From 41f6981591d789e2fa93bc4a6aa336ecee028216 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 21 Jun 2023 16:47:21 +0200 Subject: [PATCH 01/64] first version --- calendar/index.html | 16 +++++++++ calendar/package.json | 19 +++++++++++ calendar/page.js | 78 +++++++++++++++++++++++++++++++++++++++++++ calendar/screen.css | 50 +++++++++++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 calendar/index.html create mode 100644 calendar/package.json create mode 100644 calendar/page.js create mode 100644 calendar/screen.css diff --git a/calendar/index.html b/calendar/index.html new file mode 100644 index 00000000..ad5103e9 --- /dev/null +++ b/calendar/index.html @@ -0,0 +1,16 @@ + + + + + + + + + +
+ Waiting for data... +
+ + + + diff --git a/calendar/package.json b/calendar/package.json new file mode 100644 index 00000000..e7562daa --- /dev/null +++ b/calendar/package.json @@ -0,0 +1,19 @@ +{ + "name": "@gristlabs/calendar-map", + "description": "Widget for visualizing data as an calendar", + "homePage": "https://github.com/gristlabs/grist-widget", + "version": "0.0.1", + "dependencies": { + "@toast-ui/calendar": "^2.1.3" + }, + "grist": [ + { + "name": "Calendar", + "url": "https://gristlabs.github.io/grist-widget/calendar/index.html", + "widgetId": "@gristlabs/widget-calendar#calendar", + "published": true, + "accessLevel": "read table" + } + + ] +} diff --git a/calendar/page.js b/calendar/page.js new file mode 100644 index 00000000..4730fc6e --- /dev/null +++ b/calendar/page.js @@ -0,0 +1,78 @@ +function ready(fn) { + if (document.readyState !== 'loading'){ + fn(); + } else { + document.addEventListener('DOMContentLoaded', fn); + } +} + + +const options = { + week: { + taskView: false, + }, + month: {}, + defaultView: 'week', + template: { + time(event) { + const {title} = event; + + return `${title}`; + }, + allday(event) { + return `${event.title}`; + }, + }, + calendars: [ + { + id: 'cal1', + name: 'Personal', + backgroundColor: '#03bd9e', + }, + ], +} + +let Calendar +ready(function() { + const container = document.getElementById('calendar'); + // Update the widget anytime the document data changes. + Calendar = new tui.Calendar(container, options); + grist.ready({requiredAccess: 'read table'}); + grist.onRecords(updateCalendar); +}); +grist.ready({requiredAccess: 'read table'}); + +function updateCalendar(records) { + for(const record of records) { + const event = Calendar.getEvent(record.id, 'cal1'); // EventObject + if (!event) { + Calendar.createEvents([ + { + id: record.id, + calendarId: 'cal1', + title: record.A, + start: record.B, + end: record.C, + category: 'time', + state: 'Free', + isReadOnly: true, + color: '#fff', + backgroundColor: '#ccc', + customStyle: { + fontStyle: 'italic', + fontSize: '15px', + }, + }, // EventObject + ]); + } + else{ + Calendar.updateEvent(record.id, 'cal1', { + title: record.A, + start: record.B, + end: record.C, + }) + } + } +} + + diff --git a/calendar/screen.css b/calendar/screen.css new file mode 100644 index 00000000..bcbb214f --- /dev/null +++ b/calendar/screen.css @@ -0,0 +1,50 @@ +#map { + width: 100vw; + height: 100vh; +} + +html, body, #map { + margin: 0; + padding: 0; + background: + radial-gradient(#eee 3px, transparent 4px), + radial-gradient(#eee 3px, transparent 4px), + linear-gradient(#fff 4px, transparent 0), + linear-gradient(45deg, transparent 74px, transparent 75px, #a4a4a4 75px, #a4a4a4 76px, transparent 77px, transparent 109px), + linear-gradient(-45deg, transparent 75px, transparent 76px, #a4a4a4 76px, #a4a4a4 77px, transparent 78px, transparent 109px), + #fff; + background-size: 109px 109px, 109px 109px,100% 6px, 109px 109px, 109px 109px; + background-position: 54px 55px, 0px 0px, 0px 0px, 0px 0px, 0px 0px; +} + +.error { + background: red; + color: white; + padding: 2em; + margin: 2em; +} + +#settings { + position: absolute; + top: 10px; + right: 10px; + z-index: 500; + padding: 10px; + border: 1px solid lightgray; + border-radius: 5px; + display: none; + background: white; +} +#btnClose { + font-size: small; + margin-bottom: 5px; + text-align: right; + cursor: pointer; +} +#btnClose:hover { + text-decoration: underline; +} +#lblText { + min-width: 100px; + display: inline-block; +} \ No newline at end of file From f739e37a85a637e552e2327fb26fe89bbaf5d98e Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 22 Jun 2023 10:28:03 +0200 Subject: [PATCH 02/64] updating events from calendar to table --- calendar/page.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 4730fc6e..80c62d88 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -39,8 +39,21 @@ ready(function() { Calendar = new tui.Calendar(container, options); grist.ready({requiredAccess: 'read table'}); grist.onRecords(updateCalendar); + Calendar.on('beforeUpdateEvent', async (info) => { + if (info.changes) { + if (info.changes.start || info.changes.end) { + const record = await grist.fetchSelectedRecord(info.event.id) + if (record) { + const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; + const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; + const table = await grist.getTable(); + await table.update({id:record.id, fields:{B:dateFrom, C:dateTo}}) + } + } + } + }); + grist.ready({requiredAccess: 'read table'}); }); -grist.ready({requiredAccess: 'read table'}); function updateCalendar(records) { for(const record of records) { @@ -55,7 +68,6 @@ function updateCalendar(records) { end: record.C, category: 'time', state: 'Free', - isReadOnly: true, color: '#fff', backgroundColor: '#ccc', customStyle: { From 86bd58c16c59cb82e4716637d712fff2c59b3128 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 22 Jun 2023 12:19:07 +0200 Subject: [PATCH 03/64] mapping columns --- calendar/page.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 80c62d88..1272797e 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -37,7 +37,7 @@ ready(function() { const container = document.getElementById('calendar'); // Update the widget anytime the document data changes. Calendar = new tui.Calendar(container, options); - grist.ready({requiredAccess: 'read table'}); + grist.ready({requiredAccess: 'read table', columns: ['startDate', 'endDate', 'title', 'isAllDay']}); grist.onRecords(updateCalendar); Calendar.on('beforeUpdateEvent', async (info) => { if (info.changes) { @@ -55,7 +55,7 @@ ready(function() { grist.ready({requiredAccess: 'read table'}); }); -function updateCalendar(records) { +function updateCalendar(records,mappings) { for(const record of records) { const event = Calendar.getEvent(record.id, 'cal1'); // EventObject if (!event) { @@ -63,9 +63,10 @@ function updateCalendar(records) { { id: record.id, calendarId: 'cal1', - title: record.A, - start: record.B, - end: record.C, + title: record[mappings.title], + start: record[mappings.startDate], + end: record[mappings.endDate], + isAllDay: record[mappings.isAllDay], category: 'time', state: 'Free', color: '#fff', From 9ee8531db2882ba3624266b9743d7b7270405c71 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 22 Jun 2023 16:35:01 +0200 Subject: [PATCH 04/64] changing calendar perspective - day/month/week --- calendar/index.html | 12 +++- calendar/page.js | 134 +++++++++++++++++++++++++++++++------------- calendar/screen.css | 64 ++++++++------------- 3 files changed, 129 insertions(+), 81 deletions(-) diff --git a/calendar/index.html b/calendar/index.html index ad5103e9..a0b9b292 100644 --- a/calendar/index.html +++ b/calendar/index.html @@ -1,12 +1,22 @@ - + + +
+ + + + + + + +
Waiting for data...
diff --git a/calendar/page.js b/calendar/page.js index 1272797e..f6d5b33c 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -6,6 +6,40 @@ function ready(fn) { } } +const columnsMappingOptions = [ + { + name: "StartDate", // What field we will read. + title: "Start Date", // Friendly field name. + optional: false, // Is this an optional field. + type: "DateTime", // What type of column we expect. + description: "starting point of event", // Description of a field. + allowMultiple: false // Allows multiple column assignment. + }, + { + name: "EndDate", + title: "End Date", + optional: false, + type: "DateTime", + description: "ending point of event", + allowMultiple: false + }, + { + name: "Title", + title: "Title", + optional: false, + type: "Text", + description: "title of event", + allowMultiple: false + }, + { + name: "IsAllDay", + title: "Is All Day", + optional: true, + type: "Bool", + description: "is event all day long", + } +]; + const options = { week: { @@ -32,58 +66,80 @@ const options = { ], } +async function calendarViewChanges(radiobutton){ + await grist.setOption('calendarViewPerspective', radiobutton.value); +} + let Calendar ready(function() { const container = document.getElementById('calendar'); // Update the widget anytime the document data changes. Calendar = new tui.Calendar(container, options); - grist.ready({requiredAccess: 'read table', columns: ['startDate', 'endDate', 'title', 'isAllDay']}); + grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); grist.onRecords(updateCalendar); - Calendar.on('beforeUpdateEvent', async (info) => { - if (info.changes) { - if (info.changes.start || info.changes.end) { - const record = await grist.fetchSelectedRecord(info.event.id) + grist.onOptions(function (options, interaction) { + console.log(options, interaction); + if(options.calendarViewPerspective){ + Calendar.changeView(options.calendarViewPerspective); + selectRadioButton(options.calendarViewPerspective); + } + }); + Calendar.on('beforeUpdateEvent', async (info) => { + if (info.changes) { + if (info.changes.start || info.changes.end) { + const record = await grist.fetchSelectedRecord(info.event.id) if (record) { const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; - const table = await grist.getTable(); - await table.update({id:record.id, fields:{B:dateFrom, C:dateTo}}) - } - } - } + const table = await grist.getTable(); + await table.update({id: record.id, fields: {B: dateFrom, C: dateTo}}) + + } + } + } + grist.ready({requiredAccess: 'read table'}); }); - grist.ready({requiredAccess: 'read table'}); }); -function updateCalendar(records,mappings) { - for(const record of records) { - const event = Calendar.getEvent(record.id, 'cal1'); // EventObject - if (!event) { - Calendar.createEvents([ - { - id: record.id, - calendarId: 'cal1', - title: record[mappings.title], - start: record[mappings.startDate], - end: record[mappings.endDate], - isAllDay: record[mappings.isAllDay], - category: 'time', - state: 'Free', - color: '#fff', - backgroundColor: '#ccc', - customStyle: { - fontStyle: 'italic', - fontSize: '15px', - }, - }, // EventObject - ]); +function selectRadioButton(value){ + for(const element of document.getElementsByName('calendar-options')){ + if(element.value === value){ + element.checked = true; } - else{ - Calendar.updateEvent(record.id, 'cal1', { - title: record.A, - start: record.B, - end: record.C, - }) + } +} + +function updateCalendar(records,mappings) { + const mapped = grist.mapColumnNames(records, mappings); + if(mapped) { + for (const record of records) { + const event = Calendar.getEvent(record.id, 'cal1'); // EventObject + if (!event) { + Calendar.createEvents([ + { + id: record.id, + calendarId: 'cal1', + title: mapped.title, + start: mapped.startDate, + end: mapped.endDate, + isAllday: mapped.isAllDay, + category: 'time', + state: 'Free', + color: '#fff', + backgroundColor: '#ccc', + customStyle: { + fontStyle: 'italic', + fontSize: '15px', + }, + }, // EventObject + ]); + } else { + Calendar.updateEvent(record.id, 'cal1', { + title: record.A, + start: record.B, + end: record.C, + }) + } } } } diff --git a/calendar/screen.css b/calendar/screen.css index bcbb214f..68e099e8 100644 --- a/calendar/screen.css +++ b/calendar/screen.css @@ -1,50 +1,32 @@ -#map { - width: 100vw; - height: 100vh; +#calendar-options { + margin: 10px; } -html, body, #map { - margin: 0; - padding: 0; - background: - radial-gradient(#eee 3px, transparent 4px), - radial-gradient(#eee 3px, transparent 4px), - linear-gradient(#fff 4px, transparent 0), - linear-gradient(45deg, transparent 74px, transparent 75px, #a4a4a4 75px, #a4a4a4 76px, transparent 77px, transparent 109px), - linear-gradient(-45deg, transparent 75px, transparent 76px, #a4a4a4 76px, #a4a4a4 77px, transparent 78px, transparent 109px), - #fff; - background-size: 109px 109px, 109px 109px,100% 6px, 109px 109px, 109px 109px; - background-position: 54px 55px, 0px 0px, 0px 0px, 0px 0px, 0px 0px; +#calendar-options input[type="radio"] { + opacity: 0; + position: fixed; + width: 0; } -.error { - background: red; - color: white; - padding: 2em; - margin: 2em; +#calendar-options label { + display: inline-block; + background-color: #ddd; + padding: 10px 20px; + font-family: sans-serif, Arial; + font-size: 16px; + border: 2px solid #444; + border-radius: 4px; } -#settings { - position: absolute; - top: 10px; - right: 10px; - z-index: 500; - padding: 10px; - border: 1px solid lightgray; - border-radius: 5px; - display: none; - background: white; -} -#btnClose { - font-size: small; - margin-bottom: 5px; - text-align: right; - cursor: pointer; +#calendar-options label:hover { + background-color: #dfd; } -#btnClose:hover { - text-decoration: underline; + +#calendar-options input[type="radio"]:focus + label { + border: 2px dashed #444; } -#lblText { - min-width: 100px; - display: inline-block; + +#calendar-options input[type="radio"]:checked + label { + background-color: #bfb; + border-color: #4c4; } \ No newline at end of file From 3766351a735de3db4326c310b4e7c38d9815f74c Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 22 Jun 2023 16:57:16 +0200 Subject: [PATCH 05/64] typos fixes, allDayEvent support improved --- calendar/page.js | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index f6d5b33c..ea515a45 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -8,7 +8,7 @@ function ready(fn) { const columnsMappingOptions = [ { - name: "StartDate", // What field we will read. + name: "startDate", // What field we will read. title: "Start Date", // Friendly field name. optional: false, // Is this an optional field. type: "DateTime", // What type of column we expect. @@ -16,7 +16,7 @@ const columnsMappingOptions = [ allowMultiple: false // Allows multiple column assignment. }, { - name: "EndDate", + name: "endDate", title: "End Date", optional: false, type: "DateTime", @@ -24,7 +24,7 @@ const columnsMappingOptions = [ allowMultiple: false }, { - name: "Title", + name: "title", title: "Title", optional: false, type: "Text", @@ -32,7 +32,7 @@ const columnsMappingOptions = [ allowMultiple: false }, { - name: "IsAllDay", + name: "isAllDay", title: "Is All Day", optional: true, type: "Bool", @@ -78,7 +78,6 @@ ready(function() { grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); grist.onRecords(updateCalendar); grist.onOptions(function (options, interaction) { - console.log(options, interaction); if(options.calendarViewPerspective){ Calendar.changeView(options.calendarViewPerspective); selectRadioButton(options.calendarViewPerspective); @@ -97,7 +96,6 @@ ready(function() { } } } - grist.ready({requiredAccess: 'read table'}); }); }); @@ -110,19 +108,19 @@ function selectRadioButton(value){ } function updateCalendar(records,mappings) { - const mapped = grist.mapColumnNames(records, mappings); - if(mapped) { - for (const record of records) { + const mappedRecords = grist.mapColumnNames(records, mappings); + if(mappedRecords) { + for (const record of mappedRecords) { const event = Calendar.getEvent(record.id, 'cal1'); // EventObject if (!event) { Calendar.createEvents([ { id: record.id, calendarId: 'cal1', - title: mapped.title, - start: mapped.startDate, - end: mapped.endDate, - isAllday: mapped.isAllDay, + title: record.title, + start: record.startDate, + end: record.endDate, + isAllday: record.isAllDay, category: 'time', state: 'Free', color: '#fff', @@ -135,9 +133,10 @@ function updateCalendar(records,mappings) { ]); } else { Calendar.updateEvent(record.id, 'cal1', { - title: record.A, - start: record.B, - end: record.C, + title: record.title, + start: record.startDate, + end: record.endDate, + isAllday: record.isAllDay, }) } } From c215ffa3dfa63b8bddc3a9a1784991269935b0da Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Fri, 23 Jun 2023 14:01:21 +0200 Subject: [PATCH 06/64] calendar changes --- calendar/index.html | 20 +++++++++------ calendar/page.js | 12 +++++++++ calendar/screen.css | 59 ++++++++++++++++++++++++++++++++------------- 3 files changed, 67 insertions(+), 24 deletions(-) diff --git a/calendar/index.html b/calendar/index.html index a0b9b292..f9823ef9 100644 --- a/calendar/index.html +++ b/calendar/index.html @@ -9,13 +9,19 @@
- - - - - - - +
+ + + +
+
+ + + + + + +
Waiting for data... diff --git a/calendar/page.js b/calendar/page.js index ea515a45..2803b722 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -107,6 +107,18 @@ function selectRadioButton(value){ } } +function calendarPrevious(){ + Calendar.prev(); +} + +function calendarNext(){ + Calendar.next(); +} + +function calendarToday(){ + Calendar.today(); +} + function updateCalendar(records,mappings) { const mappedRecords = grist.mapColumnNames(records, mappings); if(mappedRecords) { diff --git a/calendar/screen.css b/calendar/screen.css index 68e099e8..342182d1 100644 --- a/calendar/screen.css +++ b/calendar/screen.css @@ -1,5 +1,16 @@ -#calendar-options { - margin: 10px; +body{ + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; +} + +#calendar-options{ + display:flex; + gap: 50px; + padding-bottom: 10px; +} + +#calendar-navigation-buttons,#calendar-perspective-buttons{ + display:flex; + gap: 0; } #calendar-options input[type="radio"] { @@ -8,25 +19,39 @@ width: 0; } -#calendar-options label { - display: inline-block; - background-color: #ddd; - padding: 10px 20px; - font-family: sans-serif, Arial; - font-size: 16px; - border: 2px solid #444; - border-radius: 4px; +.calendar-button{ + font-family: inherit; + font-size: 1em; + border: none; + border-top: 1px solid #11B683; + border-bottom: 1px solid #11B683; + /* border-radius: 4px; */ + letter-spacing: -0.08px; + padding: 4px 8px; + background:transparent; +} + +.calendar-button:last-of-type{ + border-right: 1px solid #11B683; + border-radius: 0 5px 5px 0; +} + +.calendar-button:first-of-type{ + border-left: 1px solid #11B683; + border-radius: 5px 0 0 5px; } -#calendar-options label:hover { - background-color: #dfd; +.calendar-button:hover{ + color: #009058; + border-color: #009058; } -#calendar-options input[type="radio"]:focus + label { - border: 2px dashed #444; +input:checked + label{ + background-color:#16B378; + color: #ffffff; + border-color:#000; } -#calendar-options input[type="radio"]:checked + label { - background-color: #bfb; - border-color: #4c4; +.toastui-calendar-day-view .toastui-calendar-panel:not(.toastui-calendar-time), .toastui-calendar-week-view .toastui-calendar-panel:not(.toastui-calendar-time) { + overflow-y: hidden; } \ No newline at end of file From c41bc496ed3944e65277f5f1b55f1437ae95d535 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Fri, 23 Jun 2023 14:57:33 +0200 Subject: [PATCH 07/64] styling, navigating to the row selected in main widget --- calendar/page.js | 30 +++++++++++++++++++++--------- calendar/screen.css | 8 +++++++- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 2803b722..a5a85e85 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -6,6 +6,12 @@ function ready(fn) { } } +let mainColor = getComputedStyle(document.documentElement) + .getPropertyValue('--main-color') + +let selectedColor = getComputedStyle(document.documentElement) + .getPropertyValue('--selected-color') + const columnsMappingOptions = [ { name: "startDate", // What field we will read. @@ -54,14 +60,14 @@ const options = { return `${title}`; }, allday(event) { - return `${event.title}`; + return `${event.title}`; }, }, calendars: [ { id: 'cal1', name: 'Personal', - backgroundColor: '#03bd9e', + backgroundColor: mainColor, }, ], } @@ -71,12 +77,24 @@ async function calendarViewChanges(radiobutton){ } let Calendar +let selectedRecordId = null; ready(function() { const container = document.getElementById('calendar'); // Update the widget anytime the document data changes. Calendar = new tui.Calendar(container, options); grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); grist.onRecords(updateCalendar); + grist.onRecord((record, mappings) => { + const mappedRecord = grist.mapColumnNames(record, mappings); + if(mappedRecord) { + Calendar.setDate(mappedRecord.startDate); + if(selectedRecordId){ + Calendar.updateEvent(selectedRecordId, 'cal1',{backgroundColor: mainColor}); + } + Calendar.updateEvent(mappedRecord.id, 'cal1',{backgroundColor: selectedColor}); + selectedRecordId = mappedRecord.id; + } + }); grist.onOptions(function (options, interaction) { if(options.calendarViewPerspective){ Calendar.changeView(options.calendarViewPerspective); @@ -135,13 +153,7 @@ function updateCalendar(records,mappings) { isAllday: record.isAllDay, category: 'time', state: 'Free', - color: '#fff', - backgroundColor: '#ccc', - customStyle: { - fontStyle: 'italic', - fontSize: '15px', - }, - }, // EventObject + }, ]); } else { Calendar.updateEvent(record.id, 'cal1', { diff --git a/calendar/screen.css b/calendar/screen.css index 342182d1..2907ef4c 100644 --- a/calendar/screen.css +++ b/calendar/screen.css @@ -1,3 +1,9 @@ +:root { + --main-color: #16B378; + --selected-color: #009058; +} + + body{ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; } @@ -47,7 +53,7 @@ body{ } input:checked + label{ - background-color:#16B378; + background-color:var(--main-color); color: #ffffff; border-color:#000; } From c02a8b274713b6f838594636128b736c610df303 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Fri, 23 Jun 2023 15:58:29 +0200 Subject: [PATCH 08/64] scroll --- calendar/page.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/calendar/page.js b/calendar/page.js index a5a85e85..0ecd7a6b 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -94,6 +94,10 @@ ready(function() { Calendar.updateEvent(mappedRecord.id, 'cal1',{backgroundColor: selectedColor}); selectedRecordId = mappedRecord.id; } + var dom = document.querySelector('.toastui-calendar-time'); + const middleHour = mappedRecord.startDate.getHours() + + (mappedRecord.endDate.getHours() - mappedRecord.startDate.getHours())/2; + dom.scrollTo({top: (dom.clientHeight/24)*middleHour, behavior: 'smooth'}); }); grist.onOptions(function (options, interaction) { if(options.calendarViewPerspective){ From d6fdaa53c5d674dc4b350f35efd7ebd7efe4f2c5 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 13 Jul 2023 16:47:57 +0200 Subject: [PATCH 09/64] deleting events, improved styles, creating new event based on selection --- calendar/index.html | 31 +- calendar/page.js | 16 + calendar/screen.css | 18 + package.json | 2 +- yarn.lock | 949 ++++++++++---------------------------------- 5 files changed, 257 insertions(+), 759 deletions(-) diff --git a/calendar/index.html b/calendar/index.html index f9823ef9..0cf1dac6 100644 --- a/calendar/index.html +++ b/calendar/index.html @@ -8,24 +8,25 @@ -
-
- - - +
+
+
+ + + +
+
+ + + + + + +
-
- - - - - - +
-
- Waiting for data... -
diff --git a/calendar/page.js b/calendar/page.js index 0ecd7a6b..facd1517 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -119,6 +119,14 @@ ready(function() { } } }); + // Registering an instance event + Calendar.on('selectDateTime', async (info) => { + const dateFrom = info.start?.valueOf() / 1000; + const dateTo = info.end?.valueOf() / 1000; + const table = await grist.getTable(); + await table.create( {fields: {B: dateFrom, C: dateTo}}) + console.log(eventObj); + }); }); function selectRadioButton(value){ @@ -141,8 +149,10 @@ function calendarToday(){ Calendar.today(); } +let previousIds= []; function updateCalendar(records,mappings) { const mappedRecords = grist.mapColumnNames(records, mappings); + if(mappedRecords) { for (const record of mappedRecords) { const event = Calendar.getEvent(record.id, 'cal1'); // EventObject @@ -168,6 +178,12 @@ function updateCalendar(records,mappings) { }) } } + for (const id of previousIds) { + if (!mappedRecords.find(record => record.id === id)) { + Calendar.deleteEvent(id, 'cal1'); + } + } + previousIds = new Set(mappedRecords.map(record => record.id)); } } diff --git a/calendar/screen.css b/calendar/screen.css index 2907ef4c..20ebf5e0 100644 --- a/calendar/screen.css +++ b/calendar/screen.css @@ -25,6 +25,10 @@ body{ width: 0; } +.toastui-calendar-timegrid{ + height: 100%; +} + .calendar-button{ font-family: inherit; font-size: 1em; @@ -60,4 +64,18 @@ input:checked + label{ .toastui-calendar-day-view .toastui-calendar-panel:not(.toastui-calendar-time), .toastui-calendar-week-view .toastui-calendar-panel:not(.toastui-calendar-time) { overflow-y: hidden; +} + +#calendar-container { + display: flex; + flex-direction: column; + gap: 10px; + height: 100%; +} + +#calendar{ + flex: 1; + min-height: 600px; + flex-shrink: 0; + background-color: #ff0000; } \ No newline at end of file diff --git a/package.json b/package.json index 37f035ad..b7726f7c 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "dev": "echo 'Starting local server and watching for changes.\nStart Grist with an environmental variable GRIST_WIDGET_LIST_URL=http://localhost:8585/manifest.json' && npm run watch 1> /dev/null & npm run serve:dev 1> /dev/null" }, "devDependencies": { - "live-server": "^1.2.1", + "live-server": "1.2.1", "nodemon": "^2.0.15" } } diff --git a/yarn.lock b/yarn.lock index 9e6b8491..9f5ee120 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,49 +2,18 @@ # yarn lockfile v1 -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== accepts@~1.3.4: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -ansi-align@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" - integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== - dependencies: - string-width "^4.1.0" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - color-convert "^2.0.1" + mime-types "~2.1.34" + negotiator "0.6.3" anymatch@^2.0.0: version "2.0.0" @@ -55,29 +24,29 @@ anymatch@^2.0.0: normalize-path "^2.1.1" anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" apache-crypt@^1.1.2: - version "1.2.5" - resolved "https://registry.yarnpkg.com/apache-crypt/-/apache-crypt-1.2.5.tgz#4eb6b6dbaed2041ce5bc2d802f4421f5fdadc25e" - integrity sha512-ICnYQH+DFVmw+S4Q0QY2XRXD8Ne8ewh8HgbuFH4K7022zCxgHM0Hz1xkRnUlEfAXNbwp1Cnhbedu60USIfDxvg== + version "1.2.6" + resolved "https://registry.yarnpkg.com/apache-crypt/-/apache-crypt-1.2.6.tgz#c3f9b98318b447f0a878b54e2cb113bbb8539698" + integrity sha512-072WetlM4blL8PREJVeY+WHiUh1R5VNt2HfceGS8aKqttPHcmqE5pkKuXPz/ULmJOFkc8Hw3kfKl6vy7Qka6DA== dependencies: unix-crypt-td-js "^1.1.4" apache-md5@^1.0.6: - version "1.1.7" - resolved "https://registry.yarnpkg.com/apache-md5/-/apache-md5-1.1.7.tgz#dcef1802700cc231d60c5e08fd088f2f9b36375a" - integrity sha512-JtHjzZmJxtzfTSjsCyHgPR155HBe5WGyUyHTaEkfy46qhwCFKx1Epm6nAxgUG3WfUZP1dWhGqj9Z2NOBeZ+uBw== + version "1.1.8" + resolved "https://registry.yarnpkg.com/apache-md5/-/apache-md5-1.1.8.tgz#ea79c6feb03abfed42b2830dde06f75df5e3bbd9" + integrity sha512-FCAJojipPn0bXjuEpjOOOMN8FZDkxfWWp4JGN9mifU2IhxvKyXZYqpzPHdnTSUpmPDy+tsslB6Z1g+Vg6nVbYA== arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== arr-flatten@^1.1.0: version "1.1.0" @@ -87,22 +56,22 @@ arr-flatten@^1.1.0: arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + version "1.0.6" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.6.tgz#52f1d9403818c179b7561e11a5d1b77eb2160e77" + integrity sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg== atob@^2.1.2: version "2.1.2" @@ -137,12 +106,12 @@ basic-auth@~2.0.1: batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== bcryptjs@^2.3.0: version "2.4.3" resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" - integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms= + integrity sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ== binary-extensions@^1.0.0: version "1.13.1" @@ -161,20 +130,6 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -boxen@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" - integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^6.2.0" - chalk "^4.1.0" - cli-boxes "^2.2.1" - string-width "^4.2.2" - type-fest "^0.20.2" - widest-line "^3.1.0" - wrap-ansi "^7.0.0" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -221,32 +176,6 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -camelcase@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.1.tgz#250fd350cfd555d0d2160b1d51510eaf8326e86e" - integrity sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA== - -chalk@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - chokidar@^2.0.4: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -267,9 +196,9 @@ chokidar@^2.0.4: fsevents "^1.2.7" chokidar@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -281,11 +210,6 @@ chokidar@^3.5.2: optionalDependencies: fsevents "~2.3.2" -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -296,38 +220,14 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -cli-boxes@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" - integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== dependencies: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - colors@latest: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" @@ -341,19 +241,7 @@ component-emitter@^1.2.1: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -configstore@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" - integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== - dependencies: - dot-prop "^5.2.0" - graceful-fs "^4.1.2" - make-dir "^3.0.0" - unique-string "^2.0.0" - write-file-atomic "^3.0.0" - xdg-basedir "^4.0.0" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== connect@^3.6.6: version "3.7.0" @@ -368,7 +256,7 @@ connect@^3.6.6: copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== core-util-is@~1.0.0: version "1.0.3" @@ -383,11 +271,6 @@ cors@latest: object-assign "^4" vary "^1" -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -403,38 +286,21 @@ debug@^3.2.7: ms "^2.1.1" decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== dependencies: is-descriptor "^1.0.0" @@ -446,32 +312,20 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -depd@~2.0.0: +depd@2.0.0, depd@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -dot-prop@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" - integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== - dependencies: - is-obj "^2.0.0" +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== duplexer@~0.1.1: version "0.1.2" @@ -481,44 +335,27 @@ duplexer@~0.1.1: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -escape-goat@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" - integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== event-stream@3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= + integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g== dependencies: duplexer "~0.1.1" from "~0" @@ -531,7 +368,7 @@ event-stream@3.3.4: expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -544,14 +381,14 @@ expand-brackets@^2.1.4: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -585,7 +422,7 @@ file-uri-to-path@1.0.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -615,24 +452,24 @@ finalhandler@1.1.2: for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= + integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g== fsevents@^1.2.7: version "1.2.13" @@ -647,29 +484,15 @@ fsevents@~2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + integrity sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA== dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" @@ -681,49 +504,20 @@ glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -global-dirs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" - integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== - dependencies: - ini "2.0.0" - -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -graceful-fs@^4.1.11, graceful-fs@^4.1.2: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +graceful-fs@^4.1.11: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -732,7 +526,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -741,101 +535,71 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== dependencies: is-number "^3.0.0" kind-of "^4.0.0" -has-yarn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" - integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== - http-auth@3.1.x: version "3.1.3" resolved "https://registry.yarnpkg.com/http-auth/-/http-auth-3.1.3.tgz#945cfadd66521eaf8f7c84913d377d7b15f24e31" - integrity sha1-lFz63WZSHq+PfISRPTd9exXyTjE= + integrity sha512-Jbx0+ejo2IOx+cRUYAGS1z6RGc6JfYUNkysZM4u4Sfk1uLlGv814F7/PIjQQAuThLdAWxb74JMGd5J8zex1VQg== dependencies: apache-crypt "^1.1.2" apache-md5 "^1.0.6" bcryptjs "^2.3.0" uuid "^3.0.0" -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" http-errors@~1.6.2: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== dependencies: depd "~1.1.2" inherits "2.0.3" setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-parser-js@>=0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5" - integrity sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA== + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= - -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - -ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== dependencies: kind-of "^3.0.2" @@ -849,7 +613,7 @@ is-accessor-descriptor@^1.0.0: is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + integrity sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q== dependencies: binary-extensions "^1.0.0" @@ -865,17 +629,10 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== dependencies: kind-of "^3.0.2" @@ -907,7 +664,7 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== is-extendable@^1.0.1: version "1.0.1" @@ -919,17 +676,12 @@ is-extendable@^1.0.1: is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + integrity sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw== dependencies: is-extglob "^2.1.0" @@ -940,23 +692,10 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-installed-globally@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" - integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== - dependencies: - global-dirs "^3.0.0" - is-path-inside "^3.0.2" - -is-npm@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" - integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== - is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== dependencies: kind-of "^3.0.2" @@ -965,16 +704,6 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-path-inside@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -982,11 +711,6 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-typedarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -995,53 +719,36 @@ is-windows@^1.0.2: is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - -is-yarn-global@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" - integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== dependencies: is-buffer "^1.1.5" @@ -1055,14 +762,7 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -latest-version@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" - integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== - dependencies: - package-json "^6.3.0" - -live-server@^1.2.1: +live-server@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/live-server/-/live-server-1.2.1.tgz#670630dd409d22fe9c513ab1c1894686c757153e" integrity sha512-Yn2XCVjErTkqnM3FfTmM7/kWy3zP7+cEtC7x6u+wUzlQ+1UW3zEYbbyJrc0jNDwiMDZI0m4a0i3dxlGHVyXczw== @@ -1081,44 +781,20 @@ live-server@^1.2.1: send latest serve-index "^1.9.1" -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= + integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g== map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== dependencies: object-visit "^1.0.0" @@ -1141,40 +817,30 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@~2.1.17, mime-types@~2.1.24: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== +mime-types@~2.1.17, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: - mime-db "1.51.0" + mime-db "1.52.0" mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== +minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -1197,22 +863,17 @@ morgan@^1.9.1: ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@^2.1.1: +ms@2.1.3, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== nan@^2.12.1: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== nanomatch@^1.2.9: version "1.2.13" @@ -1231,38 +892,38 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== nodemon@^2.0.15: - version "2.0.15" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.15.tgz#504516ce3b43d9dc9a955ccd9ec57550a31a8d4e" - integrity sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA== + version "2.0.22" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.22.tgz#182c45c3a78da486f673d6c1702e00728daf5258" + integrity sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ== dependencies: chokidar "^3.5.2" debug "^3.2.7" ignore-by-default "^1.0.1" - minimatch "^3.0.4" + minimatch "^3.1.2" pstree.remy "^1.1.8" semver "^5.7.1" + simple-update-notifier "^1.0.7" supports-color "^5.5.0" touch "^3.1.0" undefsafe "^2.0.5" - update-notifier "^5.1.0" nopt@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= + integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== dependencies: abbrev "1" normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== dependencies: remove-trailing-separator "^1.0.1" @@ -1271,20 +932,15 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - object-assign@^4, object-assign@latest: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" @@ -1293,21 +949,28 @@ object-copy@^0.1.0: object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== dependencies: isobject "^3.0.0" object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== dependencies: isobject "^3.0.1" +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== dependencies: ee-first "1.1.1" @@ -1316,13 +979,6 @@ on-headers@~1.0.2: resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== -once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - opn@latest: version "6.0.0" resolved "https://registry.yarnpkg.com/opn/-/opn-6.0.0.tgz#3c5b0db676d5f97da1233d1ed42d182bc5a27d2d" @@ -1330,21 +986,6 @@ opn@latest: dependencies: is-wsl "^1.1.0" -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -package-json@^6.3.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" - integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== - dependencies: - got "^9.6.0" - registry-auth-token "^4.0.0" - registry-url "^5.0.0" - semver "^6.2.0" - parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -1353,39 +994,34 @@ parseurl@~1.3.2, parseurl@~1.3.3: pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q== path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== pause-stream@0.0.11: version "0.0.11" resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= + integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== dependencies: through "~2.3" picomatch@^2.0.4, picomatch@^2.2.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== process-nextick-args@~2.0.0: version "2.0.1" @@ -1395,47 +1031,22 @@ process-nextick-args@~2.0.0: proxy-middleware@latest: version "0.15.0" resolved "https://registry.yarnpkg.com/proxy-middleware/-/proxy-middleware-0.15.0.tgz#a3fdf1befb730f951965872ac2f6074c61477a56" - integrity sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY= + integrity sha512-EGCG8SeoIRVMhsqHQUdDigB2i7qU7fCsWASwn54+nPutYO8n4q6EiwMzyfWlC+dzRFExP+kvcnDFdBDHoZBU7Q== pstree.remy@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pupa@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" - integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== - dependencies: - escape-goat "^2.0.0" - range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -rc@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - readable-stream@^2.0.2: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -1469,24 +1080,10 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== - dependencies: - rc "^1.2.8" - -registry-url@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" - integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== - dependencies: - rc "^1.2.8" - remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== repeat-element@^1.1.2: version "1.1.4" @@ -1496,19 +1093,12 @@ repeat-element@^1.1.2: repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== ret@~0.1.10: version "0.1.15" @@ -1528,57 +1118,43 @@ safe-buffer@>=5.1.0: safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== dependencies: ret "~0.1.10" -semver-diff@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" - integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== - dependencies: - semver "^6.3.0" - semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.4: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" +semver@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== send@latest: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" + depd "2.0.0" + destroy "1.2.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "~1.7.2" + http-errors "2.0.0" mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" + ms "2.1.3" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" serve-index@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== dependencies: accepts "~1.3.4" batch "0.6.1" @@ -1603,15 +1179,17 @@ setprototypeof@1.1.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -signal-exit@^3.0.2: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== +simple-update-notifier@^1.0.7: + version "1.1.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82" + integrity sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg== + dependencies: + semver "~7.0.0" snapdragon-node@^2.0.1: version "2.1.1" @@ -1662,7 +1240,7 @@ source-map-url@^0.4.0: source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -1674,39 +1252,35 @@ split-string@^3.0.1, split-string@^3.0.2: split@0.3: version "0.3.3" resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= + integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA== dependencies: through "2" static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== dependencies: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== stream-combiner@~0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= + integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw== dependencies: duplexer "~0.1.1" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -1714,18 +1288,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -1733,34 +1295,22 @@ supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - through@2, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== dependencies: kind-of "^3.0.2" -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -1782,10 +1332,10 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== touch@^3.1.0: version "3.1.0" @@ -1794,18 +1344,6 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - undefsafe@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" @@ -1821,13 +1359,6 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" - unix-crypt-td-js@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz#4912dfad1c8aeb7d20fa0a39e4c31918c1d5d5dd" @@ -1836,12 +1367,12 @@ unix-crypt-td-js@^1.1.4: unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -1851,37 +1382,10 @@ upath@^1.1.1: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== -update-notifier@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" - integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== - dependencies: - boxen "^5.0.0" - chalk "^4.1.0" - configstore "^5.0.1" - has-yarn "^2.1.0" - import-lazy "^2.1.0" - is-ci "^2.0.0" - is-installed-globally "^0.4.0" - is-npm "^5.0.0" - is-yarn-global "^0.3.0" - latest-version "^5.1.0" - pupa "^2.1.1" - semver "^7.3.4" - semver-diff "^3.1.1" - xdg-basedir "^4.0.0" - urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== use@^3.1.0: version "3.1.1" @@ -1891,12 +1395,12 @@ use@^3.1.0: util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@^3.0.0: version "3.4.0" @@ -1906,7 +1410,7 @@ uuid@^3.0.0: vary@^1: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== websocket-driver@>=0.5.1: version "0.7.4" @@ -1921,44 +1425,3 @@ websocket-extensions@>=0.1.1: version "0.1.4" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== From 1a3b9b8654e1e58489e2ffff65d63d27e2e0ac98 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Mon, 17 Jul 2023 13:24:56 +0200 Subject: [PATCH 10/64] calendar widget being selectable as linking source. --- calendar/page.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index facd1517..3e5e26c4 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -82,7 +82,7 @@ ready(function() { const container = document.getElementById('calendar'); // Update the widget anytime the document data changes. Calendar = new tui.Calendar(container, options); - grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); + grist.allowSelectBy(); grist.onRecords(updateCalendar); grist.onRecord((record, mappings) => { const mappedRecord = grist.mapColumnNames(record, mappings); @@ -119,14 +119,19 @@ ready(function() { } } }); + Calendar.on('clickEvent', async (info) => { + grist.setSelectedRows([info.event.id]); + }); // Registering an instance event Calendar.on('selectDateTime', async (info) => { const dateFrom = info.start?.valueOf() / 1000; const dateTo = info.end?.valueOf() / 1000; const table = await grist.getTable(); - await table.create( {fields: {B: dateFrom, C: dateTo}}) - console.log(eventObj); + await table.create( {fields: {B: dateFrom, C: dateTo, "Is_All_Day_": info.isAllday?1:0, A: "New Event"}}) + Calendar.clearGridSelections(); }); + grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); + }); function selectRadioButton(value){ From 6b2a30cb27c559d01cbe2f9f45f3fa0560b070d2 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Mon, 17 Jul 2023 16:02:37 +0200 Subject: [PATCH 11/64] saving edited event is now independent of columns name (based on mapping) --- calendar/page.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/calendar/page.js b/calendar/page.js index 3e5e26c4..3d857b98 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -76,6 +76,15 @@ async function calendarViewChanges(radiobutton){ await grist.setOption('calendarViewPerspective', radiobutton.value); } +function mapCalendarEventToGristObject(event){ + const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; + const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; + const recordToMap = {id: record.id, startDate: dateFrom, endDate: dateTo, title: info.event.title, isAllDay: info.event.isAllday}; + const mappedRecord = grist.mapColumnNamesBack(recordToMap); + delete mappedRecord.id; + return{id:record.id, fields: mappedRecord }; +} + let Calendar let selectedRecordId = null; ready(function() { @@ -113,7 +122,10 @@ ready(function() { const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; const table = await grist.getTable(); - await table.update({id: record.id, fields: {B: dateFrom, C: dateTo}}) + const recordToMap = {id: record.id, startDate: dateFrom, endDate: dateTo, title: info.event.title, isAllDay: info.event.isAllday}; + const mappedRecord = grist.mapColumnNamesBack(recordToMap); + delete mappedRecord.id; + await table.update({id:record.id, fields: mappedRecord }); } } From 9ab1af5d31aeb387068aa3155efe81c5f67aba9a Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Mon, 17 Jul 2023 17:10:42 +0200 Subject: [PATCH 12/64] creeating new events can handle any column names now --- calendar/page.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 3d857b98..1862d75e 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -77,12 +77,9 @@ async function calendarViewChanges(radiobutton){ } function mapCalendarEventToGristObject(event){ - const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; - const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; - const recordToMap = {id: record.id, startDate: dateFrom, endDate: dateTo, title: info.event.title, isAllDay: info.event.isAllday}; - const mappedRecord = grist.mapColumnNamesBack(recordToMap); + const mappedRecord = grist.mapColumnNamesBack(event); delete mappedRecord.id; - return{id:record.id, fields: mappedRecord }; + return{id:event.id, fields: mappedRecord }; } let Calendar @@ -119,13 +116,16 @@ ready(function() { if (info.changes.start || info.changes.end) { const record = await grist.fetchSelectedRecord(info.event.id) if (record) { - const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; - const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; + const gristEvent ={ + startDate:(info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000, + endDate: (info.changes.end?.valueOf() ?? info.event.end.valueOf()) / 1000, + isAllday: info.changes.isAllday ?? info.event.isAllday, + title: info.changes.title ?? info.event.title, + id: record.id, + } + const mappedRecord = mapCalendarEventToGristObject(gristEvent); const table = await grist.getTable(); - const recordToMap = {id: record.id, startDate: dateFrom, endDate: dateTo, title: info.event.title, isAllDay: info.event.isAllday}; - const mappedRecord = grist.mapColumnNamesBack(recordToMap); - delete mappedRecord.id; - await table.update({id:record.id, fields: mappedRecord }); + await table.update(mappedRecord); } } @@ -136,10 +136,15 @@ ready(function() { }); // Registering an instance event Calendar.on('selectDateTime', async (info) => { - const dateFrom = info.start?.valueOf() / 1000; - const dateTo = info.end?.valueOf() / 1000; + const gristEvent ={ + startDate:info.start?.valueOf() / 1000, + endDate: info.end?.valueOf() / 1000, + isAllDay: info.isAllday?1:0, + title: "New Event" + } + const table = await grist.getTable(); - await table.create( {fields: {B: dateFrom, C: dateTo, "Is_All_Day_": info.isAllday?1:0, A: "New Event"}}) + await table.create(mapCalendarEventToGristObject(gristEvent)); Calendar.clearGridSelections(); }); grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); From ad5065c4d2dd82de18ca0286f825a16dc3d4cdbe Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 21 Jun 2023 16:47:21 +0200 Subject: [PATCH 13/64] first version --- calendar/index.html | 16 +++++++++ calendar/package.json | 19 +++++++++++ calendar/page.js | 78 +++++++++++++++++++++++++++++++++++++++++++ calendar/screen.css | 50 +++++++++++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 calendar/index.html create mode 100644 calendar/package.json create mode 100644 calendar/page.js create mode 100644 calendar/screen.css diff --git a/calendar/index.html b/calendar/index.html new file mode 100644 index 00000000..ad5103e9 --- /dev/null +++ b/calendar/index.html @@ -0,0 +1,16 @@ + + + + + + + + + +
+ Waiting for data... +
+ + + + diff --git a/calendar/package.json b/calendar/package.json new file mode 100644 index 00000000..e7562daa --- /dev/null +++ b/calendar/package.json @@ -0,0 +1,19 @@ +{ + "name": "@gristlabs/calendar-map", + "description": "Widget for visualizing data as an calendar", + "homePage": "https://github.com/gristlabs/grist-widget", + "version": "0.0.1", + "dependencies": { + "@toast-ui/calendar": "^2.1.3" + }, + "grist": [ + { + "name": "Calendar", + "url": "https://gristlabs.github.io/grist-widget/calendar/index.html", + "widgetId": "@gristlabs/widget-calendar#calendar", + "published": true, + "accessLevel": "read table" + } + + ] +} diff --git a/calendar/page.js b/calendar/page.js new file mode 100644 index 00000000..4730fc6e --- /dev/null +++ b/calendar/page.js @@ -0,0 +1,78 @@ +function ready(fn) { + if (document.readyState !== 'loading'){ + fn(); + } else { + document.addEventListener('DOMContentLoaded', fn); + } +} + + +const options = { + week: { + taskView: false, + }, + month: {}, + defaultView: 'week', + template: { + time(event) { + const {title} = event; + + return `${title}`; + }, + allday(event) { + return `${event.title}`; + }, + }, + calendars: [ + { + id: 'cal1', + name: 'Personal', + backgroundColor: '#03bd9e', + }, + ], +} + +let Calendar +ready(function() { + const container = document.getElementById('calendar'); + // Update the widget anytime the document data changes. + Calendar = new tui.Calendar(container, options); + grist.ready({requiredAccess: 'read table'}); + grist.onRecords(updateCalendar); +}); +grist.ready({requiredAccess: 'read table'}); + +function updateCalendar(records) { + for(const record of records) { + const event = Calendar.getEvent(record.id, 'cal1'); // EventObject + if (!event) { + Calendar.createEvents([ + { + id: record.id, + calendarId: 'cal1', + title: record.A, + start: record.B, + end: record.C, + category: 'time', + state: 'Free', + isReadOnly: true, + color: '#fff', + backgroundColor: '#ccc', + customStyle: { + fontStyle: 'italic', + fontSize: '15px', + }, + }, // EventObject + ]); + } + else{ + Calendar.updateEvent(record.id, 'cal1', { + title: record.A, + start: record.B, + end: record.C, + }) + } + } +} + + diff --git a/calendar/screen.css b/calendar/screen.css new file mode 100644 index 00000000..bcbb214f --- /dev/null +++ b/calendar/screen.css @@ -0,0 +1,50 @@ +#map { + width: 100vw; + height: 100vh; +} + +html, body, #map { + margin: 0; + padding: 0; + background: + radial-gradient(#eee 3px, transparent 4px), + radial-gradient(#eee 3px, transparent 4px), + linear-gradient(#fff 4px, transparent 0), + linear-gradient(45deg, transparent 74px, transparent 75px, #a4a4a4 75px, #a4a4a4 76px, transparent 77px, transparent 109px), + linear-gradient(-45deg, transparent 75px, transparent 76px, #a4a4a4 76px, #a4a4a4 77px, transparent 78px, transparent 109px), + #fff; + background-size: 109px 109px, 109px 109px,100% 6px, 109px 109px, 109px 109px; + background-position: 54px 55px, 0px 0px, 0px 0px, 0px 0px, 0px 0px; +} + +.error { + background: red; + color: white; + padding: 2em; + margin: 2em; +} + +#settings { + position: absolute; + top: 10px; + right: 10px; + z-index: 500; + padding: 10px; + border: 1px solid lightgray; + border-radius: 5px; + display: none; + background: white; +} +#btnClose { + font-size: small; + margin-bottom: 5px; + text-align: right; + cursor: pointer; +} +#btnClose:hover { + text-decoration: underline; +} +#lblText { + min-width: 100px; + display: inline-block; +} \ No newline at end of file From 06fa897d320c5e447461b1f7bf0a550a52846f71 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 22 Jun 2023 10:28:03 +0200 Subject: [PATCH 14/64] updating events from calendar to table --- calendar/page.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 4730fc6e..80c62d88 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -39,8 +39,21 @@ ready(function() { Calendar = new tui.Calendar(container, options); grist.ready({requiredAccess: 'read table'}); grist.onRecords(updateCalendar); + Calendar.on('beforeUpdateEvent', async (info) => { + if (info.changes) { + if (info.changes.start || info.changes.end) { + const record = await grist.fetchSelectedRecord(info.event.id) + if (record) { + const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; + const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; + const table = await grist.getTable(); + await table.update({id:record.id, fields:{B:dateFrom, C:dateTo}}) + } + } + } + }); + grist.ready({requiredAccess: 'read table'}); }); -grist.ready({requiredAccess: 'read table'}); function updateCalendar(records) { for(const record of records) { @@ -55,7 +68,6 @@ function updateCalendar(records) { end: record.C, category: 'time', state: 'Free', - isReadOnly: true, color: '#fff', backgroundColor: '#ccc', customStyle: { From ce02e71732b833d4bf2eeb047a8e574b13ec7f30 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 22 Jun 2023 12:19:07 +0200 Subject: [PATCH 15/64] mapping columns --- calendar/page.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 80c62d88..1272797e 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -37,7 +37,7 @@ ready(function() { const container = document.getElementById('calendar'); // Update the widget anytime the document data changes. Calendar = new tui.Calendar(container, options); - grist.ready({requiredAccess: 'read table'}); + grist.ready({requiredAccess: 'read table', columns: ['startDate', 'endDate', 'title', 'isAllDay']}); grist.onRecords(updateCalendar); Calendar.on('beforeUpdateEvent', async (info) => { if (info.changes) { @@ -55,7 +55,7 @@ ready(function() { grist.ready({requiredAccess: 'read table'}); }); -function updateCalendar(records) { +function updateCalendar(records,mappings) { for(const record of records) { const event = Calendar.getEvent(record.id, 'cal1'); // EventObject if (!event) { @@ -63,9 +63,10 @@ function updateCalendar(records) { { id: record.id, calendarId: 'cal1', - title: record.A, - start: record.B, - end: record.C, + title: record[mappings.title], + start: record[mappings.startDate], + end: record[mappings.endDate], + isAllDay: record[mappings.isAllDay], category: 'time', state: 'Free', color: '#fff', From 8dd89c12e217efedca35ca12c7ca6f9720f9b78d Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 22 Jun 2023 16:35:01 +0200 Subject: [PATCH 16/64] changing calendar perspective - day/month/week --- calendar/index.html | 12 +++- calendar/page.js | 134 +++++++++++++++++++++++++++++++------------- calendar/screen.css | 64 ++++++++------------- 3 files changed, 129 insertions(+), 81 deletions(-) diff --git a/calendar/index.html b/calendar/index.html index ad5103e9..a0b9b292 100644 --- a/calendar/index.html +++ b/calendar/index.html @@ -1,12 +1,22 @@ - + + +
+ + + + + + + +
Waiting for data...
diff --git a/calendar/page.js b/calendar/page.js index 1272797e..f6d5b33c 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -6,6 +6,40 @@ function ready(fn) { } } +const columnsMappingOptions = [ + { + name: "StartDate", // What field we will read. + title: "Start Date", // Friendly field name. + optional: false, // Is this an optional field. + type: "DateTime", // What type of column we expect. + description: "starting point of event", // Description of a field. + allowMultiple: false // Allows multiple column assignment. + }, + { + name: "EndDate", + title: "End Date", + optional: false, + type: "DateTime", + description: "ending point of event", + allowMultiple: false + }, + { + name: "Title", + title: "Title", + optional: false, + type: "Text", + description: "title of event", + allowMultiple: false + }, + { + name: "IsAllDay", + title: "Is All Day", + optional: true, + type: "Bool", + description: "is event all day long", + } +]; + const options = { week: { @@ -32,58 +66,80 @@ const options = { ], } +async function calendarViewChanges(radiobutton){ + await grist.setOption('calendarViewPerspective', radiobutton.value); +} + let Calendar ready(function() { const container = document.getElementById('calendar'); // Update the widget anytime the document data changes. Calendar = new tui.Calendar(container, options); - grist.ready({requiredAccess: 'read table', columns: ['startDate', 'endDate', 'title', 'isAllDay']}); + grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); grist.onRecords(updateCalendar); - Calendar.on('beforeUpdateEvent', async (info) => { - if (info.changes) { - if (info.changes.start || info.changes.end) { - const record = await grist.fetchSelectedRecord(info.event.id) + grist.onOptions(function (options, interaction) { + console.log(options, interaction); + if(options.calendarViewPerspective){ + Calendar.changeView(options.calendarViewPerspective); + selectRadioButton(options.calendarViewPerspective); + } + }); + Calendar.on('beforeUpdateEvent', async (info) => { + if (info.changes) { + if (info.changes.start || info.changes.end) { + const record = await grist.fetchSelectedRecord(info.event.id) if (record) { const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; - const table = await grist.getTable(); - await table.update({id:record.id, fields:{B:dateFrom, C:dateTo}}) - } - } - } + const table = await grist.getTable(); + await table.update({id: record.id, fields: {B: dateFrom, C: dateTo}}) + + } + } + } + grist.ready({requiredAccess: 'read table'}); }); - grist.ready({requiredAccess: 'read table'}); }); -function updateCalendar(records,mappings) { - for(const record of records) { - const event = Calendar.getEvent(record.id, 'cal1'); // EventObject - if (!event) { - Calendar.createEvents([ - { - id: record.id, - calendarId: 'cal1', - title: record[mappings.title], - start: record[mappings.startDate], - end: record[mappings.endDate], - isAllDay: record[mappings.isAllDay], - category: 'time', - state: 'Free', - color: '#fff', - backgroundColor: '#ccc', - customStyle: { - fontStyle: 'italic', - fontSize: '15px', - }, - }, // EventObject - ]); +function selectRadioButton(value){ + for(const element of document.getElementsByName('calendar-options')){ + if(element.value === value){ + element.checked = true; } - else{ - Calendar.updateEvent(record.id, 'cal1', { - title: record.A, - start: record.B, - end: record.C, - }) + } +} + +function updateCalendar(records,mappings) { + const mapped = grist.mapColumnNames(records, mappings); + if(mapped) { + for (const record of records) { + const event = Calendar.getEvent(record.id, 'cal1'); // EventObject + if (!event) { + Calendar.createEvents([ + { + id: record.id, + calendarId: 'cal1', + title: mapped.title, + start: mapped.startDate, + end: mapped.endDate, + isAllday: mapped.isAllDay, + category: 'time', + state: 'Free', + color: '#fff', + backgroundColor: '#ccc', + customStyle: { + fontStyle: 'italic', + fontSize: '15px', + }, + }, // EventObject + ]); + } else { + Calendar.updateEvent(record.id, 'cal1', { + title: record.A, + start: record.B, + end: record.C, + }) + } } } } diff --git a/calendar/screen.css b/calendar/screen.css index bcbb214f..68e099e8 100644 --- a/calendar/screen.css +++ b/calendar/screen.css @@ -1,50 +1,32 @@ -#map { - width: 100vw; - height: 100vh; +#calendar-options { + margin: 10px; } -html, body, #map { - margin: 0; - padding: 0; - background: - radial-gradient(#eee 3px, transparent 4px), - radial-gradient(#eee 3px, transparent 4px), - linear-gradient(#fff 4px, transparent 0), - linear-gradient(45deg, transparent 74px, transparent 75px, #a4a4a4 75px, #a4a4a4 76px, transparent 77px, transparent 109px), - linear-gradient(-45deg, transparent 75px, transparent 76px, #a4a4a4 76px, #a4a4a4 77px, transparent 78px, transparent 109px), - #fff; - background-size: 109px 109px, 109px 109px,100% 6px, 109px 109px, 109px 109px; - background-position: 54px 55px, 0px 0px, 0px 0px, 0px 0px, 0px 0px; +#calendar-options input[type="radio"] { + opacity: 0; + position: fixed; + width: 0; } -.error { - background: red; - color: white; - padding: 2em; - margin: 2em; +#calendar-options label { + display: inline-block; + background-color: #ddd; + padding: 10px 20px; + font-family: sans-serif, Arial; + font-size: 16px; + border: 2px solid #444; + border-radius: 4px; } -#settings { - position: absolute; - top: 10px; - right: 10px; - z-index: 500; - padding: 10px; - border: 1px solid lightgray; - border-radius: 5px; - display: none; - background: white; -} -#btnClose { - font-size: small; - margin-bottom: 5px; - text-align: right; - cursor: pointer; +#calendar-options label:hover { + background-color: #dfd; } -#btnClose:hover { - text-decoration: underline; + +#calendar-options input[type="radio"]:focus + label { + border: 2px dashed #444; } -#lblText { - min-width: 100px; - display: inline-block; + +#calendar-options input[type="radio"]:checked + label { + background-color: #bfb; + border-color: #4c4; } \ No newline at end of file From df8d4f71bddeadb3c387b49d90de09784b40715b Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 22 Jun 2023 16:57:16 +0200 Subject: [PATCH 17/64] typos fixes, allDayEvent support improved --- calendar/page.js | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index f6d5b33c..ea515a45 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -8,7 +8,7 @@ function ready(fn) { const columnsMappingOptions = [ { - name: "StartDate", // What field we will read. + name: "startDate", // What field we will read. title: "Start Date", // Friendly field name. optional: false, // Is this an optional field. type: "DateTime", // What type of column we expect. @@ -16,7 +16,7 @@ const columnsMappingOptions = [ allowMultiple: false // Allows multiple column assignment. }, { - name: "EndDate", + name: "endDate", title: "End Date", optional: false, type: "DateTime", @@ -24,7 +24,7 @@ const columnsMappingOptions = [ allowMultiple: false }, { - name: "Title", + name: "title", title: "Title", optional: false, type: "Text", @@ -32,7 +32,7 @@ const columnsMappingOptions = [ allowMultiple: false }, { - name: "IsAllDay", + name: "isAllDay", title: "Is All Day", optional: true, type: "Bool", @@ -78,7 +78,6 @@ ready(function() { grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); grist.onRecords(updateCalendar); grist.onOptions(function (options, interaction) { - console.log(options, interaction); if(options.calendarViewPerspective){ Calendar.changeView(options.calendarViewPerspective); selectRadioButton(options.calendarViewPerspective); @@ -97,7 +96,6 @@ ready(function() { } } } - grist.ready({requiredAccess: 'read table'}); }); }); @@ -110,19 +108,19 @@ function selectRadioButton(value){ } function updateCalendar(records,mappings) { - const mapped = grist.mapColumnNames(records, mappings); - if(mapped) { - for (const record of records) { + const mappedRecords = grist.mapColumnNames(records, mappings); + if(mappedRecords) { + for (const record of mappedRecords) { const event = Calendar.getEvent(record.id, 'cal1'); // EventObject if (!event) { Calendar.createEvents([ { id: record.id, calendarId: 'cal1', - title: mapped.title, - start: mapped.startDate, - end: mapped.endDate, - isAllday: mapped.isAllDay, + title: record.title, + start: record.startDate, + end: record.endDate, + isAllday: record.isAllDay, category: 'time', state: 'Free', color: '#fff', @@ -135,9 +133,10 @@ function updateCalendar(records,mappings) { ]); } else { Calendar.updateEvent(record.id, 'cal1', { - title: record.A, - start: record.B, - end: record.C, + title: record.title, + start: record.startDate, + end: record.endDate, + isAllday: record.isAllDay, }) } } From 4ea9d9af2489406620c4559f3def5d6f5397549c Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Fri, 23 Jun 2023 14:01:21 +0200 Subject: [PATCH 18/64] calendar changes --- calendar/index.html | 20 +++++++++------ calendar/page.js | 12 +++++++++ calendar/screen.css | 59 ++++++++++++++++++++++++++++++++------------- 3 files changed, 67 insertions(+), 24 deletions(-) diff --git a/calendar/index.html b/calendar/index.html index a0b9b292..f9823ef9 100644 --- a/calendar/index.html +++ b/calendar/index.html @@ -9,13 +9,19 @@
- - - - - - - +
+ + + +
+
+ + + + + + +
Waiting for data... diff --git a/calendar/page.js b/calendar/page.js index ea515a45..2803b722 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -107,6 +107,18 @@ function selectRadioButton(value){ } } +function calendarPrevious(){ + Calendar.prev(); +} + +function calendarNext(){ + Calendar.next(); +} + +function calendarToday(){ + Calendar.today(); +} + function updateCalendar(records,mappings) { const mappedRecords = grist.mapColumnNames(records, mappings); if(mappedRecords) { diff --git a/calendar/screen.css b/calendar/screen.css index 68e099e8..342182d1 100644 --- a/calendar/screen.css +++ b/calendar/screen.css @@ -1,5 +1,16 @@ -#calendar-options { - margin: 10px; +body{ + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; +} + +#calendar-options{ + display:flex; + gap: 50px; + padding-bottom: 10px; +} + +#calendar-navigation-buttons,#calendar-perspective-buttons{ + display:flex; + gap: 0; } #calendar-options input[type="radio"] { @@ -8,25 +19,39 @@ width: 0; } -#calendar-options label { - display: inline-block; - background-color: #ddd; - padding: 10px 20px; - font-family: sans-serif, Arial; - font-size: 16px; - border: 2px solid #444; - border-radius: 4px; +.calendar-button{ + font-family: inherit; + font-size: 1em; + border: none; + border-top: 1px solid #11B683; + border-bottom: 1px solid #11B683; + /* border-radius: 4px; */ + letter-spacing: -0.08px; + padding: 4px 8px; + background:transparent; +} + +.calendar-button:last-of-type{ + border-right: 1px solid #11B683; + border-radius: 0 5px 5px 0; +} + +.calendar-button:first-of-type{ + border-left: 1px solid #11B683; + border-radius: 5px 0 0 5px; } -#calendar-options label:hover { - background-color: #dfd; +.calendar-button:hover{ + color: #009058; + border-color: #009058; } -#calendar-options input[type="radio"]:focus + label { - border: 2px dashed #444; +input:checked + label{ + background-color:#16B378; + color: #ffffff; + border-color:#000; } -#calendar-options input[type="radio"]:checked + label { - background-color: #bfb; - border-color: #4c4; +.toastui-calendar-day-view .toastui-calendar-panel:not(.toastui-calendar-time), .toastui-calendar-week-view .toastui-calendar-panel:not(.toastui-calendar-time) { + overflow-y: hidden; } \ No newline at end of file From 06ff8e6d3e740d56f436dc4e420a366c91ebcbbb Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Fri, 23 Jun 2023 14:57:33 +0200 Subject: [PATCH 19/64] styling, navigating to the row selected in main widget --- calendar/page.js | 30 +++++++++++++++++++++--------- calendar/screen.css | 8 +++++++- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 2803b722..a5a85e85 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -6,6 +6,12 @@ function ready(fn) { } } +let mainColor = getComputedStyle(document.documentElement) + .getPropertyValue('--main-color') + +let selectedColor = getComputedStyle(document.documentElement) + .getPropertyValue('--selected-color') + const columnsMappingOptions = [ { name: "startDate", // What field we will read. @@ -54,14 +60,14 @@ const options = { return `${title}`; }, allday(event) { - return `${event.title}`; + return `${event.title}`; }, }, calendars: [ { id: 'cal1', name: 'Personal', - backgroundColor: '#03bd9e', + backgroundColor: mainColor, }, ], } @@ -71,12 +77,24 @@ async function calendarViewChanges(radiobutton){ } let Calendar +let selectedRecordId = null; ready(function() { const container = document.getElementById('calendar'); // Update the widget anytime the document data changes. Calendar = new tui.Calendar(container, options); grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); grist.onRecords(updateCalendar); + grist.onRecord((record, mappings) => { + const mappedRecord = grist.mapColumnNames(record, mappings); + if(mappedRecord) { + Calendar.setDate(mappedRecord.startDate); + if(selectedRecordId){ + Calendar.updateEvent(selectedRecordId, 'cal1',{backgroundColor: mainColor}); + } + Calendar.updateEvent(mappedRecord.id, 'cal1',{backgroundColor: selectedColor}); + selectedRecordId = mappedRecord.id; + } + }); grist.onOptions(function (options, interaction) { if(options.calendarViewPerspective){ Calendar.changeView(options.calendarViewPerspective); @@ -135,13 +153,7 @@ function updateCalendar(records,mappings) { isAllday: record.isAllDay, category: 'time', state: 'Free', - color: '#fff', - backgroundColor: '#ccc', - customStyle: { - fontStyle: 'italic', - fontSize: '15px', - }, - }, // EventObject + }, ]); } else { Calendar.updateEvent(record.id, 'cal1', { diff --git a/calendar/screen.css b/calendar/screen.css index 342182d1..2907ef4c 100644 --- a/calendar/screen.css +++ b/calendar/screen.css @@ -1,3 +1,9 @@ +:root { + --main-color: #16B378; + --selected-color: #009058; +} + + body{ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol; } @@ -47,7 +53,7 @@ body{ } input:checked + label{ - background-color:#16B378; + background-color:var(--main-color); color: #ffffff; border-color:#000; } From 86a9a70a6436b27649a950a9c4a68565c0872bbf Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Fri, 23 Jun 2023 15:58:29 +0200 Subject: [PATCH 20/64] scroll --- calendar/page.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/calendar/page.js b/calendar/page.js index a5a85e85..0ecd7a6b 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -94,6 +94,10 @@ ready(function() { Calendar.updateEvent(mappedRecord.id, 'cal1',{backgroundColor: selectedColor}); selectedRecordId = mappedRecord.id; } + var dom = document.querySelector('.toastui-calendar-time'); + const middleHour = mappedRecord.startDate.getHours() + + (mappedRecord.endDate.getHours() - mappedRecord.startDate.getHours())/2; + dom.scrollTo({top: (dom.clientHeight/24)*middleHour, behavior: 'smooth'}); }); grist.onOptions(function (options, interaction) { if(options.calendarViewPerspective){ From b85bedd7a0dca5882642004cc1456f7500471147 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 13 Jul 2023 16:47:57 +0200 Subject: [PATCH 21/64] deleting events, improved styles, creating new event based on selection --- calendar/index.html | 31 ++++++++++++++++--------------- calendar/page.js | 16 ++++++++++++++++ calendar/screen.css | 18 ++++++++++++++++++ 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/calendar/index.html b/calendar/index.html index f9823ef9..0cf1dac6 100644 --- a/calendar/index.html +++ b/calendar/index.html @@ -8,24 +8,25 @@ -
-
- - - +
+
+
+ + + +
+
+ + + + + + +
-
- - - - - - +
-
- Waiting for data... -
diff --git a/calendar/page.js b/calendar/page.js index 0ecd7a6b..facd1517 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -119,6 +119,14 @@ ready(function() { } } }); + // Registering an instance event + Calendar.on('selectDateTime', async (info) => { + const dateFrom = info.start?.valueOf() / 1000; + const dateTo = info.end?.valueOf() / 1000; + const table = await grist.getTable(); + await table.create( {fields: {B: dateFrom, C: dateTo}}) + console.log(eventObj); + }); }); function selectRadioButton(value){ @@ -141,8 +149,10 @@ function calendarToday(){ Calendar.today(); } +let previousIds= []; function updateCalendar(records,mappings) { const mappedRecords = grist.mapColumnNames(records, mappings); + if(mappedRecords) { for (const record of mappedRecords) { const event = Calendar.getEvent(record.id, 'cal1'); // EventObject @@ -168,6 +178,12 @@ function updateCalendar(records,mappings) { }) } } + for (const id of previousIds) { + if (!mappedRecords.find(record => record.id === id)) { + Calendar.deleteEvent(id, 'cal1'); + } + } + previousIds = new Set(mappedRecords.map(record => record.id)); } } diff --git a/calendar/screen.css b/calendar/screen.css index 2907ef4c..20ebf5e0 100644 --- a/calendar/screen.css +++ b/calendar/screen.css @@ -25,6 +25,10 @@ body{ width: 0; } +.toastui-calendar-timegrid{ + height: 100%; +} + .calendar-button{ font-family: inherit; font-size: 1em; @@ -60,4 +64,18 @@ input:checked + label{ .toastui-calendar-day-view .toastui-calendar-panel:not(.toastui-calendar-time), .toastui-calendar-week-view .toastui-calendar-panel:not(.toastui-calendar-time) { overflow-y: hidden; +} + +#calendar-container { + display: flex; + flex-direction: column; + gap: 10px; + height: 100%; +} + +#calendar{ + flex: 1; + min-height: 600px; + flex-shrink: 0; + background-color: #ff0000; } \ No newline at end of file From 5fd47296f6f0c126b0f5fe01b44c71a77875ee22 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Mon, 17 Jul 2023 13:24:56 +0200 Subject: [PATCH 22/64] calendar widget being selectable as linking source. --- calendar/page.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index facd1517..3e5e26c4 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -82,7 +82,7 @@ ready(function() { const container = document.getElementById('calendar'); // Update the widget anytime the document data changes. Calendar = new tui.Calendar(container, options); - grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); + grist.allowSelectBy(); grist.onRecords(updateCalendar); grist.onRecord((record, mappings) => { const mappedRecord = grist.mapColumnNames(record, mappings); @@ -119,14 +119,19 @@ ready(function() { } } }); + Calendar.on('clickEvent', async (info) => { + grist.setSelectedRows([info.event.id]); + }); // Registering an instance event Calendar.on('selectDateTime', async (info) => { const dateFrom = info.start?.valueOf() / 1000; const dateTo = info.end?.valueOf() / 1000; const table = await grist.getTable(); - await table.create( {fields: {B: dateFrom, C: dateTo}}) - console.log(eventObj); + await table.create( {fields: {B: dateFrom, C: dateTo, "Is_All_Day_": info.isAllday?1:0, A: "New Event"}}) + Calendar.clearGridSelections(); }); + grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); + }); function selectRadioButton(value){ From 84d0b4915f2a6c5a3c95e4d564c2efbe47453971 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Mon, 17 Jul 2023 16:02:37 +0200 Subject: [PATCH 23/64] saving edited event is now independent of columns name (based on mapping) --- calendar/page.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/calendar/page.js b/calendar/page.js index 3e5e26c4..3d857b98 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -76,6 +76,15 @@ async function calendarViewChanges(radiobutton){ await grist.setOption('calendarViewPerspective', radiobutton.value); } +function mapCalendarEventToGristObject(event){ + const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; + const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; + const recordToMap = {id: record.id, startDate: dateFrom, endDate: dateTo, title: info.event.title, isAllDay: info.event.isAllday}; + const mappedRecord = grist.mapColumnNamesBack(recordToMap); + delete mappedRecord.id; + return{id:record.id, fields: mappedRecord }; +} + let Calendar let selectedRecordId = null; ready(function() { @@ -113,7 +122,10 @@ ready(function() { const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; const table = await grist.getTable(); - await table.update({id: record.id, fields: {B: dateFrom, C: dateTo}}) + const recordToMap = {id: record.id, startDate: dateFrom, endDate: dateTo, title: info.event.title, isAllDay: info.event.isAllday}; + const mappedRecord = grist.mapColumnNamesBack(recordToMap); + delete mappedRecord.id; + await table.update({id:record.id, fields: mappedRecord }); } } From a2151b14e795882a66e5930ebe521e804732b117 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Mon, 17 Jul 2023 17:10:42 +0200 Subject: [PATCH 24/64] creeating new events can handle any column names now --- calendar/page.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 3d857b98..1862d75e 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -77,12 +77,9 @@ async function calendarViewChanges(radiobutton){ } function mapCalendarEventToGristObject(event){ - const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; - const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; - const recordToMap = {id: record.id, startDate: dateFrom, endDate: dateTo, title: info.event.title, isAllDay: info.event.isAllday}; - const mappedRecord = grist.mapColumnNamesBack(recordToMap); + const mappedRecord = grist.mapColumnNamesBack(event); delete mappedRecord.id; - return{id:record.id, fields: mappedRecord }; + return{id:event.id, fields: mappedRecord }; } let Calendar @@ -119,13 +116,16 @@ ready(function() { if (info.changes.start || info.changes.end) { const record = await grist.fetchSelectedRecord(info.event.id) if (record) { - const dateFrom = (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000; - const dateTo = (info.changes.end?.valueOf() ?? info.event.start.valueOf()) / 1000; + const gristEvent ={ + startDate:(info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000, + endDate: (info.changes.end?.valueOf() ?? info.event.end.valueOf()) / 1000, + isAllday: info.changes.isAllday ?? info.event.isAllday, + title: info.changes.title ?? info.event.title, + id: record.id, + } + const mappedRecord = mapCalendarEventToGristObject(gristEvent); const table = await grist.getTable(); - const recordToMap = {id: record.id, startDate: dateFrom, endDate: dateTo, title: info.event.title, isAllDay: info.event.isAllday}; - const mappedRecord = grist.mapColumnNamesBack(recordToMap); - delete mappedRecord.id; - await table.update({id:record.id, fields: mappedRecord }); + await table.update(mappedRecord); } } @@ -136,10 +136,15 @@ ready(function() { }); // Registering an instance event Calendar.on('selectDateTime', async (info) => { - const dateFrom = info.start?.valueOf() / 1000; - const dateTo = info.end?.valueOf() / 1000; + const gristEvent ={ + startDate:info.start?.valueOf() / 1000, + endDate: info.end?.valueOf() / 1000, + isAllDay: info.isAllday?1:0, + title: "New Event" + } + const table = await grist.getTable(); - await table.create( {fields: {B: dateFrom, C: dateTo, "Is_All_Day_": info.isAllday?1:0, A: "New Event"}}) + await table.create(mapCalendarEventToGristObject(gristEvent)); Calendar.clearGridSelections(); }); grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); From dfbe568861094a4f08c1963c259a37874e4b7c6e Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 3 Aug 2023 17:03:39 +0200 Subject: [PATCH 25/64] unit tests for calendar --- test/calendar.ts | 19 +++++++++++++++++++ test/fixtures/docs/Calendar-UnitTest.grist | Bin 0 -> 225280 bytes 2 files changed, 19 insertions(+) create mode 100644 test/calendar.ts create mode 100644 test/fixtures/docs/Calendar-UnitTest.grist diff --git a/test/calendar.ts b/test/calendar.ts new file mode 100644 index 00000000..fecb1d1f --- /dev/null +++ b/test/calendar.ts @@ -0,0 +1,19 @@ +import { assert } from 'mocha-webdriver'; +import {getGrist} from "./getGrist"; + +describe('calendar', function() { + this.timeout(20000); + const grist = getGrist(); + + it('should show valid event', async function () { + }); + it('should show valid whole-day event', async function () { + }); + it('should not show event with invalid start date', async function () { + }); + it('should update event when table data is changed', async function () { + }); + it('should update table is event is changed', async function () { + }); + it() +}); \ No newline at end of file diff --git a/test/fixtures/docs/Calendar-UnitTest.grist b/test/fixtures/docs/Calendar-UnitTest.grist new file mode 100644 index 0000000000000000000000000000000000000000..f15f66b5509973372d4ebae9f34bdc7e2c8398ca GIT binary patch literal 225280 zcmeIb4~$$#dLP(5e>gKFhfRr+MwCRU)m$w#7P)-?|4`mULvkn$G$Ogf;YzZ!H>&rl z9_Oukx@Y?jDN0eiBt`AYyIQP+1Wsbab}k1b2jhYbV&mdl7#0v4kP+P7+IKb#I62(e z=h%i5WaA`;;~;TMXLs=hk+rTMraicz(; z!Wu<0w>Ov1=UyllbGcj||GW6V{gKxr?F;;s*W+E+X+QJ1FNC>Kqzo1QOr}3w_%DS& z+xh6O-yQ$X#4nG1e}@?TbmSL@e?I?G;m^|^zjy9^@YbHODcjC}Gi?yeiV}UyAt!(Kxf(h^rOQ-S}W!KLuWDmRYHI{LGp8*_qQF!m><~(NyBb zC(A4l#JpU zxo`T#xE`Zb`=-~LX!4$No<2W6kIL6X$jafX%c7G0>LmT7SWSC=`s&!^*wmpz`D?GF zuvj<0?HRySgSbhNO=pMIS}dXaax5%RIT1<@ zTM$tSk?E^@caKd?Pv@__(T&8(YB*Pksx296T}`H9(MlWy1_!lN$ygPl*4sWxWCB)y zTPR`N$lLXB8I}GroYUJ>tBE2&b4!ZcSP>E}eF5mzp3eEsy5$99cPy=>>N z%)}Kg-bp~HU#>5mEjKU3m6NQ&mYS9LYfZ8Awz!;@yt{?e`O|Y>IzJ1Aa&q>yVp_&7 zI>l-wHOsTB>aBD9a1n2tzItw_QjQX}zqe~$+octy`0UPN>(ft1s^lX_ zif79#t`y@+LtGHGVp6^$2Q0;ycZjr$o#?gGXBMG2rR1&=kzjT|f$F7ZZa>jj77~Ka z8!obPQxuQSpE=%9i-!&+^ovClQ|3?duzI~3#;hTD@lxDaRw><-rmvix7@N}d{MDCx zP(2lw#hN5YOxt&M_Cd6renUKqCtjL8@v`cXzF5?z4|nRN#AQQw&`GXds)*WLrQTqb zP|We(jIDgrR}YVkO}+SH{@SZORhm)i;3f2_)!OCbHBebzQ@jewz$$G;&x0+wJ z&S^+tEe?x;DnW7XWT%1^wjz>RCGyjLsKYu*p^GwK=ONZsa-HtG%?a`^-ZzituQ!TG zJ}GR;i`#I$KE7jW<;8qXiG2NQWsKyOShG=0RKP%hmh^$i6W3lC9h-Xo`TU1dgIb~w zjUAgoe=E4J7v2^eb0>?>mO2oYrh8z0iPe|WS_H7pDBO$C$>H1RwmJ_c!zpw+?egMP`Zctfn%nKbny2iZgw5YbGi&}%%b;;L$Y)ZBr5NlXj%NOKI=ttc4D4OuK1L+nECyZ^*} z`u1Lv18_j)4s>ij)GP@`$FI-q*arp~jbwz8+jUP!gnH!1t zEYt!n&?b(idr_n#QHxxiYX!e`nT5Ik?9b_9O?UV4*&A+O* z&f15Kk(LC$m9@!-M^Ys)E7=|iRNN!K?rI7AC6MIN_Z%e0-)@pR2} ztibkNpIe5h+o9_@QZ?G9A93B%BRw)8tUR*AED|UcQ={6He-^vc)K>X!7|(ahUqY`- z_>vo2mb?}n`KM966@@}wr8Fnfk&wMLlDCGy8tuiZrhT|N+!DLjvbOWkaH`m4CEFu* zvLdQKxvRx4cOtXch1_`X_XzEPUY*z$U=!e{M4dxk;Fk5$ZiwTEofyI0~ zvRp4TbSHDicU(yw*jloo>e#o9!IdiAe1Dh7h3f2%XDyTL+>Uq2oVwmVk!whiyF4UC zZX*Bfa@IB;N|m^*RC^>&!hQEk+}A&`vvzd0<_O>P0!w#v%duGK=v?M-}NlbgsI^0DBv1|HA_b)`EEv`EJH`%yv)hQ>h9^JXi17)EZ)Ag<=(FS zppv|qtx8^R$&wnc^>*s|)=1vktCG&HU2sji_Gn(pUT)(0;jFElDtcLo_K2RuWT5CF zJ;|`GX586dFxJbKY&8|sF)`e7Ip-PNu@B&}mM{r%Cuw`XeNf8G6;h34e9c0Ii7jj@?M zU)gzL?0+BMx95*Rl0Jk0AwUQa0$C849f5N+2=q`0A7+Q<238<+&oh0Un?`6Dfu?Kl zm|8{@2@UQ6Pva~Kx#bAcWJah5n&o|7QLzJf3p{4Iff0Fut|1eAcbdzYts`@&aTqtA zCOkJ3wuTp&xMD(>To}x7qh}Nq--%3&!EBBBrfnPC_I)I~+^|E#Mv*`- zHBdSp`YwEkP5{@1{<(yTrCEWeX-;H0j)$?G&A1ubp=N5DuWP#Dgr<AAF~HOuJK~OS z7(xqmn>!^%#p4b<%*?bc-_cxQG7N68q9P;_$MAI9^&LQ=nUR5JGfmT)}Bu|mT^+eEr$Xpsr*ebeQ>#fk|o zXwe8Zr*QQkaBb8t@C0LmGr>UJ7J-gYuVtYicp(d17xpO74&jnDL+(GNs6?S)259=4 zV*(+aVc4u`o`F|}rt4ZpC^TRdg%Q&X6Lu@iTLuc6=La?h;ZG)1gvYs!7Ij#JrVxQ| z_)G_aArrP|xTXR2F)Yu4HLM44%|}3015<^TD_QS=qJkSD;+n~AO?NaN>1b%wKM*!b z;rpHdk7+^=(0&el$Btuqzz>`i0U7wWo={W_E7EP-6yPHZgMQQv4H7vz4D=w>E!Q)M8|>#ksEb&GM`1d@jHxT0d(%r{){L*#{82!8Py_{#T~XM@jxFxX2sg(Is8 z{xMNgM|WZVhYoPI#AAwzr3Vi8BFs%#KCBQowyV=6WoPZqR9g|&XHm> zkYGBFenDojUs1uOfLRmzLf3?a>`tUH!;zv4S!b5%S*U{PI}%R^{&hGPG~aYI)Z5~^ zcvMjdHAClyCIaR&-?3e8hi0I|Yk_8P3{#-_HOMg7TbMSu-tt9c=?0hszQQ0hrjoK? zHYE&n!*?Cqh9}X~42Y`7aoaF(%>uYN1gtU*C1M6O?NI4Y(?>h3Oa$hu#9tzGVma!})^=6$1?bed)NEtCHHlv`rn2Y6%ZOpy^G+)tFQf zHWj4j-Vmv4Eb;pF_ z)Br5hY2ZNu_9`k;b!!G=ZWM?>M3}OHN`hk5paQr9PqXDS=xit)!9&Pqhz5CA;(7?Q;zgGXYIqGCHt zv(a^cfuUP<-_vj;m8J>wX(lwZ14i;8Qp^gXK;xXDDIvark4A@Z`r2edMVJ;|0-i=0 zpba!rV9LsfP$|o|brU#ye&}I}$}(&#Fwo1fP=^+>LI{9u?^aYo$ZCj=(*SEkhG0Al z;cT#E1tBYjkB$J6043!L7uahN$A8EM2J%n=wo6gbEtEF|Q)pl#*Ea($H7pz%9z+1@ z90JZoAj!J{N6mfoR=Cj6u$re^{!T@OL%PB4rVF7LP>py!DrUm>k3Ln{I$jaV9!!ID zb98dxLiE(8XB%)#3eTTVR9x^7INud^=-5&-LA8p|4qPt^F{dhmh~uu0z8yGQQqLnZ z^eFl)OF#n06&0um6N0Pjp^M&Khk|e|NP-W?OaNsJes}E%93T03w~d|@su&n)8WaRW zA2g<@hzM#OJ(+|DAOIHb8c??A=piPIgC{(UQ-H7>aDbIf3`8L345TfTXosSbbs~3E zQOPm@NEeZn*Gkxx%j%{$1f;W*Mx~vxER4KnM^5 zga9Ex2oM5<03kpK5CVh%A+W6o?8=Yi_UG%%I1QeE9&g(D%tW~wvImAoa?j-DuQJYT zu466w=LS6lH&j0cMVGwA_NElLVyq;1PB2_fDj-A2mwNX5Fi9LARyQO z=VTao`Vazy03kpK5CVh%AwUQa0)zk|KnM^5gus1^K(hWH`~QFYzO5ovj1V9M2mwNX z5Fi8y0YZQfAOr{jLVyssPZ4+)=PhDwfBukuXtr6y$@E8GWwkoH^j=9t0~DoWB~dwY z{#@z(#Qy(buJFVA6bh;qAwUQa0)zk|KnM^5ga9Ex2oM5<03q-hL|{*TEVqARd_2F% zg0j$uCJSb6bkA?)3;&{!D}1H!kM{i5XAl&sG9f?+5CVh%AwUQa0)zk|KnM^5guuOt z!1U;YxrzK!4^NIyJ~cUxPi{OnI#)l{ESFER%g3wLa_2%Hl35@2krmmKtV5@2)s>U1 zAr|8mactcLx=bm2ocj?_-#0mtMt!DoxkLQOuq6I~B>q5~`0!#io%CXL9B4m2k)M*3 zr`q{P=2;-hGf$65Qd6=@JxPn=orcO|=8GxoWNPO6S+vYJKfC z#s9lES)58u2oM5<03kpK5CVh%AwUQa0)zk|KnQFFfyu(3=O%}LK3AA3{L`sifU2oLHEhS)45{&K#egEtb-BNiuQMWlC5xx&)lU2m?eu-fHw)n+Y}52T~U8oRtV^fC?<*&Vx!eZV0wr2oS z4dNz6Hk}<-Yq5mx%dxoBkK5Lvs~A7MlGVyd0skYoE{#8G?2>%RIT1<@TM$tSk?E^@ zcaKd?Pv@__(T&8(YB*Pksx296T}`H9(MlWy1_!lN$ygPl*4sWxWCB)yTPR`N$lLXB z8I}Gro2&gOTkl~k!iVVWzD^mC%oh$|O1zJB`3W4p$tUbgdBX5tDL?<649 zFV~mOmYWyi3S7=?sac7?))Y%`i_2-ryIV+|KRx%Q^RrMWCud(Pre*A+Q><1}vpl=1 z-a5w*7xA{~tLJu(N#*##TvvPb6izYl`g^<9wOv|KiqGyWwm$uIq)I+=q;z}{D zG{gl_D<BF6RDRJ4*9dwebmnxz*SE)BxB@}bKH)AW` z^wq;-V^c4_n7{UFPnBkrI(P|vYPELxcnwsR*Z3hNalB7OQ?lN$&aLK`t#cYuSc}7A zph{4jJK3pVg{_FBR*C$yAL_79Qs|=0*LjGwm0YL$ZgYbCi}%f=`Rk2hl1~a-^5QmJ zuaEDTT6r;_QzBpgS~+frCDv?I6BRHJpe21^^2D_lM#rX}e?I@=)S#B=Lu1Eg(BBH~ z>xH)k$K1){v!xD%rRg46Ut;y;v=#xZGYa=2baMDMx~7v%)bzL%g=rs~j2r>LvuY|kORRv}5-#<$z$D8Pf`{$@tF;p6u zL+SZ}Ilfw#qlKP#wA=UU>%(JHM~>t_5a|ul=}{AQ9~syTTWNs~hxZh1T@zq5Ga$KH z7qy<`buA=^{Dab~=qGC%TBy4K<+$?pzzhSiz4BCkZ0fn^@>iNY*vg)=zQ*S2a;Oio zDscR>Pz*+P+5v%QRb~mq@+BaTAh@PgDQ3_to?M03g!n4`^Iv*WpYEC zKdZ?c#pQ<72OI6Ce#Z3ll|zq=O+E8W{^|o8+a$4t6}bER<30%Kq=VR4oPJ&r_zS>Y z=T-%jR?kz@SGzC=U!mTj&fR$3Zb`rp*$ zBmK&!QU{d~g(!=@0QX0K`pUrv$EJ=RUEhNw4#7n1yF51P#>4%}SQaXMdrEos0X3+* z`d3v&Ta7yV4#cs-%1ixkK9pM8^$*^BiDh>OcS?WYRl!cHVO+1gT|KaOZ0d_&>~WKI zO4cUbTh;dceS<63&NirS%hh^n7qg0Gcv+2CM{)1 z_lC!&uRU5&&a>-pcen1`iY#4QZdzA+Q?Y0z4njat?khFbT6{r{LQ>lgMMpnZ7acG1 z#;S2qj#psoruG=T+JwY@tyyiz@n?z$8Y4>vMZL^YA6F0dORT>guf~4NXeLx~O2`@HhQ_MJyq5i8Y{M)}~a zJ<2;tQ#UkqvrSVs*Qcfwi+%K^ZmCPg0c{JSYt-7dDjrLfzjcq@ybx~2ns`}UP7xSP zRW!;QdluOt4W6mvB4W*QJ1Ue| zCaD8^q}I`8CQ2$@5y1sL!WHrpZ4$37~0>RTKt@_$gwEllH z&I`&z2oM5<03kpK5CVh%AwUQa0)zk|KnUF12$21MZ?_+no)91e2mwNX5Fi8y0YZQf zAOr{jLVyt13<6~TZw4jGLkJK8ga9Ex2oM5<03kpK5CVh%AwUS++X#^Te{Z)Rm7WkF z1PB2_fDj-A2mwNX5Fi8y0YZQf*bD;F{?8ZwB8PwUAp{5kLVyq;1PB2_fDj-A2mwNX z5Fi8yf%^`Dk^D$*Vj{8s|8uVJpYOX0QiTWsLVyq;1PB2_fDj-A2mwNX5Fi8y0YYFj zKbo5uZ`uEUk}LcPK|%-+0)zk|KnM^5ga9Ex2oM5<03kpK5CZoB0{dX`?>{iPC{MK3 zYwXgJJU&>?{|^;@HCOom3ctGhncdIa2lb>X5CVh%AwUQa0)zk|KnM^5gg`a~hJO}o zh4)WR<|ihE~DIL?^$CmPHhhMHAk^C}oxABW-d-kUIrG-}){@qOjEH>2&+X?sMLl0ppKaoy} zbt0TK5msxQAIKxICAu>00VTPu#5cY&S@_f3c%hjqGz-69_`eIkTKI*+|5W&!h3k9% z)B69isSkRZ5Fi8y0YZQfAOr{jLVyq;1PB2_fDpI?2*Bq3dOn{YhoL-~8`(RG>(#aE z!U(S4TD#sejO(*&*ONoIexY+cyjwo6tzGYu&llIOcgpAYu3b+I?aA+gO`ac8?;pzj z%H%k%+vOP_-7~f;*U3IKHo9j=_w|mEJ)_;%qr-bfy01ruCWpJo4UbF?bzKe(1MfX} zc~bcyivNEH_>W#m2oM5<03kpK5CVh%AwUQa0)zk|KnUDs1jzos&4APE2mwNX5Fi8y z0YZQfAOr{jLVyq;1PFmUfB@P5cK~#HB_Tiv5CVh%AwUQa0)zk|KnM^5ga9FMn-L)U z|26|ouOkEq0YZQfAOr{jLVyq;1PB2_fDj-A?f?SP{?8Zwbq@dNLkJK8ga9Ex2oM5< z03kpK5CVh%AwUQa0{1imkLGtHz~H{g@yW@t$;rR^hW?cw|6x+0$>FQH$)QqiPkHix z+5M-xzPj`I@xMFvA9wu69j8VsBlb{f=r8W+ic{gYjsQ5~52x_;ds7Dw=C6%jIe&0$ zYX5%xQm2t5$44gLhfXZa&MeLr7iW&o&lXF`%~J8%m>1_xFV4O=yHGs4F!##L!t2GC zXJ0>DEUmCglaqs&EUBYgmS!3a7A~)dN~69M#bq(a@pEI^v#pxXojy7HT5)6g+Ox$or&H3O?a-b^ z1N~Ep@73pT556<$ARbS@eIn)d^i`)cHucOi`45h&BDbo4LX^w(?%$tZ&mP@LgP26o zTo6&I!$fTs(a@$iNTqLDt$JyWr$1J!R>5-{xBvuKSq)9x@43e1Rgq3H#IZ(rFpck; zbx~7=>|x32E9ajco0^`^UlrZJor=p1QENljx_TxRyjJ2M_%7n`q;ttJKz)H41R^*S zrAez64hpIW;JX3E=_}6_$EI92f2G-7ubC6`uZWcZRa=f%+tpit^K+@ST%Tu9Ws}D1 z(?H8{IgJ~pue|@%*pzMOuN~+q?b%vf3FB29Mb(z*6Z32L4)!bST9!dYO*pBCBfx)> zS!P#QoT|ZO;%S^#mDU^=YSrdyzr?tL!<;H1^w)+*r>`7*a%{>p^H)}S>c1fB)n*On zP_0$JbF0*^_G>u?D1P;#l(HlOJ;&=COL^_d17lOqJ(s_Zir^Hit|B$d>q;mui+xKc zQwKFmtySlA9$FQ(mAGD)M`!iP&|#SkH9*~1SUy#)tu)K5PwEME3RgPmwTI8LT3rg> zM&{`%-=cUYRT<`!Jce$s76;9S#A@SPR>TUr-k$r@R}Vj-8t8*UcLOcf z;tLnnv|0P|sniB)rw(c$MZB*j!+B|y#v+t-Z^2t*hPb|fgVZhq=e{JEIx?;Ic{PB* zNp9&Qi&R9=;G!aVHC0Dm8-09iO4sw(?QXcb#~T|)AWx=(*7e9B+@Qyk(aVOGLpfz) zKh+`AB%=MEI~Tv(r%RMi&Zcu=yuvPsmqdJF8BE$99Cr8XD#NQWZ!D*$H{um>Qj|qQ zqI(jf&c(S`W;?^VR%^>l=U2;B#{1@)zT!PLHg)7k{_4T*c37A_JHPZ24)1H}na=fr z)HdiO4{CuBhZm-SSZy{|n~i?*Dr&WAEj4la%8%|>EVRDpUuNYPN4ZNK)hc|~ohMR@ z-<4rd1)~1COCF(^R<{AtI(_YdN5`gSX7bmMbR#bhd#o?D4lcyFS(JIZ8XHp{Pp{6# zjDxB*c*K{a4%C=~hEF(du^$VsJBcw3JRa9q%S zDKpc_{QqC%3S{SR-BP9}2mwNX5Fi8y0YZQfAOr{jLVyq;1PFn<9)XekNN#dc+W#Yk zf1E4)o5JrD{yBcohY%nH2mwNX5Fi8y0YZQfAOr{jLVyq;1nw{b`$oocQFM)pq(@n8S?Tk`)|c|?lwFgE{B;Ql!O^bfwr zKm8A%sN4EZS*yMGM%Ad4ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|aB~RA`Tx<}`?)=0 z=O2$<9R5rEynUY!e|&U2cV#l4|Mo>I;uiM<%QYy{7bKB!{`a#Olk<7jT)CY;&SR^K^419>rC21YaR5 zhi~9-PGu04i=te`8MJTYaVsfEP2eQy7@n8prh4k&%>2Bje#Moj`o<74$CAi<>K+&M z@N_G+-cYq^R_da0M4si`+<|=MxbpTKSC2Hua9wRIi(31JES5a~^g`~t|HOUdr{6iQ zNXf%}oBNPdk86!(23ODv7vy2nUkIx!T2nfHlJhQS)FHSX+#(U`!U&nE2MoxwPz$&~ zn>d>8MUjp~Epm0P8Qgc6@B4ueXg$MZcHr>9v{iBI2t+Bks^(f<-;m{O?#9;w4$EDU zhgmjPDk}e?JUdr!N(@glCDils_}#Qe&#&UZQ?VezYK=D^LeAESp^8F%3FmWyW-QhE8Nx{^$*4%|Ur~{glLy8rH z-TbS1>#Tj)7->o1TUncYcqCN#ml-PkztIDuHh3n3n09TI6xtwM^Ry z9Z%Ox#|muU^|@u3x*fWnBUPhq`VrSHJ<=ls!pb8%%p!qOF*T}9`Dd|9O>LF$hVgv2 z{3Z0dgfF?VWyx#Nk$)Q1TTv*~RZ4Rr9SPZ6BYA5GtkGVqYTAdZ!!5CUEo(au4X27- zR&h2=Y%&F_`6S;;I zxywUR>O0`GgB;0qu#C`n}J8MU0YmV?uFR*k+w;YRwj?Q%-BYf^y zk);L95Ee6nAneiShI9=lJ8~|%BO18m7AA2*;w5@ofIuev5Upq zx3=8dwI5WHH?vjA>n&MQ4w|sZb|4AQCT$Vs@If|H#KShkL35|c3mDn zH}cE)L7#6Nnn(s`AD`k}7q*6BI80oj3EeV$<~b%t;-+p2TMz9pG=vsv!t}ZB2`6$* z&oe#Sz%W60{`f>Hzh))d!>`guF_2#+Lnj5fgISuc5}T-r;u$jx5Qhqc>uI;>>F=M>XTVnV{ANCQnQlnk<@YEefLZ1>i_IzmDC_K zOhfl|J#-B@Y;zsgirm1*m@W`*pc{^BN2cvZJ`|)TX%oUW4v`w-`qg2x1ifN&|7;|GSFLBdRSTq z#}cXh)?dlW20O-5r7|no9;uYB^gAz=(!oE-tN+P=%k0$`k>i*!q%8E3w#EV;a@X)o zp=-KnbH)uGd4XmbhUIBY7~C_t=V3mEK~ydDqTNy{`Kwo~BqPjl-tx;ohO3reUY=A{ zU#bh`#9oSGQRcDKh3_ef@XjxYD4AT5cas?j%xkEDxFnj~Ia{r(r@F*Tl|nhEk{N}S z>c#f7z$RWlpugHmRZefY8mBewqmdnnl>B5aYqN~*NR^VTWP7AU@u%$ax61|Cl(xtm zX1r>RVlsoHgi_6Z$*H}Yn+(hS*UVy*c@j}V*P0BIyxK=>HjX)!4u4N6g{WFvX_i?N zk0*1Eas5z>Z+z2#?f05%UJ658;GVHY$`rq(=hU>E)Am^tVhH2X{k4QvTX+MKF{1h zd8r<&*Pd6pPztE35cKedVnR_#0GC#wNF~TnLy7(WGr8SAHva#QM){vXGJWnE1impl znRF808L}Ow*#^U;yJ2G@(DyW5_?jjRBQW8DaA5KJ=+>DPM1jUR^EAv$7=h2=L)CR( z+dY}uNn|D4(@98ny7NOR*?xnDQn^=WvKlzHFfGfDbi?pGxP$`D6j&@_M9dbJZ|i1g zS)LzySR7#)wiOr}4_T<|SWFRG0Y+clLn)tF$s=)K*E9Dlo#m2r0MPM71X{3yXm7Ej5APO??* zemVZ+r@oj~j>C`zA!m^h+E!!;#={U3O;+Uio&nMIBNoCO3Jf?WT%kK!#PJ`pS)t)U z7qf0TmLl9c^cuw867r5Oq06r*ndf-5TFxNP$xu!bQUk*dMb)NT@EP_iq7uGVQ>*hv2+8D!H;iRAuconV;oPnHsvPl*SSb` znU@O;dn9jBywk`ad9vBkC~j5q(u&s>m$f0n=6d&@GPTLv5~=H~(^kc$c zLQZ8kF1CVbT7<0!u)<+{3#`xxESTk33cv!-4Q(tVvrOINSVLg?hG9pp2)(@zr1mUX z$@cUt4*<}6z?!-^o3&?Qp}^1#D`PN+Wb3e(ux^%lArlOnMl26AO1d8K!13^3ZpHnQQ1waKS??>IywAjC?HnHnhm}9iy9P zB|mM&1JE_dm#lP4TzScWe5>TTcwS0IvgARTN2-2Fu%IsSQ8ksXQsT1-8*5#Gw(h}8 zsa0Ph1L}eTLkaYsIoaTC7(h!VwQ$kC@x?;R*r{dZr#*#K@y<%NN4yKN>F#=Cr#OEi zt9biS80dBoNspc#2nKJx$AssyzziYZp35EC`S=z$;m>z9ow0T-E&XKZ|?ueKGBwO-m_bN(}t8AH2w{y-q(6ZELUhO$G?Jx z=n^9JicY_{&ONt9!l1jgu4;?)Rl!^H|DWb2&rUQ)NAjP_x6#Gq) zuNb3ZK>)WcANtG-1-4gN27Kz+yNG4Ej;HyiX!G1-=)(lyv}t*a_Hr5I6{2!7$7)LoW;h$H%r3;c8KY$wuay z99u|OWCvKSfoo6aj^PSR*dkar$FV5|*45{(TXz{JeXevy$UqY3YT>zLL8e@MDJgGG zjolP^P~Vy|yTM!JI+Io)v(B{>mg11X62zocD}oqwXya+ zlqx$}$@a*O;@a&Tyf+U4O*mQvFIL2*qQnh9TkCg=jcV~C7W5Wd@j7HdGA`2G%QK6a zB?Pwn_yS9pE$k7(zHBUO);J4XffZ1g-FFyVQXb~*bzxyk7Y_pNng%2i`$;3u>>ek` zp<%BXF9+RguBRKYr!+7F#3m87SJfavN|!Q}xrkV^+(_Bo{7EQl@--%Y}h?l_R< ziPAhLY682#q|R+AR;5+dS64HhKCOM@wS9@g`OdRh+4jMGsR}16*&c->x9Z*b&KiXn z*jX2+PG#+^g%-HXbsWSqa$n`l;n>L}u#d@t zYXMs*c()djEZeI^wy+#%t5$xOEUXWMl&p){D!DGBTMA&}#OSP6TI`ZfRnLye)6W$s z-`{z>$0gF&^506G`VtvjlT$bAMMy?v^wIm&STJr!c9BA5|-^Q zhO+;MMn`hH4&sYGga9Ex2zU}`(6mK*QEpj07>;C0%C}7xAOxF0#3)S*O=ci!EaC@X=|Y6{?V`^;g*HYFxR1tSDl=!Dl{?u+iE7_iIe?JO-_jmin{jX;2_JOOwZjR8$46nc*58a8dQPjcF zA=n)%m}Men73@JDt6D%IW-~P&@tzO8;s`jQHP3?uUlI`h*9=#`e zp|ih}**BTlr@M{DCuzO`BA2H5Zn3>eUbS`jry;&QeGM`GI^fs$H7U)I*#ATC=O)hL zi#~+F?L^??vyUf(o4@<0VMV%an}`k0EFA3OxBLM`-s-DeCZ zD`4}a?U=wGL8Apuz`)u_-9~sx>|bDx?&7Sh&~dqEZL5iW_C7G{uu_;8)mrXbI0d_2 z+jkq=_#M}0R49Dd-gZhypt$-*>(RC_{c-9(Xr#NPX|`vmL}JuuB|{c5(mp=&Skk5a zorSDAbpK&k7vUX{iz3tm*uamYMV7A=Zj*PsQn{1l2LB;m; zTqG@+c0rdI!;t)UKD9qDr4i^=L1isS~^+D_EqXWQOWM?P&jhKG8$+{@oDhDZ58!j0cOn-zd3 z4y1EqR$S!{=(Q6z6dy<+wkz8B?T+E`*1yfjxZpt%an0oLC_5UDa9ECs&Gmt>p+B&Q zOW;sKoWYEoP|0NGa5=l>1mem^&{gs=Pa^WDqE zL{@+9tHOzF&oMmRcF}bhHX=V6I2_(EW$1VrC7xLVp~)RYiNeY9CSsP$AkUnkgK_1Y z^i#!DS z%~JQo_xtcqc5OzEuswP6Q?5xtT8G7gbZc|-hJDKNe#&lIr8IALgBtNmpMB=Hm0w^J zgWbVHo7%vhkza0|+1tJMkkpJi^7*#1&Fxe(+Q&~mm5e?9j+M2$d-AE&u}4<2J!6lj z?uoI-4|Zf6dt`PkZq-V-fxCf}!iJb7w^b?J*1qHxk3ArbYcqr{U<#x{m{(B@hpz!3X_S*=elFz*z*WSMffRnk{ch<0x0KNo%6>&tZA6S^M;2o@T; zE(?9r(;TeIcYMS&!3unvJ5QHV&HAild(8S0+T!jv>-SD)H0v`vL$=YZ|1&b{?^ClL ztC70mou+MxzQvQjWUYOMthKGI|K7ra6H-U_D-YdJ9kuNL$8%#cv>AN}0YZQfAOr{j zLf|KZgNbGTKmMq1;aovPEpQ^saXe-OHuffmHckT9G+)NM95Zmj&_l3H zW(%AdE)1VXM(JRxWuKL7k7a)lZFcut_CI$tqh+7jAF_>>{SdY~-xWs`Zenv+awsJ2 z8&ij3ZrC^0J9)N#D2=P_JIQ3@R6bc~pIHlSn{0kkRG$rwx`Con_Ww|RA-Ch-UFwIcoA@@8@An<@dECOFQam9o% zxiFaFMxT2ob=a7dY|pUqnR{Z`SRDFR#&82pWMUz$tufz3&>(L6K2UbKVIvR(N4zW- zt%2|Yrf!;M;2OHT;p034?gTh=TP4|2!fK5-Wpw2w zwR?VP-Ff0mQ7p>*4cXJjGA>cPQ+~+>UGZ*wb%ie4V%Qv&y)(z4%BikoEF4+7wE##r zS+tuCBqR$Kum4hf*b_)71q@BWq%yCSzOQ>*zT!RAX>Kxn(*t;*6^87b2pe&=vLK=u zGjy#;HLc^`DO~!k50~B?2g(TpAP}B{T(*C5=VftOiCoyMH>xWtt2!{D-8x$O$Vjrh zikX+lp_IB-vnuY>{>JXlCF=Pf?DaEhgoB?;RnJ+;_NeF2$qGps-mXA#rxo?MQg1Y+ z7HU@NqH#oBN<&$SMmtL3fUt#cxf!kc%)XFqwCW!qtNt@FU*A1g#_w%CGDS-C`j|sx zl95TKz2B!>Q-e4;G+YPPpLnu<>aPU|Vl0G@Z6}%=Sb@+z53>nyY9qvMpuv-ESe6k*LUTOb(>RMT z6M^`~^0)^*&@Atn&!>8_vXbrbWPKiZ-u<4e?_JF}(U5t1rpuFcOD7sq;^E)?M1wL& z)t8K-n{}cgrD!)h(ICrolP4BzX`&%9vA1weM0bowvc}08-w>7hHcy902G;&N)|U@l literal 0 HcmV?d00001 From bf57d151e0799f84e40a7add68b9490b9f6700cc Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Mon, 7 Aug 2023 13:28:08 +0200 Subject: [PATCH 26/64] tests --- test/calendar.ts | 98 +++++++++- test/getGrist.ts | 479 +++++++++++++++++++++++++++-------------------- 2 files changed, 370 insertions(+), 207 deletions(-) diff --git a/test/calendar.ts b/test/calendar.ts index fecb1d1f..aaa86aba 100644 --- a/test/calendar.ts +++ b/test/calendar.ts @@ -1,19 +1,105 @@ -import { assert } from 'mocha-webdriver'; +import {assert} from 'mocha-webdriver'; import {getGrist} from "./getGrist"; -describe('calendar', function() { +function getAbstractFromCalendarObject(eventId: number) { + return ` + const calendarObject = Calendar.getEvent(${eventId},"cal1"); + if(calendarObject) + { + return{ + title: calendarObject?.title, + startDate: calendarObject?.start.toString(), + endDate: calendarObject?.end.toString(), + isAllDay: calendarObject?.isAllday??false + } + }else{ + return calendarObject + }` +}; + +describe('calendar', function () { this.timeout(20000); const grist = getGrist(); + before(async function () { + const docId = await grist.upload('test/fixtures/docs/Calendar-UnitTest.grist'); + //await grist.createDoc("Calendar Test"); + //await grist.addNewColumn("Table1", "Label", "Text"); + await grist.openDoc(docId); + await grist.toggleSidePanel('right', 'open'); + await grist.addNewSection(/Custom/, /Table1/); + await grist.clickWidgetPane(); + await grist.selectCustomWidget(/Calendar/); + await grist.setCustomWidgetAccess('full'); + await grist.setCustomWidgetMapping('startDate', /From/); + await grist.setCustomWidgetMapping('endDate', /To/); + await grist.setCustomWidgetMapping('title', /Label/); + await grist.setCustomWidgetMapping('isAllDay', /IsFullDay/); + }); + it('should show valid event', async function () { + //const obj = await grist.getCustomWidgetObject('); + const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(1)); + assert.deepEqual(mappedObject, { + title: "Event1", + startDate: new Date('2023-08-01 13:00').toString(), + endDate: new Date('2023-08-01 14:00').toString(), + isAllDay: false + }) + await grist.waitToPass(async () => { + const txt = await grist.getCustomWidgetBody('[data-testid*="Event1"]'); + assert.equal(txt, 'Event1'); + }); }); it('should show valid whole-day event', async function () { + const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(2)); + assert.deepEqual(mappedObject, { + title: "Event2", + startDate: new Date('2023-08-02 00:00:00').toString(), + endDate: new Date('2023-08-02 23:59:59').toString(), + isAllDay: true + }) + }); - it('should not show event with invalid start date', async function () { + + it('should create new event when new row is added', async function () { + await grist.sendActions([['AddRecord', 'Table1', -1, { + From: new Date('2023-08-03 13:00'), + To: new Date('2023-08-03 14:00'), + Label: "New Event", + IsFullDay: false + }]]); + const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(3)); + assert.deepEqual(mappedObject, { + title: "New Event", + startDate: new Date('2023-08-03 13:00').toString(), + endDate: new Date('2023-08-03 14:00').toString(), + isAllDay: false + }) }); - it('should update event when table data is changed', async function () { + + it('should remove event when row is deleted', async function () { + await grist.sendActions([['RemoveRecord', 'Table1', 3]]); + const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(3)); + assert.notExists(mappedObject); }); - it('should update table is event is changed', async function () { + + it('should update event when table data is changed', async function () { + await grist.sendActions([['UpdateRecord', 'Table1', 1, { + From: new Date('2023-08-03 13:00'), + To: new Date('2023-08-03 15:00'), + Label: "New Event", + IsFullDay: false + }]]); + const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(1)); + assert.deepEqual(mappedObject, { + title: "New Event", + startDate: new Date('2023-08-03 13:00').toString(), + endDate: new Date('2023-08-03 15:00').toString(), + isAllDay: false + }) }); - it() + + //TODO: test adding new events and moving existing one on the calendar. ToastUI is not best optimalized for drag and drop tests in mocha and i cannot yet make it working correctly. + }); \ No newline at end of file diff --git a/test/getGrist.ts b/test/getGrist.ts index f17df3a4..c66d4db9 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -1,28 +1,30 @@ -import { ChildProcess, execSync, spawn } from 'child_process'; +import {ChildProcess, execSync, spawn} from 'child_process'; import FormData from 'form-data'; import fs from 'fs'; -import { driver } from 'mocha-webdriver'; +import {By, Key, WebDriver, driver} from 'mocha-webdriver'; import fetch from 'node-fetch'; -import { GristWebDriverUtils } from 'test/gristWebDriverUtils'; +import {GristWebDriverUtils} from 'test/gristWebDriverUtils'; + +type UserAction = Array; /** * Set up mocha hooks for starting and stopping Grist. Return * an interface for interacting with Grist. */ export function getGrist(): GristUtils { - const server = new GristTestServer(); - const grist = new GristUtils(server); - - before(async function() { - // Server will have started up in a global fixture, we just - // need to make sure it is ready. - // TODO: mocha-webdriver has a way of explicitly connecting a - // server that might have advantages for debugging. - await grist.wait(); - }); - - return grist; + const server = new GristTestServer(); + const grist = new GristUtils(server); + + before(async function () { + // Server will have started up in a global fixture, we just + // need to make sure it is ready. + // TODO: mocha-webdriver has a way of explicitly connecting a + // server that might have advantages for debugging. + await grist.wait(); + }); + + return grist; } /** @@ -34,11 +36,11 @@ export function getGrist(): GristUtils { * */ const serverSettings = { - gristContainerName: 'grist-test', - gristImage: 'gristlabs/grist', - gristPort: 9999, - contentPort: 9998, - site: 'grist-widget', + gristContainerName: 'grist-test', + gristImage: 'gristlabs/grist', + gristPort: 9999, + contentPort: 9998, + site: 'grist-widget', }; /** @@ -47,195 +49,270 @@ const serverSettings = { * by running live-server with some middleware. */ export class GristTestServer { - private _assetServer?: ChildProcess; - - public async start() { - await this.stop(); - const {gristContainerName, gristImage, gristPort, contentPort} = serverSettings; - const cmd = `docker run -d --rm --name ${gristContainerName}` + - ` --network="host"` + - ` -e PORT=${gristPort} -p ${gristPort}:${gristPort}` + - ` -e GRIST_SINGLE_ORG=${serverSettings.site}` + - ` -e GRIST_WIDGET_LIST_URL=http://localhost:${contentPort}/manifest.json` + - ` ${gristImage}`; - try { - execSync(cmd, { - stdio: 'pipe' - }); - } catch (e) { - throw new Error( - `Failed to start Grist: ${cmd} (${e?.stderr.toString()})` - ); - } - const pwd = process.cwd(); - this._assetServer = spawn('live-server', [ - `--port=${contentPort}`, '--no-browser', '-q', - `--middleware=${pwd}/buildtools/rewriteUrl.js` - ], { - env: { - ...process.env, - GRIST_PORT: String(gristPort), - }, - }); - } - - public async stop() { - try { - execSync(`docker kill ${serverSettings.gristContainerName}`, { - stdio: 'pipe' - }); - } catch (e) { - // fine if kill fails, may not have been running. - } - try { - execSync(`docker rm ${serverSettings.gristContainerName}`, { - stdio: 'pipe' - }); - } catch (e) { - // fine if rm fails, may not actually exist. - } - if (this._assetServer) { - this._assetServer.kill(); - this._assetServer = undefined; - } - } - - public get gristUrl() { - const {gristPort} = serverSettings; - return `http://localhost:${gristPort}`; - } - - public get assetUrl() { - const {contentPort} = serverSettings; - return `http://localhost:${contentPort}`; - } + private _assetServer?: ChildProcess; + + public async start() { + await this.stop(); + const {gristContainerName, gristImage, gristPort, contentPort} = serverSettings; + const cmd = `docker run -d --rm --name ${gristContainerName}` + + ` --network="host"` + + ` -e PORT=${gristPort} -p ${gristPort}:${gristPort}` + + ` -e GRIST_SINGLE_ORG=${serverSettings.site}` + + ` -e GRIST_WIDGET_LIST_URL=http://localhost:${contentPort}/manifest.json` + + ` ${gristImage}`; + try { + execSync(cmd, { + stdio: 'pipe' + }); + } catch (e) { + throw new Error( + `Failed to start Grist: ${cmd} (${e?.stderr.toString()})` + ); + } + const pwd = process.cwd(); + this._assetServer = spawn('live-server', [ + `--port=${contentPort}`, + `--middleware=${pwd}/buildtools/rewriteUrl.js`, + `-q`, + `--no-browser` + ], { + env: { + ...process.env, + GRIST_PORT: String(gristPort), + } + }); + } + + public async stop() { + try { + execSync(`docker kill ${serverSettings.gristContainerName}`, { + stdio: 'pipe' + }); + } catch (e) { + // fine if kill fails, may not have been running. + } + try { + execSync(`docker rm ${serverSettings.gristContainerName}`, { + stdio: 'pipe' + }); + } catch (e) { + // fine if rm fails, may not actually exist. + } + if (this._assetServer) { + this._assetServer.kill(); + this._assetServer = undefined; + } + } + + public get gristUrl() { + const {gristPort} = serverSettings; + return `http://localhost:${gristPort}`; + } + + public get assetUrl() { + const {contentPort} = serverSettings; + return `http://localhost:${contentPort}`; + } } export class GristUtils extends GristWebDriverUtils { - public constructor(public server: GristTestServer) { - super(driver); - } - - public get url() { - return this.server.gristUrl; - } - - public async wait() { - let ct = 0; - while (true) { - if (ct > 8) { - console.log("Waiting for Grist..."); - } - try { - const url = this.url; - const resp = await fetch(url + '/status'); - if (resp.status === 200) { break; } - } catch (e) { - // we expect fetch failures initially. - } - await new Promise(resolve => setTimeout(resolve, 250)); - ct++; + public constructor(public server: GristTestServer) { + super(driver); } - ct = 0; - while (true) { - if (ct > 8) { - console.log("Waiting for asset server..."); - } - try { - const resp = await fetch(this.server.assetUrl); - if (resp.status === 200) { break; } - } catch (e) { - // we expect fetch failures initially. - } - await new Promise(resolve => setTimeout(resolve, 250)); - ct++; + + public get url() { + return this.server.gristUrl; + } + + public async wait() { + let ct = 0; + while (true) { + if (ct > 8) { + console.log("Waiting for Grist..."); + } + try { + const url = this.url; + const resp = await fetch(url + '/status'); + if (resp.status === 200) { + break; + } + } catch (e) { + // we expect fetch failures initially. + } + await new Promise(resolve => setTimeout(resolve, 250)); + ct++; + } + ct = 0; + while (true) { + if (ct > 8) { + console.log("Waiting for asset server..."); + } + try { + const resp = await fetch(this.server.assetUrl); + if (resp.status === 200) { + break; + } + } catch (e) { + // we expect fetch failures initially. + } + await new Promise(resolve => setTimeout(resolve, 250)); + ct++; + } + } + + public async upload(gristFileName: string): Promise { + const endpoint = this.url + '/api/docs'; + const formData = new FormData(); + formData.append('upload', fs.createReadStream(gristFileName), 'sample.grist'); + + const response = await fetch(endpoint, { + method: 'POST', + body: formData, + headers: { + 'X-Requested-With': 'XMLHttpRequest', + } + }); + + if (response.ok) { + const result = await response.json(); + if (typeof result !== 'string') { + throw new Error(`Unexpected response: ${result}`); + } + return result; + } else { + console.error('File upload failed. Status:', response.status); + throw new Error(`Upload failed: ${await response.json()}`); + } + } + + public async openDoc(docId: string): Promise { + await driver.get(this.url + `/doc/${docId}`); + await driver.findWait('.viewsection_title', 10000); + await this.waitForServer(); } - } - public async upload(gristFileName: string): Promise { - const endpoint = this.url + '/api/docs'; - const formData = new FormData(); - formData.append('upload', fs.createReadStream(gristFileName), 'sample.grist'); - const response = await fetch(endpoint, { - method: 'POST', - body: formData, - headers: { - 'X-Requested-With': 'XMLHttpRequest', + + public async addRow(table: string, data: Record): Promise { + var fields = await driver.findElements(By.css(`.record-add .field`)); + const entities = Object.entries(data) + for (const col in entities) { + await fields[col].click(); + await driver.sendKeys(entities[col][1]); + await driver.sendKeys(Key.ENTER); + } + } + + + + public async sendActions(actions: UserAction[]) { + const result = await driver.executeAsyncScript(` + const done = arguments[arguments.length - 1]; + const prom = gristDocPageModel.gristDoc.get().docModel.docData.sendActions(${JSON.stringify(actions)}); + prom.then(() => done(null)); + prom.catch((err) => done(String(err?.message || err))); + `); + if (result) { + throw new Error(result as string); + } + await this.waitForServer(); } - }); - if (response.ok) { - const result = await response.json(); - if (typeof result !== 'string') { - throw new Error(`Unexpected response: ${result}`); + + public async waitForServer(optTimeout: number = 2000) { + await this.driver.wait(() => this.driver.executeScript( + "return window.gristApp && (!window.gristApp.comm || !window.gristApp.comm.hasActiveRequests())" + + " && window.gristApp.testNumPendingApiRequests() === 0", + optTimeout, + "Timed out waiting for server requests to complete" + )); } - return result; - } else { - console.error('File upload failed. Status:', response.status); - throw new Error(`Upload failed: ${await response.json()}`); - } - } - - public async openDoc(docId: string): Promise { - await driver.get(this.url + `/doc/${docId}`); - await driver.findWait('.viewsection_title', 10000); - await this.waitForServer(); - } - - public async clickWidgetPane() { - const elem = this.driver.find('.test-config-widget-select .test-select-open'); - if (await elem.isPresent()) { - await elem.click(); - // if not present, may just be already selected. - } - } - - public async selectCustomWidget(text: string | RegExp) { - await this.driver.findContent('.test-select-menu li', text).click(); - await this.waitForServer(); - } - - public async setCustomWidgetAccess(option: "none"|"read table"|"full") { - const text = { - "none" : "No document access", - "read table": "Read selected table", - "full": "Full document access" - }; - await this.driver.find(`.test-config-widget-access .test-select-open`).click(); - await this.driver.findContent(`.test-select-menu li`, text[option]).click(); - } - - public async setCustomWidgetMapping(name: string, value: string|RegExp) { - const click = (selector: string) => driver.findWait(`${selector}`, 2000).click(); - const toggleDrop = (selector: string) => click(`${selector} .test-select-open`); - const pickerDrop = (name: string) => `.test-config-widget-mapping-for-${name}`; - await toggleDrop(pickerDrop(name)); - const clickOption = async (text: string | RegExp) => { - await driver.findContentWait('.test-select-menu li', text, 2000).click(); - await this.waitForServer(); - }; - await clickOption(value); - } - - // Crude, assumes a single iframe. Should elaborate. - public async getCustomWidgetBody(selector: string = 'html'): Promise { - const iframe = driver.find('iframe'); - try { - await this.driver.switchTo().frame(iframe); - return await driver.find(selector).getText(); - } finally { - await driver.switchTo().defaultContent(); - } - } - - public async inCustomWidget(op: () => Promise): Promise { - const iframe = driver.find('iframe'); - try { - await this.driver.switchTo().frame(iframe); - return await op(); - } finally { - await driver.switchTo().defaultContent(); - } - } + + public async clickWidgetPane() { + const elem = this.driver.find('.test-config-widget-select .test-select-open'); + if (await elem.isPresent()) { + await elem.click(); + // if not present, may just be already selected. + } + } + + public async selectCustomWidget(text: string | RegExp) { + await this.driver.findContent('.test-select-menu li', text).click(); + await this.waitForServer(); + } + + public async setCustomWidgetAccess(option: "none" | "read table" | "full") { + const text = { + "none": "No document access", + "read table": "Read selected table", + "full": "Full document access" + }; + await this.driver.find(`.test-config-widget-access .test-select-open`).click(); + await this.driver.findContent(`.test-select-menu li`, text[option]).click(); + } + + public async setCustomWidgetMapping(name: string, value: string | RegExp) { + const click = (selector: string) => driver.findWait(`${selector}`, 2000).click(); + const toggleDrop = (selector: string) => click(`${selector} .test-select-open`); + const pickerDrop = (name: string) => `.test-config-widget-mapping-for-${name}`; + await toggleDrop(pickerDrop(name)); + const clickOption = async (text: string | RegExp) => { + await driver.findContentWait('.test-select-menu li', text, 2000).click(); + await this.waitForServer(); + }; + await clickOption(value); + } + + // Crude, assumes a single iframe. Should elaborate. + public async getCustomWidgetBody(selector: string = 'html'): Promise { + const iframe = this.driver.find('iframe'); + try { + await this.driver.switchTo().frame(iframe); + return await this.driver.find(selector).getText(); + } finally { + await this.driver.switchTo().defaultContent(); + } + } + + public async executeInIframe(fnc:(driver:WebDriver)=>void){ + const iframe = this.driver.find('iframe'); + try { + await this.driver.switchTo().frame(iframe); + return await fnc(this.driver); + } finally { + await this.driver.switchTo().defaultContent(); + } + } + + public async getCustomWidgetObject(script: string): Promise { + const iframe = this.driver.find('iframe'); + try { + await this.driver.switchTo().frame(iframe); + const jsValue = await this.driver.executeScript(script); + return await jsValue; + } finally { + await this.driver.switchTo().defaultContent(); + } + } + + // Crude, assumes a single iframe. Should elaborate. + // public async getCustomWidgetX(selector: string = 'html'): Promise { + // const iframe = this.driver.find('iframe'); + // try { + // await this.driver.switchTo().frame(iframe); + // return await this.driver.execute('Calendar.getEvent(1,"cal1")','GettingCalendarObject'); + // } finally { + // await this.driver.switchTo().defaultContent(); + // } + // } + + public async inCustomWidget(op: () => Promise): Promise { + const iframe = driver.find('iframe'); + try { + await this.driver.switchTo().frame(iframe); + return await op(); + } finally { + await driver.switchTo().defaultContent(); + } + } } From 4b621484d60f948a5c08e2a17a019516ebff4e88 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Mon, 7 Aug 2023 15:37:53 +0200 Subject: [PATCH 27/64] calendar refactor --- calendar/page.js | 256 +++++++++++++++++++++++++---------------------- test/calendar.ts | 2 +- 2 files changed, 139 insertions(+), 119 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 1862d75e..015c724d 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -1,3 +1,5 @@ +// grist is imported in html, so it is available here. +var grist; function ready(fn) { if (document.readyState !== 'loading'){ fn(); @@ -12,66 +14,6 @@ let mainColor = getComputedStyle(document.documentElement) let selectedColor = getComputedStyle(document.documentElement) .getPropertyValue('--selected-color') -const columnsMappingOptions = [ - { - name: "startDate", // What field we will read. - title: "Start Date", // Friendly field name. - optional: false, // Is this an optional field. - type: "DateTime", // What type of column we expect. - description: "starting point of event", // Description of a field. - allowMultiple: false // Allows multiple column assignment. - }, - { - name: "endDate", - title: "End Date", - optional: false, - type: "DateTime", - description: "ending point of event", - allowMultiple: false - }, - { - name: "title", - title: "Title", - optional: false, - type: "Text", - description: "title of event", - allowMultiple: false - }, - { - name: "isAllDay", - title: "Is All Day", - optional: true, - type: "Bool", - description: "is event all day long", - } -]; - - -const options = { - week: { - taskView: false, - }, - month: {}, - defaultView: 'week', - template: { - time(event) { - const {title} = event; - - return `${title}`; - }, - allday(event) { - return `${event.title}`; - }, - }, - calendars: [ - { - id: 'cal1', - name: 'Personal', - backgroundColor: mainColor, - }, - ], -} - async function calendarViewChanges(radiobutton){ await grist.setOption('calendarViewPerspective', radiobutton.value); } @@ -82,73 +24,150 @@ function mapCalendarEventToGristObject(event){ return{id:event.id, fields: mappedRecord }; } -let Calendar let selectedRecordId = null; -ready(function() { +let Calendar = null; + + + +async function configureGristSettings() { + const columnsMappingOptions = [ + { + name: "startDate", // What field we will read. + title: "Start Date", // Friendly field name. + optional: false, // Is this an optional field. + type: "DateTime", // What type of column we expect. + description: "starting point of event", // Description of a field. + allowMultiple: false // Allows multiple column assignment. + }, + { + name: "endDate", + title: "End Date", + optional: false, + type: "DateTime", + description: "ending point of event", + allowMultiple: false + }, + { + name: "title", + title: "Title", + optional: false, + type: "Text", + description: "title of event", + allowMultiple: false + }, + { + name: "isAllDay", + title: "Is All Day", + optional: true, + type: "Bool", + description: "is event all day long", + } + ]; + + await grist.allowSelectBy(); + grist.onRecords(updateCalendar); + grist.onRecord(gristRecordChanged); + grist.onOptions(onGristSettingsChanged); + grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); +} + +let gristRecordChanged = (record, mappings) => { + const mappedRecord = grist.mapColumnNames(record, mappings); + if(mappedRecord) { + Calendar.setDate(mappedRecord.startDate); + if(selectedRecordId){ + Calendar.updateEvent(selectedRecordId, 'cal1',{backgroundColor: mainColor}); + } + Calendar.updateEvent(mappedRecord.id, 'cal1',{backgroundColor: selectedColor}); + selectedRecordId = mappedRecord.id; + } + var dom = document.querySelector('.toastui-calendar-time'); + const middleHour = mappedRecord.startDate.getHours() + + (mappedRecord.endDate.getHours() - mappedRecord.startDate.getHours())/2; + dom.scrollTo({top: (dom.clientHeight/24)*middleHour, behavior: 'smooth'}); +}; + +let onGristSettingsChanged = function (options) { + if(options.calendarViewPerspective){ + Calendar.changeView(options.calendarViewPerspective); + selectRadioButton(options.calendarViewPerspective); + } +}; + + + +function configureCalendar() { const container = document.getElementById('calendar'); + // ToastUI calendar settings - https://nhn.github.io/tui.calendar/latest/Calendar + const options = { + week: { + taskView: false, + }, + month: {}, + defaultView: 'week', + template: { + time(event) { + const {title} = event; + return `${title}`; + }, + allday(event) { + const {title} = event; + return `${title}`; + }, + }, + calendars: [ + { + id: 'cal1', + name: 'Personal', + backgroundColor: mainColor, + }, + ], + } // Update the widget anytime the document data changes. Calendar = new tui.Calendar(container, options); - grist.allowSelectBy(); - grist.onRecords(updateCalendar); - grist.onRecord((record, mappings) => { - const mappedRecord = grist.mapColumnNames(record, mappings); - if(mappedRecord) { - Calendar.setDate(mappedRecord.startDate); - if(selectedRecordId){ - Calendar.updateEvent(selectedRecordId, 'cal1',{backgroundColor: mainColor}); - } - Calendar.updateEvent(mappedRecord.id, 'cal1',{backgroundColor: selectedColor}); - selectedRecordId = mappedRecord.id; - } - var dom = document.querySelector('.toastui-calendar-time'); - const middleHour = mappedRecord.startDate.getHours() - + (mappedRecord.endDate.getHours() - mappedRecord.startDate.getHours())/2; - dom.scrollTo({top: (dom.clientHeight/24)*middleHour, behavior: 'smooth'}); - }); - grist.onOptions(function (options, interaction) { - if(options.calendarViewPerspective){ - Calendar.changeView(options.calendarViewPerspective); - selectRadioButton(options.calendarViewPerspective); - } + Calendar.on('beforeUpdateEvent', onCalendarEventBeingUpdated); + Calendar.on('clickEvent', async (info) => { + grist.setSelectedRows([info.event.id]); }); - Calendar.on('beforeUpdateEvent', async (info) => { - if (info.changes) { - if (info.changes.start || info.changes.end) { - const record = await grist.fetchSelectedRecord(info.event.id) - if (record) { - const gristEvent ={ - startDate:(info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000, - endDate: (info.changes.end?.valueOf() ?? info.event.end.valueOf()) / 1000, - isAllday: info.changes.isAllday ?? info.event.isAllday, - title: info.changes.title ?? info.event.title, - id: record.id, - } - const mappedRecord = mapCalendarEventToGristObject(gristEvent); - const table = await grist.getTable(); - await table.update(mappedRecord); + Calendar.on('selectDateTime', onNewDateBeingSelectedOnCalendar); + return Calendar; +} +const onCalendarEventBeingUpdated = async (info) => { + if (info.changes) { + if (info.changes.start || info.changes.end) { + const record = await grist.fetchSelectedRecord(info.event.id) + if (record) { + const gristEvent = { + startDate: (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000, + endDate: (info.changes.end?.valueOf() ?? info.event.end.valueOf()) / 1000, + isAllday: info.changes.isAllday ?? info.event.isAllday, + title: info.changes.title ?? info.event.title, + id: record.id, } + const mappedRecord = mapCalendarEventToGristObject(gristEvent); + const table = await grist.getTable(); + await table.update(mappedRecord); + } } - }); - Calendar.on('clickEvent', async (info) => { - grist.setSelectedRows([info.event.id]); - }); - // Registering an instance event - Calendar.on('selectDateTime', async (info) => { - const gristEvent ={ - startDate:info.start?.valueOf() / 1000, - endDate: info.end?.valueOf() / 1000, - isAllDay: info.isAllday?1:0, - title: "New Event" - } - - const table = await grist.getTable(); - await table.create(mapCalendarEventToGristObject(gristEvent)); - Calendar.clearGridSelections(); - }); - grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); - + } +}; + +const onNewDateBeingSelectedOnCalendar = async (info) => { + const gristEvent = { + startDate: info.start?.valueOf() / 1000, + endDate: info.end?.valueOf() / 1000, + isAllDay: info.isAllday ? 1 : 0, + title: "New Event" + } + const table = await grist.getTable(); + await table.create(mapCalendarEventToGristObject(gristEvent)); + Calendar.clearGridSelections(); +} +ready(function() { + configureGristSettings(); + Calendar = configureCalendar(); }); function selectRadioButton(value){ @@ -173,6 +192,7 @@ function calendarToday(){ let previousIds= []; function updateCalendar(records,mappings) { + const mappedRecords = grist.mapColumnNames(records, mappings); if(mappedRecords) { diff --git a/test/calendar.ts b/test/calendar.ts index aaa86aba..652d2847 100644 --- a/test/calendar.ts +++ b/test/calendar.ts @@ -15,7 +15,7 @@ function getAbstractFromCalendarObject(eventId: number) { }else{ return calendarObject }` -}; +} describe('calendar', function () { this.timeout(20000); From f2ebcf59b62093b295fb05ab469eeea3e04e8d44 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Mon, 7 Aug 2023 16:49:19 +0200 Subject: [PATCH 28/64] refactor - selecting event to mark --- calendar/page.js | 163 ++++++++++++++++++++++------------------------- 1 file changed, 77 insertions(+), 86 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 015c724d..5529ca62 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -1,43 +1,39 @@ -// grist is imported in html, so it is available here. +// lets assume that it's imported in a html file var grist; -function ready(fn) { - if (document.readyState !== 'loading'){ - fn(); - } else { - document.addEventListener('DOMContentLoaded', fn); - } -} + +document.addEventListener('DOMContentLoaded', function() { + configureGristSettings(); + Calendar = configureCalendar(); +}); + let mainColor = getComputedStyle(document.documentElement) - .getPropertyValue('--main-color') + .getPropertyValue('--main-color'); let selectedColor = getComputedStyle(document.documentElement) - .getPropertyValue('--selected-color') + .getPropertyValue('--selected-color'); -async function calendarViewChanges(radiobutton){ +async function calendarViewChanges(radiobutton) { await grist.setOption('calendarViewPerspective', radiobutton.value); } -function mapCalendarEventToGristObject(event){ +function mapCalendarEventToGristObject(event) { const mappedRecord = grist.mapColumnNamesBack(event); delete mappedRecord.id; - return{id:event.id, fields: mappedRecord }; + return { id: event.id, fields: mappedRecord }; } -let selectedRecordId = null; let Calendar = null; - - -async function configureGristSettings() { - const columnsMappingOptions = [ +function getGristOptions() { + return [ { - name: "startDate", // What field we will read. - title: "Start Date", // Friendly field name. - optional: false, // Is this an optional field. - type: "DateTime", // What type of column we expect. - description: "starting point of event", // Description of a field. - allowMultiple: false // Allows multiple column assignment. + name: "startDate", + title: "Start Date", + optional: false, + type: "DateTime", + description: "starting point of event", + allowMultiple: false }, { name: "endDate", @@ -63,43 +59,43 @@ async function configureGristSettings() { description: "is event all day long", } ]; +} - await grist.allowSelectBy(); +async function configureGristSettings() { + const columnsMappingOptions = getGristOptions(); + + grist.allowSelectBy(); grist.onRecords(updateCalendar); grist.onRecord(gristRecordChanged); grist.onOptions(onGristSettingsChanged); - grist.ready({requiredAccess: 'read table', columns: columnsMappingOptions}); + grist.ready({ requiredAccess: 'read table', columns: columnsMappingOptions }); } -let gristRecordChanged = (record, mappings) => { - const mappedRecord = grist.mapColumnNames(record, mappings); - if(mappedRecord) { - Calendar.setDate(mappedRecord.startDate); - if(selectedRecordId){ - Calendar.updateEvent(selectedRecordId, 'cal1',{backgroundColor: mainColor}); + function gristRecordChanged(record, mappings) { + const mappedRecord = grist.mapColumnNames(record, mappings); + if (mappedRecord) { + Calendar.setDate(mappedRecord.startDate); + if (this._selectedRecordId) { + Calendar.updateEvent(this._selectedRecordId, 'cal1', {backgroundColor: mainColor}); + } + Calendar.updateEvent(mappedRecord.id, 'cal1', {backgroundColor: selectedColor}); + this._selectedRecordId = mappedRecord.id; } - Calendar.updateEvent(mappedRecord.id, 'cal1',{backgroundColor: selectedColor}); - selectedRecordId = mappedRecord.id; + var dom = document.querySelector('.toastui-calendar-time'); + const middleHour = mappedRecord.startDate.getHours() + + (mappedRecord.endDate.getHours() - mappedRecord.startDate.getHours()) / 2; + dom.scrollTo({top: (dom.clientHeight / 24) * middleHour, behavior: 'smooth'}); } - var dom = document.querySelector('.toastui-calendar-time'); - const middleHour = mappedRecord.startDate.getHours() - + (mappedRecord.endDate.getHours() - mappedRecord.startDate.getHours())/2; - dom.scrollTo({top: (dom.clientHeight/24)*middleHour, behavior: 'smooth'}); -}; -let onGristSettingsChanged = function (options) { - if(options.calendarViewPerspective){ +let onGristSettingsChanged = function(options) { + if (options.calendarViewPerspective) { Calendar.changeView(options.calendarViewPerspective); selectRadioButton(options.calendarViewPerspective); } }; - - -function configureCalendar() { - const container = document.getElementById('calendar'); - // ToastUI calendar settings - https://nhn.github.io/tui.calendar/latest/Calendar - const options = { +function getCalendarOptions() { + return { week: { taskView: false, }, @@ -122,8 +118,12 @@ function configureCalendar() { backgroundColor: mainColor, }, ], - } - // Update the widget anytime the document data changes. + }; +} + +function configureCalendar() { + const container = document.getElementById('calendar'); + const options = getCalendarOptions() Calendar = new tui.Calendar(container, options); Calendar.on('beforeUpdateEvent', onCalendarEventBeingUpdated); Calendar.on('clickEvent', async (info) => { @@ -165,68 +165,59 @@ const onNewDateBeingSelectedOnCalendar = async (info) => { await table.create(mapCalendarEventToGristObject(gristEvent)); Calendar.clearGridSelections(); } -ready(function() { - configureGristSettings(); - Calendar = configureCalendar(); -}); -function selectRadioButton(value){ - for(const element of document.getElementsByName('calendar-options')){ - if(element.value === value){ +function selectRadioButton(value) { + for (const element of document.getElementsByName('calendar-options')) { + if (element.value === value) { element.checked = true; } } } -function calendarPrevious(){ +function calendarPrevious() { Calendar.prev(); } -function calendarNext(){ +function calendarNext() { Calendar.next(); } -function calendarToday(){ +function calendarToday() { Calendar.today(); } -let previousIds= []; -function updateCalendar(records,mappings) { - +let previousIds = new Set(); +function updateCalendar(records, mappings) { const mappedRecords = grist.mapColumnNames(records, mappings); - if(mappedRecords) { + if (mappedRecords) { + const currentIds = new Set(); for (const record of mappedRecords) { - const event = Calendar.getEvent(record.id, 'cal1'); // EventObject + const event = Calendar.getEvent(record.id, 'cal1'); + const eventData = { + id: record.id, + calendarId: 'cal1', + title: record.title, + start: record.startDate, + end: record.endDate, + isAllday: record.isAllDay, + category: 'time', + state: 'Free', + }; + if (!event) { - Calendar.createEvents([ - { - id: record.id, - calendarId: 'cal1', - title: record.title, - start: record.startDate, - end: record.endDate, - isAllday: record.isAllDay, - category: 'time', - state: 'Free', - }, - ]); + Calendar.createEvents([eventData]); } else { - Calendar.updateEvent(record.id, 'cal1', { - title: record.title, - start: record.startDate, - end: record.endDate, - isAllday: record.isAllDay, - }) + Calendar.updateEvent(record.id, 'cal1', eventData); } + currentIds.add(record.id); } + for (const id of previousIds) { - if (!mappedRecords.find(record => record.id === id)) { + if (!currentIds.has(id)) { Calendar.deleteEvent(id, 'cal1'); } } - previousIds = new Set(mappedRecords.map(record => record.id)); + previousIds = currentIds; } } - - From 0d10535d278b33149c850bd30015540c7ed734f5 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Mon, 7 Aug 2023 17:16:50 +0200 Subject: [PATCH 29/64] move part of the code to the class to give it some structure --- calendar/page.js | 140 ++++++++++++++++++++++++++--------------------- 1 file changed, 79 insertions(+), 61 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 5529ca62..ca2721b3 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -1,17 +1,13 @@ // lets assume that it's imported in a html file var grist; -document.addEventListener('DOMContentLoaded', function() { +document.addEventListener('DOMContentLoaded', ()=> { + this.calendarHandler = new CalendarHandler(); + Calendar = this.calendarHandler.calendar; configureGristSettings(); - Calendar = configureCalendar(); -}); - -let mainColor = getComputedStyle(document.documentElement) - .getPropertyValue('--main-color'); +}); -let selectedColor = getComputedStyle(document.documentElement) - .getPropertyValue('--selected-color'); async function calendarViewChanges(radiobutton) { await grist.setOption('calendarViewPerspective', radiobutton.value); @@ -23,7 +19,65 @@ function mapCalendarEventToGristObject(event) { return { id: event.id, fields: mappedRecord }; } -let Calendar = null; +let Calendar +class CalendarHandler { + static _mainColor = getComputedStyle(document.documentElement) + .getPropertyValue('--main-color'); + + static _selectedColor = getComputedStyle(document.documentElement) + .getPropertyValue('--selected-color'); + static getCalendarOptions() { + return { + week: { + taskView: false, + }, + month: {}, + defaultView: 'week', + template: { + time(event) { + const {title} = event; + return `${title}`; + }, + allday(event) { + const {title} = event; + return `${title}`; + }, + }, + calendars: [ + { + id: 'cal1', + name: 'Personal', + backgroundColor: CalendarHandler._mainColor, + }, + ], + }; + } + constructor() { + const container = document.getElementById('calendar'); + const options = CalendarHandler.getCalendarOptions(); + this.calendar = new tui.Calendar(container, options); + this.calendar.on('beforeUpdateEvent', onCalendarEventBeingUpdated); + this.calendar.on('clickEvent', async (info) => { + grist.setSelectedRows([info.event.id]); + }); + this.calendar.on('selectDateTime', onNewDateBeingSelectedOnCalendar); + } + + + selectRecord(record) { + if (this._selectedRecordId) { + this.calendar.updateEvent(this._selectedRecordId, 'cal1', {backgroundColor: CalendarHandler._mainColor}); + } + this.calendar.updateEvent(record.id, 'cal1', {backgroundColor: CalendarHandler._selectedColor}); + this._selectedRecordId = record.id; + Calendar.setDate(record.startDate); + var dom = document.querySelector('.toastui-calendar-time'); + const middleHour = record.startDate.getHours() + + (record.endDate.getHours() - record.startDate.getHours()) / 2; + dom.scrollTo({top: (dom.clientHeight / 24) * middleHour, behavior: 'smooth'}); + + } +} function getGristOptions() { return [ @@ -66,72 +120,36 @@ async function configureGristSettings() { grist.allowSelectBy(); grist.onRecords(updateCalendar); - grist.onRecord(gristRecordChanged); + grist.onRecord(gristSelectedRecordChanged); grist.onOptions(onGristSettingsChanged); grist.ready({ requiredAccess: 'read table', columns: columnsMappingOptions }); } - function gristRecordChanged(record, mappings) { + function gristSelectedRecordChanged(record, mappings) { const mappedRecord = grist.mapColumnNames(record, mappings); - if (mappedRecord) { - Calendar.setDate(mappedRecord.startDate); - if (this._selectedRecordId) { - Calendar.updateEvent(this._selectedRecordId, 'cal1', {backgroundColor: mainColor}); - } - Calendar.updateEvent(mappedRecord.id, 'cal1', {backgroundColor: selectedColor}); - this._selectedRecordId = mappedRecord.id; + if (mappedRecord && this.calendarHandler) { + this.calendarHandler.selectRecord(mappedRecord); } - var dom = document.querySelector('.toastui-calendar-time'); - const middleHour = mappedRecord.startDate.getHours() - + (mappedRecord.endDate.getHours() - mappedRecord.startDate.getHours()) / 2; - dom.scrollTo({top: (dom.clientHeight / 24) * middleHour, behavior: 'smooth'}); } let onGristSettingsChanged = function(options) { - if (options.calendarViewPerspective) { + if (options?.calendarViewPerspective) { Calendar.changeView(options.calendarViewPerspective); selectRadioButton(options.calendarViewPerspective); } }; -function getCalendarOptions() { - return { - week: { - taskView: false, - }, - month: {}, - defaultView: 'week', - template: { - time(event) { - const {title} = event; - return `${title}`; - }, - allday(event) { - const {title} = event; - return `${title}`; - }, - }, - calendars: [ - { - id: 'cal1', - name: 'Personal', - backgroundColor: mainColor, - }, - ], - }; -} - -function configureCalendar() { - const container = document.getElementById('calendar'); - const options = getCalendarOptions() - Calendar = new tui.Calendar(container, options); - Calendar.on('beforeUpdateEvent', onCalendarEventBeingUpdated); - Calendar.on('clickEvent', async (info) => { - grist.setSelectedRows([info.event.id]); - }); - Calendar.on('selectDateTime', onNewDateBeingSelectedOnCalendar); - return Calendar; -} +// function configureCalendar() { +// const container = document.getElementById('calendar'); +// const options = getCalendarOptions() +// Calendar = new tui.Calendar(container, options); +// Calendar.on('beforeUpdateEvent', onCalendarEventBeingUpdated); +// Calendar.on('clickEvent', async (info) => { +// grist.setSelectedRows([info.event.id]); +// }); +// Calendar.on('selectDateTime', onNewDateBeingSelectedOnCalendar); +// return Calendar; +// } const onCalendarEventBeingUpdated = async (info) => { if (info.changes) { From a8ce80f14e55c006d952bb1669a739ab00cb7e43 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 04:11:05 +0200 Subject: [PATCH 30/64] refactoring editing and creating events form calendar --- calendar/index.html | 6 +-- calendar/page.js | 112 ++++++++++++++++++++++++-------------------- 2 files changed, 65 insertions(+), 53 deletions(-) diff --git a/calendar/index.html b/calendar/index.html index 0cf1dac6..18b7a012 100644 --- a/calendar/index.html +++ b/calendar/index.html @@ -11,9 +11,9 @@
- - - + + +
diff --git a/calendar/page.js b/calendar/page.js index ca2721b3..8f433dc7 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -8,12 +8,11 @@ document.addEventListener('DOMContentLoaded', ()=> { }); - async function calendarViewChanges(radiobutton) { await grist.setOption('calendarViewPerspective', radiobutton.value); } -function mapCalendarEventToGristObject(event) { +function convertEventToGristTableFormat(event) { const mappedRecord = grist.mapColumnNamesBack(event); delete mappedRecord.id; return { id: event.id, fields: mappedRecord }; @@ -64,19 +63,41 @@ class CalendarHandler { } + selectRecord(record) { if (this._selectedRecordId) { this.calendar.updateEvent(this._selectedRecordId, 'cal1', {backgroundColor: CalendarHandler._mainColor}); } this.calendar.updateEvent(record.id, 'cal1', {backgroundColor: CalendarHandler._selectedColor}); this._selectedRecordId = record.id; - Calendar.setDate(record.startDate); + this.calendar.setDate(record.startDate); var dom = document.querySelector('.toastui-calendar-time'); const middleHour = record.startDate.getHours() + (record.endDate.getHours() - record.startDate.getHours()) / 2; dom.scrollTo({top: (dom.clientHeight / 24) * middleHour, behavior: 'smooth'}); } + + changeView(calendarViewPerspective) { + Calendar.changeView(calendarViewPerspective); + } + + calendarPrevious() { + Calendar.prev(); + } + + calendarNext() { + Calendar.next(); + } + + calendarToday() { + Calendar.today(); + } + + + async onNewTimeSelected(aaa){ + + } } function getGristOptions() { @@ -133,54 +154,57 @@ async function configureGristSettings() { } let onGristSettingsChanged = function(options) { - if (options?.calendarViewPerspective) { - Calendar.changeView(options.calendarViewPerspective); - selectRadioButton(options.calendarViewPerspective); - } + let option = options?.calendarViewPerspective??'week'; + this.calendarHandler.changeView(option); + selectRadioButton(option); }; -// function configureCalendar() { -// const container = document.getElementById('calendar'); -// const options = getCalendarOptions() -// Calendar = new tui.Calendar(container, options); -// Calendar.on('beforeUpdateEvent', onCalendarEventBeingUpdated); -// Calendar.on('clickEvent', async (info) => { -// grist.setSelectedRows([info.event.id]); -// }); -// Calendar.on('selectDateTime', onNewDateBeingSelectedOnCalendar); -// return Calendar; -// } const onCalendarEventBeingUpdated = async (info) => { - if (info.changes) { - if (info.changes.start || info.changes.end) { - const record = await grist.fetchSelectedRecord(info.event.id) + if (info.changes?.start || info.changes?.end) { + const record = await grist.fetchSelectedRecord(info.event.id); if (record) { - const gristEvent = { - startDate: (info.changes.start?.valueOf() ?? info.event.start.valueOf()) / 1000, - endDate: (info.changes.end?.valueOf() ?? info.event.end.valueOf()) / 1000, - isAllday: info.changes.isAllday ?? info.event.isAllday, - title: info.changes.title ?? info.event.title, - id: record.id, - } - const mappedRecord = mapCalendarEventToGristObject(gristEvent); - const table = await grist.getTable(); - await table.update(mappedRecord); + const gristEvent = buildGristFlatFormatFromEventObject(info.event) + // { + // id: record.id, + // startDate: info.event.start.valueOf() / 1000, + // endDate: info.event.end.valueOf() / 1000, + // isAllDay: info.event.isAllday, + // title: info.event.title, + // } + if(info.changes.start) gristEvent.startDate = info.changes.start.valueOf() / 1000; + if(info.changes.end) gristEvent.endDate = info.changes.end.valueOf() / 1000; + await upsertGristRecord(gristEvent); } } - } }; -const onNewDateBeingSelectedOnCalendar = async (info) => { + +async function upsertGristRecord(gristEvent){ + const table = await grist.getTable(); + const eventInValidFormat = convertEventToGristTableFormat(gristEvent); + if (gristEvent.id) { + await table.update(eventInValidFormat); + } else { + await table.create(eventInValidFormat); + } +} +function buildGristFlatFormatFromEventObject(TUIEvent) { const gristEvent = { - startDate: info.start?.valueOf() / 1000, - endDate: info.end?.valueOf() / 1000, - isAllDay: info.isAllday ? 1 : 0, - title: "New Event" + startDate: TUIEvent.start?.valueOf() / 1000, + endDate: TUIEvent.end?.valueOf() / 1000, + isAllDay: TUIEvent.isAllday ? 1 : 0, + title: TUIEvent.title??"New Event" } + if(TUIEvent.id) gristEvent.id = TUIEvent.id; + return gristEvent; +} + +const onNewDateBeingSelectedOnCalendar = async (info) => { + const gristEvent = buildGristFlatFormatFromEventObject(info); const table = await grist.getTable(); - await table.create(mapCalendarEventToGristObject(gristEvent)); + await table.create(convertEventToGristTableFormat(gristEvent)); Calendar.clearGridSelections(); } @@ -192,18 +216,6 @@ function selectRadioButton(value) { } } -function calendarPrevious() { - Calendar.prev(); -} - -function calendarNext() { - Calendar.next(); -} - -function calendarToday() { - Calendar.today(); -} - let previousIds = new Set(); function updateCalendar(records, mappings) { const mappedRecords = grist.mapColumnNames(records, mappings); From 9effe1bbbc30c9382de3ed337b8f652519ad0414 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 04:58:59 +0200 Subject: [PATCH 31/64] refactor: creating calendar events moved into the class --- calendar/page.js | 122 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 38 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 8f433dc7..b19f8bb4 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -59,11 +59,12 @@ class CalendarHandler { this.calendar.on('clickEvent', async (info) => { grist.setSelectedRows([info.event.id]); }); - this.calendar.on('selectDateTime', onNewDateBeingSelectedOnCalendar); + this.calendar.on('selectDateTime', (info)=> { + onNewDateBeingSelectedOnCalendar(info); + this.calendar.clearGridSelections(); + }); } - - selectRecord(record) { if (this._selectedRecordId) { this.calendar.updateEvent(this._selectedRecordId, 'cal1', {backgroundColor: CalendarHandler._mainColor}); @@ -79,23 +80,62 @@ class CalendarHandler { } changeView(calendarViewPerspective) { - Calendar.changeView(calendarViewPerspective); + this.calendar.changeView(calendarViewPerspective); } calendarPrevious() { - Calendar.prev(); + this.calendar.prev(); } calendarNext() { - Calendar.next(); + this.calendar.next(); } calendarToday() { - Calendar.today(); + this.calendar.today(); } + async updateCalendarEvents(calendarEvents) { + const currentIds = new Set(); + for (const record of calendarEvents) { + const event = Calendar.getEvent(record.id, 'cal1'); + const eventData = record; - async onNewTimeSelected(aaa){ + if (!event) { + Calendar.createEvents([eventData]); + } else { + Calendar.updateEvent(record.id, 'cal1', eventData); + } + currentIds.add(record.id); + } + for (const id of this.previousIds) { + if (!currentIds.has(id)) { + Calendar.deleteEvent(id, 'cal1'); + } + } + this.previousIds = currentIds; + // //const mappedRecords = grist.mapColumnNames(records, mappings); + // // if any records was successfully mapped, create or update them in the calendar + // if (calendarEvents && calendarEvents.length) { + // const currentIds = new Set(); + // for (const record of calendarEvents) { + // const event = this.calendar.getEvent(record.id, 'cal1'); + // if (!event) { + // await this.calendar.createEvents(record); + // } else { + // await this.calendar.updateEvent(record.id, 'cal1', record); + // } + // currentIds.add(record.id); + // } + // //Checking if there are any events that are not in the grist table anymore, and delete them from the calendar + // for (const id of this.calendarEventsIds) { + // if (!currentIds.has(id)) { + // this.calendar.deleteEvent(id, 'cal1'); + // } + // } + // // update the current ids to reflect the new state + // this.calendarEventsIds = currentIds; + // } } } @@ -140,7 +180,7 @@ async function configureGristSettings() { const columnsMappingOptions = getGristOptions(); grist.allowSelectBy(); - grist.onRecords(updateCalendar); + grist.onRecords(updateCalendar2); grist.onRecord(gristSelectedRecordChanged); grist.onOptions(onGristSettingsChanged); grist.ready({ requiredAccess: 'read table', columns: columnsMappingOptions }); @@ -159,41 +199,35 @@ let onGristSettingsChanged = function(options) { selectRadioButton(option); }; - const onCalendarEventBeingUpdated = async (info) => { if (info.changes?.start || info.changes?.end) { const record = await grist.fetchSelectedRecord(info.event.id); if (record) { const gristEvent = buildGristFlatFormatFromEventObject(info.event) - // { - // id: record.id, - // startDate: info.event.start.valueOf() / 1000, - // endDate: info.event.end.valueOf() / 1000, - // isAllDay: info.event.isAllday, - // title: info.event.title, - // } - if(info.changes.start) gristEvent.startDate = info.changes.start.valueOf() / 1000; - if(info.changes.end) gristEvent.endDate = info.changes.end.valueOf() / 1000; + if(info.changes.start) gristEvent.startDate = roundEpochDateToSeconds(info.changes.start.valueOf()); + if(info.changes.end) gristEvent.endDate = roundEpochDateToSeconds(info.changes.end.valueOf()); await upsertGristRecord(gristEvent); } } }; - async function upsertGristRecord(gristEvent){ - const table = await grist.getTable(); const eventInValidFormat = convertEventToGristTableFormat(gristEvent); + const table = await grist.getTable(); if (gristEvent.id) { await table.update(eventInValidFormat); } else { await table.create(eventInValidFormat); } } +function roundEpochDateToSeconds(date) { + return date/1000; +} function buildGristFlatFormatFromEventObject(TUIEvent) { const gristEvent = { - startDate: TUIEvent.start?.valueOf() / 1000, - endDate: TUIEvent.end?.valueOf() / 1000, + startDate: roundEpochDateToSeconds(TUIEvent.start?.valueOf()), + endDate: roundEpochDateToSeconds(TUIEvent.end?.valueOf()), isAllDay: TUIEvent.isAllday ? 1 : 0, title: TUIEvent.title??"New Event" } @@ -202,10 +236,8 @@ function buildGristFlatFormatFromEventObject(TUIEvent) { } const onNewDateBeingSelectedOnCalendar = async (info) => { - const gristEvent = buildGristFlatFormatFromEventObject(info); - const table = await grist.getTable(); - await table.create(convertEventToGristTableFormat(gristEvent)); - Calendar.clearGridSelections(); + const gristEvent = buildGristFlatFormatFromEventObject(info); + upsertGristRecord(gristEvent); } function selectRadioButton(value) { @@ -216,24 +248,38 @@ function selectRadioButton(value) { } } + +function buildCalendarEventObject(record) { + return { + id: record.id, + calendarId: 'cal1', + title: record.title, + start: record.startDate, + end: record.endDate, + isAllday: record.isAllDay, + category: 'time', + state: 'Free', + }; +} + +async function updateCalendar2(records, mappings) { + const mappedRecords = grist.mapColumnNames(records, mappings); + // if any records was successfully mapped, create or update them in the calendar + if (mappedRecords) { + const CalendarEventObjects = mappedRecords.map(buildCalendarEventObject); + await this.calendarHandler.updateCalendarEvents(CalendarEventObjects); + } +} + let previousIds = new Set(); function updateCalendar(records, mappings) { const mappedRecords = grist.mapColumnNames(records, mappings); if (mappedRecords) { const currentIds = new Set(); - for (const record of mappedRecords) { + for (const record of mappedRecords.map(buildCalendarEventObject)) { const event = Calendar.getEvent(record.id, 'cal1'); - const eventData = { - id: record.id, - calendarId: 'cal1', - title: record.title, - start: record.startDate, - end: record.endDate, - isAllday: record.isAllDay, - category: 'time', - state: 'Free', - }; + const eventData = record; if (!event) { Calendar.createEvents([eventData]); From c7c8f2b42106e425a500ef41a267e7443065d295 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 05:04:48 +0200 Subject: [PATCH 32/64] refactor: remove global Calendar variable --- calendar/page.js | 66 ++++++------------------------------------------ 1 file changed, 8 insertions(+), 58 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index b19f8bb4..7317115e 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -3,7 +3,6 @@ var grist; document.addEventListener('DOMContentLoaded', ()=> { this.calendarHandler = new CalendarHandler(); - Calendar = this.calendarHandler.calendar; configureGristSettings(); }); @@ -18,7 +17,6 @@ function convertEventToGristTableFormat(event) { return { id: event.id, fields: mappedRecord }; } -let Calendar class CalendarHandler { static _mainColor = getComputedStyle(document.documentElement) .getPropertyValue('--main-color'); @@ -98,45 +96,24 @@ class CalendarHandler { async updateCalendarEvents(calendarEvents) { const currentIds = new Set(); for (const record of calendarEvents) { - const event = Calendar.getEvent(record.id, 'cal1'); + const event = this.calendar.getEvent(record.id, 'cal1'); const eventData = record; if (!event) { - Calendar.createEvents([eventData]); + this.calendar.createEvents([eventData]); } else { - Calendar.updateEvent(record.id, 'cal1', eventData); + this.calendar.updateEvent(record.id, 'cal1', eventData); } currentIds.add(record.id); } - for (const id of this.previousIds) { - if (!currentIds.has(id)) { - Calendar.deleteEvent(id, 'cal1'); + if(this.previousIds) { + for (const id of this.previousIds) { + if (!currentIds.has(id)) { + this.calendar.deleteEvent(id, 'cal1'); + } } } this.previousIds = currentIds; - // //const mappedRecords = grist.mapColumnNames(records, mappings); - // // if any records was successfully mapped, create or update them in the calendar - // if (calendarEvents && calendarEvents.length) { - // const currentIds = new Set(); - // for (const record of calendarEvents) { - // const event = this.calendar.getEvent(record.id, 'cal1'); - // if (!event) { - // await this.calendar.createEvents(record); - // } else { - // await this.calendar.updateEvent(record.id, 'cal1', record); - // } - // currentIds.add(record.id); - // } - // //Checking if there are any events that are not in the grist table anymore, and delete them from the calendar - // for (const id of this.calendarEventsIds) { - // if (!currentIds.has(id)) { - // this.calendar.deleteEvent(id, 'cal1'); - // } - // } - // // update the current ids to reflect the new state - // this.calendarEventsIds = currentIds; - // } - } } @@ -270,30 +247,3 @@ async function updateCalendar2(records, mappings) { await this.calendarHandler.updateCalendarEvents(CalendarEventObjects); } } - -let previousIds = new Set(); -function updateCalendar(records, mappings) { - const mappedRecords = grist.mapColumnNames(records, mappings); - - if (mappedRecords) { - const currentIds = new Set(); - for (const record of mappedRecords.map(buildCalendarEventObject)) { - const event = Calendar.getEvent(record.id, 'cal1'); - const eventData = record; - - if (!event) { - Calendar.createEvents([eventData]); - } else { - Calendar.updateEvent(record.id, 'cal1', eventData); - } - currentIds.add(record.id); - } - - for (const id of previousIds) { - if (!currentIds.has(id)) { - Calendar.deleteEvent(id, 'cal1'); - } - } - previousIds = currentIds; - } -} From 9efdf7a2647f82b199b11566f6169db37ed0543e Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 05:25:53 +0200 Subject: [PATCH 33/64] comments --- calendar/page.js | 85 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 24 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 7317115e..8682d3b7 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -1,22 +1,6 @@ // lets assume that it's imported in a html file var grist; -document.addEventListener('DOMContentLoaded', ()=> { - this.calendarHandler = new CalendarHandler(); - configureGristSettings(); - -}); - -async function calendarViewChanges(radiobutton) { - await grist.setOption('calendarViewPerspective', radiobutton.value); -} - -function convertEventToGristTableFormat(event) { - const mappedRecord = grist.mapColumnNamesBack(event); - delete mappedRecord.id; - return { id: event.id, fields: mappedRecord }; -} - class CalendarHandler { static _mainColor = getComputedStyle(document.documentElement) .getPropertyValue('--main-color'); @@ -63,6 +47,7 @@ class CalendarHandler { }); } + // navigate to the selected date in the calendar and scroll to the time period of the event selectRecord(record) { if (this._selectedRecordId) { this.calendar.updateEvent(this._selectedRecordId, 'cal1', {backgroundColor: CalendarHandler._mainColor}); @@ -77,28 +62,36 @@ class CalendarHandler { } + // change calendar perspective between week, month and day. changeView(calendarViewPerspective) { this.calendar.changeView(calendarViewPerspective); } + // navigate to the previous time period calendarPrevious() { this.calendar.prev(); } + // navigate to the next time period calendarNext() { this.calendar.next(); } + //navigate to today calendarToday() { this.calendar.today(); } + // update calendar events based on the collection of records from the grist table. async updateCalendarEvents(calendarEvents) { + // we need to keep track of the ids of the events that are currently in the calendar to compare it + // with the new set of events when they come. const currentIds = new Set(); + for (const record of calendarEvents) { + //chek if event already exist in the calendar - update it if so, create new otherwise const event = this.calendar.getEvent(record.id, 'cal1'); const eventData = record; - if (!event) { this.calendar.createEvents([eventData]); } else { @@ -106,6 +99,7 @@ class CalendarHandler { } currentIds.add(record.id); } + // if some events are not in the new set of events, we need to remove them from the calendar if(this.previousIds) { for (const id of this.previousIds) { if (!currentIds.has(id)) { @@ -117,6 +111,22 @@ class CalendarHandler { } } +// when document is ready, register calendar and subscribe to grist events +document.addEventListener('DOMContentLoaded', ()=> { + this.calendarHandler = new CalendarHandler(); + configureGristSettings(); +}); + +//to update the table, grist require other format that it is returning in onRecords event (it's flat there), +// so it need to be converted +function convertEventToGristTableFormat(event) { + const mappedRecord = grist.mapColumnNamesBack(event); + // we cannot save record is some unexpected columns are defined in fields, so we need to remove them + delete mappedRecord.id; + return { id: event.id, fields: mappedRecord }; +} + +// Data for column mapping fileds in Widget GUI function getGristOptions() { return [ { @@ -153,34 +163,52 @@ function getGristOptions() { ]; } +// let subscribe all the events that we need async function configureGristSettings() { - const columnsMappingOptions = getGristOptions(); - + // table selection should change when other event is selected grist.allowSelectBy(); - grist.onRecords(updateCalendar2); + // CRUD operations on records in table + grist.onRecords(updateCalendar); + // When cursor (selected record) change in the table grist.onRecord(gristSelectedRecordChanged); + // When options changed in the widget configuration (reaction to perspective change) grist.onOptions(onGristSettingsChanged); + + // bind columns mapping options to the GUI + const columnsMappingOptions = getGristOptions(); grist.ready({ requiredAccess: 'read table', columns: columnsMappingOptions }); } +// when user select record in the table, we want to select it on the calendar function gristSelectedRecordChanged(record, mappings) { const mappedRecord = grist.mapColumnNames(record, mappings); if (mappedRecord && this.calendarHandler) { this.calendarHandler.selectRecord(mappedRecord); } - } +} + +// when user change the perspective in the GUI, we want to save it as grist option +// - rest of logic is in reaction to grist option changed +async function calendarViewChanges(radiobutton) { + await grist.setOption('calendarViewPerspective', radiobutton.value); +} + +// when user change a perspective of calendar we want this to be persisted in grist options between sessions. +// This is the place where we can react to this change and update calendar view, or when new session is started +// (so we are loading previous settings) let onGristSettingsChanged = function(options) { let option = options?.calendarViewPerspective??'week'; this.calendarHandler.changeView(option); selectRadioButton(option); }; +// when user move or resize event on the calendar, we want to update the record in the table const onCalendarEventBeingUpdated = async (info) => { if (info.changes?.start || info.changes?.end) { const record = await grist.fetchSelectedRecord(info.event.id); if (record) { - + // get all the record data from the event, and update only start and end date const gristEvent = buildGristFlatFormatFromEventObject(info.event) if(info.changes.start) gristEvent.startDate = roundEpochDateToSeconds(info.changes.start.valueOf()); if(info.changes.end) gristEvent.endDate = roundEpochDateToSeconds(info.changes.end.valueOf()); @@ -189,6 +217,7 @@ const onCalendarEventBeingUpdated = async (info) => { } }; +// saving events to the table or updating existing one - basing on if ID is present or not in the send event async function upsertGristRecord(gristEvent){ const eventInValidFormat = convertEventToGristTableFormat(gristEvent); const table = await grist.getTable(); @@ -198,9 +227,14 @@ async function upsertGristRecord(gristEvent){ await table.create(eventInValidFormat); } } + +// grist expect date in seconds, but calendar is returning it in miliseconds, so we need to convert it function roundEpochDateToSeconds(date) { return date/1000; } + +// conversion between calendar event object and grist flat format (so the one that is returned in onRecords event +// and can be mapped by grist.mapColumnNamesBack) function buildGristFlatFormatFromEventObject(TUIEvent) { const gristEvent = { startDate: roundEpochDateToSeconds(TUIEvent.start?.valueOf()), @@ -212,11 +246,13 @@ function buildGristFlatFormatFromEventObject(TUIEvent) { return gristEvent; } +// when user select new date range on the calendar, we want to create new record in the table const onNewDateBeingSelectedOnCalendar = async (info) => { const gristEvent = buildGristFlatFormatFromEventObject(info); upsertGristRecord(gristEvent); } +//helper function to select radio button in the GUI function selectRadioButton(value) { for (const element of document.getElementsByName('calendar-options')) { if (element.value === value) { @@ -225,7 +261,7 @@ function selectRadioButton(value) { } } - +// helper function to build calendar event object from grist flat record function buildCalendarEventObject(record) { return { id: record.id, @@ -239,7 +275,8 @@ function buildCalendarEventObject(record) { }; } -async function updateCalendar2(records, mappings) { +// when some CRUD operation is performed on the table, we want to update calendar +async function updateCalendar(records, mappings) { const mappedRecords = grist.mapColumnNames(records, mappings); // if any records was successfully mapped, create or update them in the calendar if (mappedRecords) { From ddbdb8a30dce686bc61beb44ec7d14d979c54b4f Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 05:35:35 +0200 Subject: [PATCH 34/64] test fix after refactor --- test/calendar.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/calendar.ts b/test/calendar.ts index 652d2847..542fea01 100644 --- a/test/calendar.ts +++ b/test/calendar.ts @@ -1,9 +1,10 @@ import {assert} from 'mocha-webdriver'; import {getGrist} from "./getGrist"; +//not to pretty way to get events from currently used calendar control. but it's working. function getAbstractFromCalendarObject(eventId: number) { return ` - const calendarObject = Calendar.getEvent(${eventId},"cal1"); + const calendarObject = this.calendarHandler.calendar.getEvent(${eventId},"cal1"); if(calendarObject) { return{ From 269605c56ba578a40a7315f1c109383b39ab1f60 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 05:45:45 +0200 Subject: [PATCH 35/64] package.json updted --- package.json | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index b7726f7c..e5463f8e 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,38 @@ { "name": "grist-widget", - "version": "0.0.1", + "version": "0.0.2", "description": "A repository of grist custom widgets that have no back-end requirements.", "scripts": { - "build": "node ./_build/publish.js", + "build": "tsc --build && node ./buildtools/publish.js", "serve": "live-server --port=8585 --no-browser -q", - "build:dev": "node ./_build/publish.js http://localhost:8585", - "serve:dev": "live-server --port=8585 --no-browser -q --middleware=$(pwd)/_build/rewriteUrl.js", + "build:dev": "node ./buildtools/publish.js http://localhost:8585", + "build:test": "tsc --build && node ./buildtools/publish.js http://localhost:9998", + "serve:dev": "live-server --port=8585 --no-browser -q --middleware=$(pwd)/buildtools/rewriteUrl.js", "watch": "nodemon --ignore manifest.json -e js,json --exec 'npm run build:dev'", - "dev": "echo 'Starting local server and watching for changes.\nStart Grist with an environmental variable GRIST_WIDGET_LIST_URL=http://localhost:8585/manifest.json' && npm run watch 1> /dev/null & npm run serve:dev 1> /dev/null" + "dev": "echo 'Starting local server and watching for changes.\nStart Grist with an environmental variable GRIST_WIDGET_LIST_URL=http://localhost:8585/manifest.json' && npm run watch 1> /dev/null & npm run serve:dev 1> /dev/null", + "test": "docker image inspect gristlabs/grist --format 'gristlabs/grist image present' && NODE_PATH=_build SELENIUM_BROWSER=chrome mocha _build/test/*.js" }, "devDependencies": { - "live-server": "1.2.1", - "nodemon": "^2.0.15" + "@types/chai": "^4.3.5", + "@types/mocha": "^10.0.1", + "@types/node": "^20.3.1", + "@types/node-fetch": "^2.6.4", + "@types/selenium-webdriver": "^4.1.15", + "chromedriver": "114", + "live-server": "^1.2.1", + "mocha": "^10.2.0", + "mocha-webdriver": "^0.2.13", + "node-fetch": "^2", + "nodemon": "^2.0.15", + "ts-node": "^10.9.1", + "typescript": "^5.1.3" + }, + "resolutions": { + "chromedriver": "114.0.2" + }, + "mocha": { + "require": [ + "_build/test/init-mocha-webdriver" + ] } } From 7177773b835c112e12e3762d45ba9e8e72badd50 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 05:50:20 +0200 Subject: [PATCH 36/64] cleanup of getGrist.ts --- test/getGrist.ts | 47 +++++++++++------------------------------------ 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/test/getGrist.ts b/test/getGrist.ts index c66d4db9..decd087b 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -7,7 +7,8 @@ import fetch from 'node-fetch'; import {GristWebDriverUtils} from 'test/gristWebDriverUtils'; -type UserAction = Array; +type UserAction = Array; + /** * Set up mocha hooks for starting and stopping Grist. Return * an interface for interacting with Grist. @@ -191,20 +192,6 @@ export class GristUtils extends GristWebDriverUtils { await this.waitForServer(); } - - - public async addRow(table: string, data: Record): Promise { - var fields = await driver.findElements(By.css(`.record-add .field`)); - const entities = Object.entries(data) - for (const col in entities) { - await fields[col].click(); - await driver.sendKeys(entities[col][1]); - await driver.sendKeys(Key.ENTER); - } - } - - - public async sendActions(actions: UserAction[]) { const result = await driver.executeAsyncScript(` const done = arguments[arguments.length - 1]; @@ -213,20 +200,19 @@ export class GristUtils extends GristWebDriverUtils { prom.catch((err) => done(String(err?.message || err))); `); if (result) { - throw new Error(result as string); + throw new Error(result as string); } await this.waitForServer(); - } - + } - public async waitForServer(optTimeout: number = 2000) { + public async waitForServer(optTimeout: number = 2000) { await this.driver.wait(() => this.driver.executeScript( - "return window.gristApp && (!window.gristApp.comm || !window.gristApp.comm.hasActiveRequests())" + "return window.gristApp && (!window.gristApp.comm || !window.gristApp.comm.hasActiveRequests())" + " && window.gristApp.testNumPendingApiRequests() === 0", - optTimeout, - "Timed out waiting for server requests to complete" + optTimeout, + "Timed out waiting for server requests to complete" )); - } + } public async clickWidgetPane() { const elem = this.driver.find('.test-config-widget-select .test-select-open'); @@ -274,11 +260,11 @@ export class GristUtils extends GristWebDriverUtils { } } - public async executeInIframe(fnc:(driver:WebDriver)=>void){ + public async executeInIframe(fnc: (driver: WebDriver) => void) { const iframe = this.driver.find('iframe'); try { await this.driver.switchTo().frame(iframe); - return await fnc(this.driver); + await fnc(this.driver); } finally { await this.driver.switchTo().defaultContent(); } @@ -295,17 +281,6 @@ export class GristUtils extends GristWebDriverUtils { } } - // Crude, assumes a single iframe. Should elaborate. - // public async getCustomWidgetX(selector: string = 'html'): Promise { - // const iframe = this.driver.find('iframe'); - // try { - // await this.driver.switchTo().frame(iframe); - // return await this.driver.execute('Calendar.getEvent(1,"cal1")','GettingCalendarObject'); - // } finally { - // await this.driver.switchTo().defaultContent(); - // } - // } - public async inCustomWidget(op: () => Promise): Promise { const iframe = driver.find('iframe'); try { From 302ca7690ce05259c32e87602563565a2d33e8c1 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 05:54:17 +0200 Subject: [PATCH 37/64] tab size and imports in getGrist.ts fixed --- test/getGrist.ts | 432 +++++++++++++++++++++++------------------------ 1 file changed, 216 insertions(+), 216 deletions(-) diff --git a/test/getGrist.ts b/test/getGrist.ts index decd087b..6bb90a7d 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -1,7 +1,7 @@ import {ChildProcess, execSync, spawn} from 'child_process'; import FormData from 'form-data'; import fs from 'fs'; -import {By, Key, WebDriver, driver} from 'mocha-webdriver'; +import {driver, WebDriver} from 'mocha-webdriver'; import fetch from 'node-fetch'; import {GristWebDriverUtils} from 'test/gristWebDriverUtils'; @@ -14,18 +14,18 @@ type UserAction = Array; * an interface for interacting with Grist. */ export function getGrist(): GristUtils { - const server = new GristTestServer(); - const grist = new GristUtils(server); + const server = new GristTestServer(); + const grist = new GristUtils(server); - before(async function () { - // Server will have started up in a global fixture, we just - // need to make sure it is ready. - // TODO: mocha-webdriver has a way of explicitly connecting a - // server that might have advantages for debugging. - await grist.wait(); - }); + before(async function () { + // Server will have started up in a global fixture, we just + // need to make sure it is ready. + // TODO: mocha-webdriver has a way of explicitly connecting a + // server that might have advantages for debugging. + await grist.wait(); + }); - return grist; + return grist; } /** @@ -37,11 +37,11 @@ export function getGrist(): GristUtils { * */ const serverSettings = { - gristContainerName: 'grist-test', - gristImage: 'gristlabs/grist', - gristPort: 9999, - contentPort: 9998, - site: 'grist-widget', + gristContainerName: 'grist-test', + gristImage: 'gristlabs/grist', + gristPort: 9999, + contentPort: 9998, + site: 'grist-widget', }; /** @@ -50,244 +50,244 @@ const serverSettings = { * by running live-server with some middleware. */ export class GristTestServer { - private _assetServer?: ChildProcess; + private _assetServer?: ChildProcess; - public async start() { - await this.stop(); - const {gristContainerName, gristImage, gristPort, contentPort} = serverSettings; - const cmd = `docker run -d --rm --name ${gristContainerName}` + - ` --network="host"` + - ` -e PORT=${gristPort} -p ${gristPort}:${gristPort}` + - ` -e GRIST_SINGLE_ORG=${serverSettings.site}` + - ` -e GRIST_WIDGET_LIST_URL=http://localhost:${contentPort}/manifest.json` + - ` ${gristImage}`; - try { - execSync(cmd, { - stdio: 'pipe' - }); - } catch (e) { - throw new Error( - `Failed to start Grist: ${cmd} (${e?.stderr.toString()})` - ); - } - const pwd = process.cwd(); - this._assetServer = spawn('live-server', [ - `--port=${contentPort}`, - `--middleware=${pwd}/buildtools/rewriteUrl.js`, - `-q`, - `--no-browser` - ], { - env: { - ...process.env, - GRIST_PORT: String(gristPort), - } - }); - } + public get gristUrl() { + const {gristPort} = serverSettings; + return `http://localhost:${gristPort}`; + } - public async stop() { - try { - execSync(`docker kill ${serverSettings.gristContainerName}`, { - stdio: 'pipe' - }); - } catch (e) { - // fine if kill fails, may not have been running. - } - try { - execSync(`docker rm ${serverSettings.gristContainerName}`, { - stdio: 'pipe' - }); - } catch (e) { - // fine if rm fails, may not actually exist. - } - if (this._assetServer) { - this._assetServer.kill(); - this._assetServer = undefined; - } - } + public get assetUrl() { + const {contentPort} = serverSettings; + return `http://localhost:${contentPort}`; + } - public get gristUrl() { - const {gristPort} = serverSettings; - return `http://localhost:${gristPort}`; + public async start() { + await this.stop(); + const {gristContainerName, gristImage, gristPort, contentPort} = serverSettings; + const cmd = `docker run -d --rm --name ${gristContainerName}` + + ` --network="host"` + + ` -e PORT=${gristPort} -p ${gristPort}:${gristPort}` + + ` -e GRIST_SINGLE_ORG=${serverSettings.site}` + + ` -e GRIST_WIDGET_LIST_URL=http://localhost:${contentPort}/manifest.json` + + ` ${gristImage}`; + try { + execSync(cmd, { + stdio: 'pipe' + }); + } catch (e) { + throw new Error( + `Failed to start Grist: ${cmd} (${e?.stderr.toString()})` + ); } + const pwd = process.cwd(); + this._assetServer = spawn('live-server', [ + `--port=${contentPort}`, + `--middleware=${pwd}/buildtools/rewriteUrl.js`, + `-q`, + `--no-browser` + ], { + env: { + ...process.env, + GRIST_PORT: String(gristPort), + } + }); + } - public get assetUrl() { - const {contentPort} = serverSettings; - return `http://localhost:${contentPort}`; + public async stop() { + try { + execSync(`docker kill ${serverSettings.gristContainerName}`, { + stdio: 'pipe' + }); + } catch (e) { + // fine if kill fails, may not have been running. + } + try { + execSync(`docker rm ${serverSettings.gristContainerName}`, { + stdio: 'pipe' + }); + } catch (e) { + // fine if rm fails, may not actually exist. + } + if (this._assetServer) { + this._assetServer.kill(); + this._assetServer = undefined; } + } } export class GristUtils extends GristWebDriverUtils { - public constructor(public server: GristTestServer) { - super(driver); - } + public constructor(public server: GristTestServer) { + super(driver); + } - public get url() { - return this.server.gristUrl; - } + public get url() { + return this.server.gristUrl; + } - public async wait() { - let ct = 0; - while (true) { - if (ct > 8) { - console.log("Waiting for Grist..."); - } - try { - const url = this.url; - const resp = await fetch(url + '/status'); - if (resp.status === 200) { - break; - } - } catch (e) { - // we expect fetch failures initially. - } - await new Promise(resolve => setTimeout(resolve, 250)); - ct++; + public async wait() { + let ct = 0; + while (true) { + if (ct > 8) { + console.log("Waiting for Grist..."); + } + try { + const url = this.url; + const resp = await fetch(url + '/status'); + if (resp.status === 200) { + break; } - ct = 0; - while (true) { - if (ct > 8) { - console.log("Waiting for asset server..."); - } - try { - const resp = await fetch(this.server.assetUrl); - if (resp.status === 200) { - break; - } - } catch (e) { - // we expect fetch failures initially. - } - await new Promise(resolve => setTimeout(resolve, 250)); - ct++; + } catch (e) { + // we expect fetch failures initially. + } + await new Promise(resolve => setTimeout(resolve, 250)); + ct++; + } + ct = 0; + while (true) { + if (ct > 8) { + console.log("Waiting for asset server..."); + } + try { + const resp = await fetch(this.server.assetUrl); + if (resp.status === 200) { + break; } + } catch (e) { + // we expect fetch failures initially. + } + await new Promise(resolve => setTimeout(resolve, 250)); + ct++; } + } - public async upload(gristFileName: string): Promise { - const endpoint = this.url + '/api/docs'; - const formData = new FormData(); - formData.append('upload', fs.createReadStream(gristFileName), 'sample.grist'); + public async upload(gristFileName: string): Promise { + const endpoint = this.url + '/api/docs'; + const formData = new FormData(); + formData.append('upload', fs.createReadStream(gristFileName), 'sample.grist'); - const response = await fetch(endpoint, { - method: 'POST', - body: formData, - headers: { - 'X-Requested-With': 'XMLHttpRequest', - } - }); + const response = await fetch(endpoint, { + method: 'POST', + body: formData, + headers: { + 'X-Requested-With': 'XMLHttpRequest', + } + }); - if (response.ok) { - const result = await response.json(); - if (typeof result !== 'string') { - throw new Error(`Unexpected response: ${result}`); - } - return result; - } else { - console.error('File upload failed. Status:', response.status); - throw new Error(`Upload failed: ${await response.json()}`); - } + if (response.ok) { + const result = await response.json(); + if (typeof result !== 'string') { + throw new Error(`Unexpected response: ${result}`); + } + return result; + } else { + console.error('File upload failed. Status:', response.status); + throw new Error(`Upload failed: ${await response.json()}`); } + } - public async openDoc(docId: string): Promise { - await driver.get(this.url + `/doc/${docId}`); - await driver.findWait('.viewsection_title', 10000); - await this.waitForServer(); - } + public async openDoc(docId: string): Promise { + await driver.get(this.url + `/doc/${docId}`); + await driver.findWait('.viewsection_title', 10000); + await this.waitForServer(); + } - public async sendActions(actions: UserAction[]) { - const result = await driver.executeAsyncScript(` + public async sendActions(actions: UserAction[]) { + const result = await driver.executeAsyncScript(` const done = arguments[arguments.length - 1]; const prom = gristDocPageModel.gristDoc.get().docModel.docData.sendActions(${JSON.stringify(actions)}); prom.then(() => done(null)); prom.catch((err) => done(String(err?.message || err))); `); - if (result) { - throw new Error(result as string); - } - await this.waitForServer(); + if (result) { + throw new Error(result as string); } + await this.waitForServer(); + } - public async waitForServer(optTimeout: number = 2000) { - await this.driver.wait(() => this.driver.executeScript( - "return window.gristApp && (!window.gristApp.comm || !window.gristApp.comm.hasActiveRequests())" - + " && window.gristApp.testNumPendingApiRequests() === 0", - optTimeout, - "Timed out waiting for server requests to complete" - )); - } + public async waitForServer(optTimeout: number = 2000) { + await this.driver.wait(() => this.driver.executeScript( + "return window.gristApp && (!window.gristApp.comm || !window.gristApp.comm.hasActiveRequests())" + + " && window.gristApp.testNumPendingApiRequests() === 0", + optTimeout, + "Timed out waiting for server requests to complete" + )); + } - public async clickWidgetPane() { - const elem = this.driver.find('.test-config-widget-select .test-select-open'); - if (await elem.isPresent()) { - await elem.click(); - // if not present, may just be already selected. - } + public async clickWidgetPane() { + const elem = this.driver.find('.test-config-widget-select .test-select-open'); + if (await elem.isPresent()) { + await elem.click(); + // if not present, may just be already selected. } + } - public async selectCustomWidget(text: string | RegExp) { - await this.driver.findContent('.test-select-menu li', text).click(); - await this.waitForServer(); - } + public async selectCustomWidget(text: string | RegExp) { + await this.driver.findContent('.test-select-menu li', text).click(); + await this.waitForServer(); + } - public async setCustomWidgetAccess(option: "none" | "read table" | "full") { - const text = { - "none": "No document access", - "read table": "Read selected table", - "full": "Full document access" - }; - await this.driver.find(`.test-config-widget-access .test-select-open`).click(); - await this.driver.findContent(`.test-select-menu li`, text[option]).click(); - } + public async setCustomWidgetAccess(option: "none" | "read table" | "full") { + const text = { + "none": "No document access", + "read table": "Read selected table", + "full": "Full document access" + }; + await this.driver.find(`.test-config-widget-access .test-select-open`).click(); + await this.driver.findContent(`.test-select-menu li`, text[option]).click(); + } - public async setCustomWidgetMapping(name: string, value: string | RegExp) { - const click = (selector: string) => driver.findWait(`${selector}`, 2000).click(); - const toggleDrop = (selector: string) => click(`${selector} .test-select-open`); - const pickerDrop = (name: string) => `.test-config-widget-mapping-for-${name}`; - await toggleDrop(pickerDrop(name)); - const clickOption = async (text: string | RegExp) => { - await driver.findContentWait('.test-select-menu li', text, 2000).click(); - await this.waitForServer(); - }; - await clickOption(value); - } + public async setCustomWidgetMapping(name: string, value: string | RegExp) { + const click = (selector: string) => driver.findWait(`${selector}`, 2000).click(); + const toggleDrop = (selector: string) => click(`${selector} .test-select-open`); + const pickerDrop = (name: string) => `.test-config-widget-mapping-for-${name}`; + await toggleDrop(pickerDrop(name)); + const clickOption = async (text: string | RegExp) => { + await driver.findContentWait('.test-select-menu li', text, 2000).click(); + await this.waitForServer(); + }; + await clickOption(value); + } - // Crude, assumes a single iframe. Should elaborate. - public async getCustomWidgetBody(selector: string = 'html'): Promise { - const iframe = this.driver.find('iframe'); - try { - await this.driver.switchTo().frame(iframe); - return await this.driver.find(selector).getText(); - } finally { - await this.driver.switchTo().defaultContent(); - } + // Crude, assumes a single iframe. Should elaborate. + public async getCustomWidgetBody(selector: string = 'html'): Promise { + const iframe = this.driver.find('iframe'); + try { + await this.driver.switchTo().frame(iframe); + return await this.driver.find(selector).getText(); + } finally { + await this.driver.switchTo().defaultContent(); } + } - public async executeInIframe(fnc: (driver: WebDriver) => void) { - const iframe = this.driver.find('iframe'); - try { - await this.driver.switchTo().frame(iframe); - await fnc(this.driver); - } finally { - await this.driver.switchTo().defaultContent(); - } + public async executeInIframe(fnc: (driver: WebDriver) => void) { + const iframe = this.driver.find('iframe'); + try { + await this.driver.switchTo().frame(iframe); + await fnc(this.driver); + } finally { + await this.driver.switchTo().defaultContent(); } + } - public async getCustomWidgetObject(script: string): Promise { - const iframe = this.driver.find('iframe'); - try { - await this.driver.switchTo().frame(iframe); - const jsValue = await this.driver.executeScript(script); - return await jsValue; - } finally { - await this.driver.switchTo().defaultContent(); - } + public async getCustomWidgetObject(script: string): Promise { + const iframe = this.driver.find('iframe'); + try { + await this.driver.switchTo().frame(iframe); + const jsValue = await this.driver.executeScript(script); + return await jsValue; + } finally { + await this.driver.switchTo().defaultContent(); } + } - public async inCustomWidget(op: () => Promise): Promise { - const iframe = driver.find('iframe'); - try { - await this.driver.switchTo().frame(iframe); - return await op(); - } finally { - await driver.switchTo().defaultContent(); - } + public async inCustomWidget(op: () => Promise): Promise { + const iframe = driver.find('iframe'); + try { + await this.driver.switchTo().frame(iframe); + return await op(); + } finally { + await driver.switchTo().defaultContent(); } + } } From 6a80bf51d1683898e5320720bffe38b396abfe93 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 13:32:44 +0200 Subject: [PATCH 38/64] main.yml improved to allow binding to the working server during tests --- .github/workflows/main.yml | 2 +- calendar/page.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1669d955..5b0cd14e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: run: yarn install - name: Build Node.js test code - run: yarn run build + run: yarn run build:test - name: Cache Docker images. uses: ScribeMD/docker-cache@0.3.3 diff --git a/calendar/page.js b/calendar/page.js index 8682d3b7..8090e771 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -39,7 +39,7 @@ class CalendarHandler { this.calendar = new tui.Calendar(container, options); this.calendar.on('beforeUpdateEvent', onCalendarEventBeingUpdated); this.calendar.on('clickEvent', async (info) => { - grist.setSelectedRows([info.event.id]); + await grist.setSelectedRows([info.event.id]); }); this.calendar.on('selectDateTime', (info)=> { onNewDateBeingSelectedOnCalendar(info); From a02880d82cbc29261d18abbdcd8dea48bc597995 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 15:37:29 +0200 Subject: [PATCH 39/64] package.json fixed --- package.json | 2 +- yarn.lock | 1988 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 1796 insertions(+), 194 deletions(-) diff --git a/package.json b/package.json index e5463f8e..137d79f6 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "build": "tsc --build && node ./buildtools/publish.js", "serve": "live-server --port=8585 --no-browser -q", "build:dev": "node ./buildtools/publish.js http://localhost:8585", - "build:test": "tsc --build && node ./buildtools/publish.js http://localhost:9998", "serve:dev": "live-server --port=8585 --no-browser -q --middleware=$(pwd)/buildtools/rewriteUrl.js", "watch": "nodemon --ignore manifest.json -e js,json --exec 'npm run build:dev'", "dev": "echo 'Starting local server and watching for changes.\nStart Grist with an environmental variable GRIST_WIDGET_LIST_URL=http://localhost:8585/manifest.json' && npm run watch 1> /dev/null & npm run serve:dev 1> /dev/null", @@ -30,6 +29,7 @@ "resolutions": { "chromedriver": "114.0.2" }, + "dependencies": {}, "mocha": { "require": [ "_build/test/init-mocha-webdriver" diff --git a/yarn.lock b/yarn.lock index 9f5ee120..bb478336 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,18 +2,211 @@ # yarn lockfile v1 +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@sindresorhus/is@^4.0.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@szmarczak/http-timer@^4.0.5": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" + integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== + dependencies: + defer-to-connect "^2.0.0" + +"@testim/chrome-version@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@testim/chrome-version/-/chrome-version-1.1.3.tgz#fbb68696899d7b8c1b9b891eded9c04fe2cd5529" + integrity sha512-g697J3WxV/Zytemz8aTuKjTGYtta9+02kva3C1xc7KXB8GdbfE1akGJIsZLyY/FSh2QrnE+fiB7vmWU3XNcb6A== + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/cacheable-request@^6.0.1": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" + integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "^3.1.4" + "@types/node" "*" + "@types/responselike" "^1.0.0" + +"@types/chai@^4.3.5": + version "4.3.5" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" + integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== + +"@types/http-cache-semantics@*": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" + integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== + +"@types/keyv@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" + integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== + dependencies: + "@types/node" "*" + +"@types/mocha@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.1.tgz#2f4f65bb08bc368ac39c96da7b2f09140b26851b" + integrity sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q== + +"@types/node-fetch@^2.6.4": + version "2.6.4" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" + integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*", "@types/node@^20.3.1": + version "20.3.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.1.tgz#e8a83f1aa8b649377bb1fb5d7bac5cb90e784dfe" + integrity sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg== + +"@types/responselike@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + +"@types/selenium-webdriver@^4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-4.1.15.tgz#d346b674b96f5ba43f1ad5343f997030559e5b23" + integrity sha512-oQ15G3q3EZ0dS049SB/5zx2tQkIS2kmDQWC/TSfAHJYKvXLZoUiLaPXnfSwbLP8Q5lcJeu5oYjKVSEV0t3H6Bg== + dependencies: + "@types/ws" "*" + +"@types/ws@*": + version "8.5.5" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb" + integrity sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg== + dependencies: + "@types/node" "*" + +"@types/yauzl@^2.9.1": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599" + integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw== + dependencies: + "@types/node" "*" + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== accepts@~1.3.4: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" + mime-types "~2.1.24" + negotiator "0.6.2" + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.9.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" + integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== + +adm-zip@0.5.9: + version "0.5.9" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.9.tgz#b33691028333821c0cf95c31374c5462f2905a83" + integrity sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" anymatch@^2.0.0: version "2.0.0" @@ -24,29 +217,39 @@ anymatch@^2.0.0: normalize-path "^2.1.1" anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" apache-crypt@^1.1.2: - version "1.2.6" - resolved "https://registry.yarnpkg.com/apache-crypt/-/apache-crypt-1.2.6.tgz#c3f9b98318b447f0a878b54e2cb113bbb8539698" - integrity sha512-072WetlM4blL8PREJVeY+WHiUh1R5VNt2HfceGS8aKqttPHcmqE5pkKuXPz/ULmJOFkc8Hw3kfKl6vy7Qka6DA== + version "1.2.5" + resolved "https://registry.yarnpkg.com/apache-crypt/-/apache-crypt-1.2.5.tgz#4eb6b6dbaed2041ce5bc2d802f4421f5fdadc25e" + integrity sha512-ICnYQH+DFVmw+S4Q0QY2XRXD8Ne8ewh8HgbuFH4K7022zCxgHM0Hz1xkRnUlEfAXNbwp1Cnhbedu60USIfDxvg== dependencies: unix-crypt-td-js "^1.1.4" apache-md5@^1.0.6: - version "1.1.8" - resolved "https://registry.yarnpkg.com/apache-md5/-/apache-md5-1.1.8.tgz#ea79c6feb03abfed42b2830dde06f75df5e3bbd9" - integrity sha512-FCAJojipPn0bXjuEpjOOOMN8FZDkxfWWp4JGN9mifU2IhxvKyXZYqpzPHdnTSUpmPDy+tsslB6Z1g+Vg6nVbYA== + version "1.1.7" + resolved "https://registry.yarnpkg.com/apache-md5/-/apache-md5-1.1.7.tgz#dcef1802700cc231d60c5e08fd088f2f9b36375a" + integrity sha512-JtHjzZmJxtzfTSjsCyHgPR155HBe5WGyUyHTaEkfy46qhwCFKx1Epm6nAxgUG3WfUZP1dWhGqj9Z2NOBeZ+uBw== + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.1.0: version "1.1.0" @@ -56,28 +259,47 @@ arr-flatten@^1.1.0: arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= async-each@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.6.tgz#52f1d9403818c179b7561e11a5d1b77eb2160e77" - integrity sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +axios@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" + integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -106,12 +328,12 @@ basic-auth@~2.0.1: batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= bcryptjs@^2.3.0: version "2.4.3" resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" - integrity sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ== + integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms= binary-extensions@^1.0.0: version "1.13.1" @@ -130,6 +352,25 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +bluebird@3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +boxen@^5.0.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -138,6 +379,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" @@ -161,6 +409,16 @@ braces@~3.0.2: dependencies: fill-range "^7.0.1" +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -176,6 +434,95 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cacheable-lookup@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" + integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +cacheable-request@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817" + integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^6.0.1" + responselike "^2.0.0" + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +camelcase@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.1.tgz#250fd350cfd555d0d2160b1d51510eaf8326e86e" + integrity sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA== + +chai-as-promised@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" + integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== + dependencies: + check-error "^1.0.2" + +chai@^4.1.2: + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^4.1.2" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chokidar@^2.0.4: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -196,9 +543,9 @@ chokidar@^2.0.4: fsevents "^1.2.7" chokidar@^3.5.2: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + version "3.5.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" + integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -210,6 +557,29 @@ chokidar@^3.5.2: optionalDependencies: fsevents "~2.3.2" +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +chromedriver@114, chromedriver@114.0.2, chromedriver@^74.0.0: + version "114.0.2" + resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-114.0.2.tgz#1ddaa6738f2b60e6b832a39f791c8c54bf840837" + integrity sha512-v0qrXRBknbxqmtklG7RWOe3TJ/dLaHhtB0jVxE7BAdYERxUjEaNRyqBwoGgVfQDibHCB0swzvzsj158nnfPgZw== + dependencies: + "@testim/chrome-version" "^1.1.3" + axios "^1.4.0" + compare-versions "^5.0.3" + extract-zip "^2.0.1" + https-proxy-agent "^5.0.1" + proxy-from-env "^1.1.0" + tcp-port-used "^1.0.1" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -220,19 +590,64 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + colors@latest: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +compare-versions@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-5.0.3.tgz#a9b34fea217472650ef4a2651d905f42c28ebfd7" + integrity sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A== + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -241,7 +656,19 @@ component-emitter@^1.2.1: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" connect@^3.6.6: version "3.7.0" @@ -256,7 +683,7 @@ connect@^3.6.6: copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-util-is@~1.0.0: version "1.0.3" @@ -271,6 +698,16 @@ cors@latest: object-assign "^4" vary "^1" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -278,6 +715,20 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" +debug@4, debug@4.3.4, debug@^4.1.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -285,22 +736,68 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + decode-uri-component@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" - integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +deep-eql@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +defer-to-connect@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" @@ -312,20 +809,47 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -depd@2.0.0, depd@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== +depd@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== + dependencies: + is-obj "^2.0.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= duplexer@~0.1.1: version "0.1.2" @@ -335,27 +859,54 @@ duplexer@~0.1.1: ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" + integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= event-stream@3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g== + integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= dependencies: duplexer "~0.1.1" from "~0" @@ -368,7 +919,7 @@ event-stream@3.3.4: expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -381,14 +932,14 @@ expand-brackets@^2.1.4: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -407,6 +958,17 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extract-zip@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + faye-websocket@0.11.x: version "0.11.4" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" @@ -414,6 +976,13 @@ faye-websocket@0.11.x: dependencies: websocket-driver ">=0.5.1" +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== + dependencies: + pend "~1.2.0" + file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -422,7 +991,7 @@ file-uri-to-path@1.0.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -449,27 +1018,84 @@ finalhandler@1.1.2: statuses "~1.5.0" unpipe "~1.0.0" +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +follow-redirects@^1.15.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g== + integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= + +fs-extra@^8.0.1: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^1.2.7: version "1.2.13" @@ -484,15 +1110,50 @@ fsevents@~2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== +geckodriver@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/geckodriver/-/geckodriver-3.2.0.tgz#6b0a85e2aafbce209bca30e2d53af857707b1034" + integrity sha512-p+qR2RKlI/TQoCEYrSuTaYCLqsJNni96WmEukTyXmOmLn+3FLdgPAEwMZ0sG2Cwi9hozUzGAWyT6zLuhF6cpiQ== + dependencies: + adm-zip "0.5.9" + bluebird "3.7.2" + got "11.8.5" + https-proxy-agent "5.0.1" + tar "6.1.11" + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== + +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA== + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" @@ -504,7 +1165,77 @@ glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -graceful-fs@^4.1.11: +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-dirs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" + integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== + dependencies: + ini "2.0.0" + +got@11.8.5: + version "11.8.5" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.5.tgz#ce77d045136de56e8f024bebb82ea349bc730046" + integrity sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ== + dependencies: + "@sindresorhus/is" "^4.0.0" + "@szmarczak/http-timer" "^4.0.5" + "@types/cacheable-request" "^6.0.1" + "@types/responselike" "^1.0.0" + cacheable-lookup "^5.0.3" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + http2-wrapper "^1.0.0-beta.5.2" + lowercase-keys "^2.0.0" + p-cancelable "^2.0.0" + responselike "^2.0.0" + +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2: + version "4.2.8" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" + integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== + +graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -512,12 +1243,17 @@ graceful-fs@^4.1.11: has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -526,7 +1262,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -535,71 +1271,140 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + http-auth@3.1.x: version "3.1.3" resolved "https://registry.yarnpkg.com/http-auth/-/http-auth-3.1.3.tgz#945cfadd66521eaf8f7c84913d377d7b15f24e31" - integrity sha512-Jbx0+ejo2IOx+cRUYAGS1z6RGc6JfYUNkysZM4u4Sfk1uLlGv814F7/PIjQQAuThLdAWxb74JMGd5J8zex1VQg== + integrity sha1-lFz63WZSHq+PfISRPTd9exXyTjE= dependencies: apache-crypt "^1.1.2" apache-md5 "^1.0.6" bcryptjs "^2.3.0" uuid "^3.0.0" -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== http-errors@~1.6.2: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= dependencies: depd "~1.1.2" inherits "2.0.3" setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + http-parser-js@>=0.5.1: - version "0.5.8" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" - integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + version "0.5.5" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5" + integrity sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA== + +http2-wrapper@^1.0.0-beta.5.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" + integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.0.0" + +https-proxy-agent@5.0.1, https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== + integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= -inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3: +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" + integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +ip-regex@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" + integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" @@ -613,7 +1418,7 @@ is-accessor-descriptor@^1.0.0: is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q== + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" @@ -629,10 +1434,17 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" @@ -664,7 +1476,7 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" @@ -676,12 +1488,17 @@ is-extendable@^1.0.1: is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw== + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" @@ -692,10 +1509,23 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-installed-globally@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" + integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== + dependencies: + global-dirs "^3.0.0" + is-path-inside "^3.0.2" + +is-npm@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" + integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" @@ -704,6 +1534,21 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -711,6 +1556,21 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -719,36 +1579,98 @@ is-windows@^1.0.2: is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + +is2@^2.0.6: + version "2.0.9" + resolved "https://registry.yarnpkg.com/is2/-/is2-2.0.9.tgz#ff63b441f90de343fa8fac2125ee170da8e8240d" + integrity sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g== + dependencies: + deep-is "^0.1.3" + ip-regex "^4.1.0" + is-url "^1.2.4" isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +jszip@^3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + setimmediate "^1.0.5" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +keyv@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" + integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== + dependencies: + json-buffer "3.0.1" kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" @@ -762,7 +1684,21 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -live-server@1.2.1: +latest-version@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + +lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + +live-server@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/live-server/-/live-server-1.2.1.tgz#670630dd409d22fe9c513ab1c1894686c757153e" integrity sha512-Yn2XCVjErTkqnM3FfTmM7/kWy3zP7+cEtC7x6u+wUzlQ+1UW3zEYbbyJrc0jNDwiMDZI0m4a0i3dxlGHVyXczw== @@ -781,20 +1717,71 @@ live-server@1.2.1: send latest serve-index "^1.9.1" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +loupe@^2.3.1: + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== + dependencies: + get-func-name "^2.0.0" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g== + integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" @@ -817,30 +1804,86 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@~2.1.17, mime-types@~2.1.34: +mime-types@^2.1.12: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" +mime-types@~2.1.17, mime-types@~2.1.24: + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== + dependencies: + mime-db "1.51.0" + mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -minimatch@^3.1.2: +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" +minimist@^1.2.0: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -849,6 +1892,52 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mocha-webdriver@^0.2.13: + version "0.2.13" + resolved "https://registry.yarnpkg.com/mocha-webdriver/-/mocha-webdriver-0.2.13.tgz#6e39360e08dc32e2de7375c6eaee83bd6aa98cc6" + integrity sha512-xSQ9fTViIucIZs+loRzKhOkUtztMheHYRg2+CrgqBPg9/MYjOWbcUk+uye5r117BN/r57KRuZxvsZRH0Jm0gCg== + dependencies: + chai "^4.1.2" + chai-as-promised "^7.1.1" + chromedriver "^74.0.0" + fs-extra "^8.0.1" + geckodriver "^3.2.0" + mocha "^10.1.0" + npm-run-path "^3.1.0" + selenium-webdriver "^4.0.0-alpha.1" + +mocha@^10.1.0, mocha@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" + integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + morgan@^1.9.1: version "1.10.0" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" @@ -863,7 +1952,17 @@ morgan@^1.9.1: ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== ms@2.1.3, ms@^2.1.1: version "2.1.3" @@ -871,9 +1970,14 @@ ms@2.1.3, ms@^2.1.1: integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== nan@^2.12.1: - version "2.17.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" - integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== + version "2.15.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== nanomatch@^1.2.9: version "1.2.13" @@ -892,38 +1996,45 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + +node-fetch@^2: + version "2.6.12" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" + integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + dependencies: + whatwg-url "^5.0.0" nodemon@^2.0.15: - version "2.0.22" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.22.tgz#182c45c3a78da486f673d6c1702e00728daf5258" - integrity sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ== + version "2.0.15" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.15.tgz#504516ce3b43d9dc9a955ccd9ec57550a31a8d4e" + integrity sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA== dependencies: chokidar "^3.5.2" debug "^3.2.7" ignore-by-default "^1.0.1" - minimatch "^3.1.2" + minimatch "^3.0.4" pstree.remy "^1.1.8" semver "^5.7.1" - simple-update-notifier "^1.0.7" supports-color "^5.5.0" touch "^3.1.0" undefsafe "^2.0.5" + update-notifier "^5.1.0" nopt@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== + integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= dependencies: abbrev "1" normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" @@ -932,15 +2043,32 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== + +npm-run-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-3.1.0.tgz#7f91be317f6a466efed3c9f2980ad8a4ee8b0fa5" + integrity sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg== + dependencies: + path-key "^3.0.0" + object-assign@^4, object-assign@latest: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" @@ -949,28 +2077,21 @@ object-copy@^0.1.0: object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= dependencies: ee-first "1.1.1" @@ -979,6 +2100,13 @@ on-headers@~1.0.2: resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + opn@latest: version "6.0.0" resolved "https://registry.yarnpkg.com/opn/-/opn-6.0.0.tgz#3c5b0db676d5f97da1233d1ed42d182bc5a27d2d" @@ -986,6 +2114,45 @@ opn@latest: dependencies: is-wsl "^1.1.0" +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-cancelable@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" + integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + +pako@~1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -994,56 +2161,136 @@ parseurl@~1.3.2, parseurl@~1.3.3: pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q== + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== pause-stream@0.0.11: version "0.0.11" resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== + integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= dependencies: through "~2.3" +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== + picomatch@^2.0.4, picomatch@^2.2.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" + integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + proxy-middleware@latest: version "0.15.0" resolved "https://registry.yarnpkg.com/proxy-middleware/-/proxy-middleware-0.15.0.tgz#a3fdf1befb730f951965872ac2f6074c61477a56" - integrity sha512-EGCG8SeoIRVMhsqHQUdDigB2i7qU7fCsWASwn54+nPutYO8n4q6EiwMzyfWlC+dzRFExP+kvcnDFdBDHoZBU7Q== + integrity sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY= pstree.remy@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pupa@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" + integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== + dependencies: + escape-goat "^2.0.0" + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + readable-stream@^2.0.2: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@~2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -1080,10 +2327,24 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +registry-auth-token@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" + integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + dependencies: + rc "^1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.4" @@ -1093,24 +2354,55 @@ repeat-element@^1.1.2: repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-alpn@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +responselike@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" + integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== + dependencies: + lowercase-keys "^2.0.0" ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@>=5.1.0: +safe-buffer@>=5.1.0, safe-buffer@^5.1.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -1118,43 +2410,73 @@ safe-buffer@>=5.1.0: safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" +selenium-webdriver@^4.0.0-alpha.1: + version "4.10.0" + resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.10.0.tgz#0508cdfbb5ad8470d8fd19db1a69d3e87f474b79" + integrity sha512-hSQPw6jgc+ej/UEcdQPG/iBwwMeCEgZr9HByY/J8ToyXztEqXzU9aLsIyrlj1BywBcStO4JQK/zMUWWrV8+riA== + dependencies: + jszip "^3.10.1" + tmp "^0.2.1" + ws ">=8.13.0" + +semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" + integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== + dependencies: + semver "^6.3.0" + semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@~7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.4: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" send@latest: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== dependencies: debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" + depd "~1.1.2" + destroy "~1.0.4" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "2.0.0" + http-errors "~1.7.2" mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" + ms "2.1.1" + on-finished "~2.3.0" range-parser "~1.2.1" - statuses "2.0.1" + statuses "~1.5.0" + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" serve-index@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= dependencies: accepts "~1.3.4" batch "0.6.1" @@ -1174,22 +2496,25 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== -simple-update-notifier@^1.0.7: - version "1.1.0" - resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82" - integrity sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg== - dependencies: - semver "~7.0.0" +signal-exit@^3.0.2: + version "3.0.6" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" + integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== snapdragon-node@^2.0.1: version "2.1.1" @@ -1240,7 +2565,7 @@ source-map-url@^0.4.0: source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -1252,35 +2577,39 @@ split-string@^3.0.1, split-string@^3.0.2: split@0.3: version "0.3.3" resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA== + integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= dependencies: through "2" static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" object-copy "^0.1.0" -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -"statuses@>= 1.4.0 < 2", statuses@~1.5.0: +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= stream-combiner@~0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw== + integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= dependencies: duplexer "~0.1.1" +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -1288,6 +2617,30 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -1295,22 +2648,61 @@ supports-color@^5.5.0: dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +tar@6.1.11: + version "6.1.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +tcp-port-used@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tcp-port-used/-/tcp-port-used-1.0.2.tgz#9652b7436eb1f4cfae111c79b558a25769f6faea" + integrity sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA== + dependencies: + debug "4.3.1" + is2 "^2.0.6" + through@2, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +tmp@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -1332,10 +2724,10 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== touch@^3.1.0: version "3.1.0" @@ -1344,6 +2736,52 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +ts-node@^10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typescript@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.3.tgz#8d84219244a6b40b6fb2b33cc1c062f715b9e826" + integrity sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw== + undefsafe@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" @@ -1359,6 +2797,18 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + unix-crypt-td-js@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz#4912dfad1c8aeb7d20fa0a39e4c31918c1d5d5dd" @@ -1367,12 +2817,12 @@ unix-crypt-td-js@^1.1.4: unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -1382,10 +2832,37 @@ upath@^1.1.1: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== +update-notifier@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" + integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== + dependencies: + boxen "^5.0.0" + chalk "^4.1.0" + configstore "^5.0.1" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.4.0" + is-npm "^5.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.1.0" + pupa "^2.1.1" + semver "^7.3.4" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" + urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" use@^3.1.0: version "3.1.1" @@ -1395,22 +2872,32 @@ use@^3.1.0: util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@^3.0.0: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + vary@^1: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== websocket-driver@>=0.5.1: version "0.7.4" @@ -1425,3 +2912,118 @@ websocket-extensions@>=0.1.1: version "0.1.4" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@>=8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From e51d0043d067b5a37623da67b99a7d68afe229cd Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 15:40:53 +0200 Subject: [PATCH 40/64] Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5b0cd14e..1669d955 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: run: yarn install - name: Build Node.js test code - run: yarn run build:test + run: yarn run build - name: Cache Docker images. uses: ScribeMD/docker-cache@0.3.3 From 06f7135112d4d32cc9ffa31ccc9f52ead30afb2d Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 15:55:37 +0200 Subject: [PATCH 41/64] without changes in build, in test production widget are used. --- .github/workflows/main.yml | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1669d955..5b0cd14e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: run: yarn install - name: Build Node.js test code - run: yarn run build + run: yarn run build:test - name: Cache Docker images. uses: ScribeMD/docker-cache@0.3.3 diff --git a/package.json b/package.json index 137d79f6..0a23ec35 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "build": "tsc --build && node ./buildtools/publish.js", "serve": "live-server --port=8585 --no-browser -q", "build:dev": "node ./buildtools/publish.js http://localhost:8585", + "build:test": "node ./buildtools/publish.js http://localhost:9998", "serve:dev": "live-server --port=8585 --no-browser -q --middleware=$(pwd)/buildtools/rewriteUrl.js", "watch": "nodemon --ignore manifest.json -e js,json --exec 'npm run build:dev'", "dev": "echo 'Starting local server and watching for changes.\nStart Grist with an environmental variable GRIST_WIDGET_LIST_URL=http://localhost:8585/manifest.json' && npm run watch 1> /dev/null & npm run serve:dev 1> /dev/null", From 01b83fd14533b393817f0d3c9d741197dd65e994 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Tue, 8 Aug 2023 16:15:04 +0200 Subject: [PATCH 42/64] fix for build:test to generate not only manifest but also actually build. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a23ec35..06863e62 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "build": "tsc --build && node ./buildtools/publish.js", "serve": "live-server --port=8585 --no-browser -q", "build:dev": "node ./buildtools/publish.js http://localhost:8585", - "build:test": "node ./buildtools/publish.js http://localhost:9998", + "build:test": "tsc --build && node ./buildtools/publish.js http://localhost:9998", "serve:dev": "live-server --port=8585 --no-browser -q --middleware=$(pwd)/buildtools/rewriteUrl.js", "watch": "nodemon --ignore manifest.json -e js,json --exec 'npm run build:dev'", "dev": "echo 'Starting local server and watching for changes.\nStart Grist with an environmental variable GRIST_WIDGET_LIST_URL=http://localhost:8585/manifest.json' && npm run watch 1> /dev/null & npm run serve:dev 1> /dev/null", From d7df3c74d25a50e4f7372e544c909e2452f7e611 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 9 Aug 2023 11:40:21 +0200 Subject: [PATCH 43/64] test rewritten to not really on any pre-set data. --- test/calendar.ts | 75 ++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/test/calendar.ts b/test/calendar.ts index 542fea01..1c0b31db 100644 --- a/test/calendar.ts +++ b/test/calendar.ts @@ -24,8 +24,6 @@ describe('calendar', function () { before(async function () { const docId = await grist.upload('test/fixtures/docs/Calendar-UnitTest.grist'); - //await grist.createDoc("Calendar Test"); - //await grist.addNewColumn("Table1", "Label", "Text"); await grist.openDoc(docId); await grist.toggleSidePanel('right', 'open'); await grist.addNewSection(/Custom/, /Table1/); @@ -38,30 +36,29 @@ describe('calendar', function () { await grist.setCustomWidgetMapping('isAllDay', /IsFullDay/); }); - it('should show valid event', async function () { - //const obj = await grist.getCustomWidgetObject('); - const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(1)); - assert.deepEqual(mappedObject, { - title: "Event1", - startDate: new Date('2023-08-01 13:00').toString(), - endDate: new Date('2023-08-01 14:00').toString(), - isAllDay: false - }) - await grist.waitToPass(async () => { - const txt = await grist.getCustomWidgetBody('[data-testid*="Event1"]'); - assert.equal(txt, 'Event1'); - }); - }); - it('should show valid whole-day event', async function () { - const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(2)); - assert.deepEqual(mappedObject, { - title: "Event2", - startDate: new Date('2023-08-02 00:00:00').toString(), - endDate: new Date('2023-08-02 23:59:59').toString(), - isAllDay: true - }) - - }); + // it('should show valid event', async function () { + // //const obj = await grist.getCustomWidgetObject('); + // const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(1)); + // assert.deepEqual(mappedObject, { + // title: "Event1", + // startDate: new Date('2023-08-01 13:00').toString(), + // endDate: new Date('2023-08-01 14:00').toString(), + // isAllDay: false + // }) + // await grist.waitToPass(async () => { + // const txt = await grist.getCustomWidgetBody('[data-testid*="Event1"]'); + // assert.equal(txt, 'Event1'); + // }); + // }); + // it('should show valid whole-day event', async function () { + // const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(2)); + // assert.deepEqual(mappedObject, { + // title: "Event2", + // startDate: new Date('2023-08-02 00:00:00').toString(), + // endDate: new Date('2023-08-02 23:59:59').toString(), + // isAllDay: true + // }) + // }); it('should create new event when new row is added', async function () { await grist.sendActions([['AddRecord', 'Table1', -1, { @@ -70,7 +67,7 @@ describe('calendar', function () { Label: "New Event", IsFullDay: false }]]); - const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(3)); + const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(1)); assert.deepEqual(mappedObject, { title: "New Event", startDate: new Date('2023-08-03 13:00').toString(), @@ -79,10 +76,19 @@ describe('calendar', function () { }) }); - it('should remove event when row is deleted', async function () { - await grist.sendActions([['RemoveRecord', 'Table1', 3]]); - const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(3)); - assert.notExists(mappedObject); + it('should create new all day event when new row is added', async function () { + await grist.sendActions([['AddRecord', 'Table1', -1, { + From: new Date('2023-08-04 13:00'), + To: new Date('2023-08-04 14:00'), + Label: "All Day Event", + IsFullDay: true + }]]); + const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(2)); + assert.equal(mappedObject.title, "All Day Event"); + assert.equal(mappedObject.isAllDay, true); + // Ignoring time component, because it's not important in full day events + assert.equal(new Date(mappedObject.startDate).toDateString(), new Date('2023-08-04 00:00:00').toDateString()); + assert.equal(new Date(mappedObject.endDate).toDateString(), new Date('2023-08-04 00:00:00').toDateString()); }); it('should update event when table data is changed', async function () { @@ -101,6 +107,13 @@ describe('calendar', function () { }) }); + it('should remove event when row is deleted', async function () { + await grist.sendActions([['RemoveRecord', 'Table1', 1]]); + const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(1)); + assert.notExists(mappedObject); + }); + + //TODO: test adding new events and moving existing one on the calendar. ToastUI is not best optimalized for drag and drop tests in mocha and i cannot yet make it working correctly. }); \ No newline at end of file From a916f83e2791a65fb9668a365fc844bc0be63df0 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 9 Aug 2023 11:40:58 +0200 Subject: [PATCH 44/64] file replaced --- test/fixtures/docs/Calendar-UnitTest.grist | Bin 225280 -> 212992 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/fixtures/docs/Calendar-UnitTest.grist b/test/fixtures/docs/Calendar-UnitTest.grist index f15f66b5509973372d4ebae9f34bdc7e2c8398ca..9de2b522290fd5843c875a7e4135c8e1ff47567b 100644 GIT binary patch delta 3810 zcmcIndu$X%7~h>eu6NhFTgpQ$N_(XRMUc+yYjzc(psf-LNLqOlncdli%GqMu(-=Zp zHE0NufDKMG7<}L#KB5?eLR4amL?9p%6XOE`Um+x7FeYkze|OhHiJ<7}Zf>&o?ac4{ z=J)$%=G*QQsqXI7hDzCZCG+L%ic)pI1ec-ytbVV4tA4GXR6kcgRXsJ3{32~n$018mq1{S8?Y|S zU5G}bTnnhlu+F*57{i44mg{<0w;cw-Ru*8W#=#NxY~M0G@Zx#YH7u^{0d=tJo1lm5 zas$`^0*ydpR3iZ3SkS>Ij8zm-ToVTjB*1|MLNTKI4&gwNhq7^;< zT~vY^r8q^6Ktdgwxqf+N9|^ZyJf$x!qbn)}c@7P)3yUMOZ<@T!@)S)VL|tyOBtH+W6;=zhw=MpiXi%-M@Bn-a285MNMW z?8MRM`x(2$qT!-7!vMz051z-^>4Se}4E+UT`NIf5*j!a)?BPt<$TC&MBnyipl2-#| zc*a@ESjYlNl&Q)zap+YPyJ}VrPG4zyM?)@~y@}o1kQ)Sl8=328bMPSL@|-lc&C2hr zV?|~+Diz-xMA7`%bo#uJ%>wU6!%|w`h?b?@`?=V-M7c5sC4n?8mt7$?97ZF$ipiOW zU6qSK+tA*2XTetVcOK>d``NGt*ov{8GhqCnl_`q1j$eeM@t0ghR%VL%9+vAhWgy;r zW6z2g`tSwuCW+&_P&Cue->kn=txU|=iqe9BLdkxC-u!Ogg#=nw;IpuM{0{=9Kyf+I zBqf?)OP`*Yx$c^pqF|dE!+sA{*Yq8qA-}6c&%C@~pS;+=L4`dddTw2Cg?MQNRDc!D T%Fy0No0J|oWSz5muG0Ajp|w96 delta 8624 zcmd^EZEO_B8Qz^e-v{>Hp21*QfPFsu+|YtNJNr%fu%Sjx8#hi$+n^ZPv%9mz^f)`V zFa03YZlWk4r~Th={Eqw= z`A_m$`FHZ0@)`NG{F?mAzI|UgzN2T2yi^d33=Gy=pwZIMsLjxj6f{cX#M!>(J#AG7 zgy^PtSM*TzJJE}=&&+!(@sfP9W~Ayu&CkLo;?r___`~pEcv2;4pS^k zwG~e#E+Gz9ut_wH_&&pirC8XbzUyfQQ&mb_#lf1@Rz%SqMRzT#nGW$SN5L?Ncs4dY zsw*(q#h&X~7G{>|G9AMNs%4E~%9!dgLW${TiZHg}tBP&wnA)nY6Hm8oxNUkwcZm*b z0zlVezM?9ssyZft<$11cI@B{9tQtyd2}Q%2V_|IgnqgR!I6C!IS9h_Bv8`Z*7_Q1R zb<9)^)pQIO7Vhd)XQs*+u|1!(6k!b4c8G2<)d%NzmaS;2s<|%Ke85o@iz&A2U=zEh zNnKmDu%Y{&VH3iztLUDQE}~eT;p-Mvb3fMO6!(M{U`XJFMQ5IF)%@f`=;N;PI!hM~E{fbjT=MzF7f z`)$?qY>lQ$o`InHhU+s^ahx$z2MZmGQOZ2ZD8TE?Q4G)5G*}7DNFCGkEE62=TE4Hk zp50W0@m)p3(WOkch^Z3DA);A^MX2IfuIhthF=UpjnJPX0)yKBix3>XF z=4E2pL6_D_At56czGeIJxe=BdZIe+*Xuff&c;Tt>m&e7LWT+-nlK~Rc*UXm=39(p1 zJTAuKJKN*%iSo?{#iu#Gj^ZKPwk_Uy9cAja_oj1n8|zK4>`kwyS(fwYFz>vK8fV5d zjot4RZ+C1N9vB(TQfH+78w1`JHo5{u+E6yXWgrK0^XIOiC3U4K9~>GT7|e~p z$Q+F0kN*et$$}sb&e;0Q3jWAJac9BI&+}LRjrQ`>hs2G^#I^tb10TJS=#c*@jEkZe zjYp$#A(X6w{?M(y9D;uTt$sp+e$TCb98Ky+#J7${kvuKPm*i;x{gvFl2t@=j6l#be z@633A;lJw%h#6TZMuZq#k9t!Vk9t%8I#s-^ygY##`1!X{LJaYro<>9z_{GyG^+0xM$wPa4f=;t! zY0*OgdCNZtOT&E8>u4z5|86<%;V;Cc&WVRMHSr?{QG%abEj56N5B(bbA{hsF4kQW< zWVbMov^Jp5^MMu8iS((&t}^m&t$lkr zxch3r5C0Nr5 zGIrnl=xg_$v3FGy3&whd$nHolPv`R6HVhAbo8{6g@eYi?*Vt6z^$S`+j@XS&rLqzf zhhLcw#Qtr#9AXErVYQ2;FWh_a|Cq^MU^Wzj{eMP}eqwBX_Z+GZi;=BDWGg&L^+&q* zEod&K{NcvAUs=j~V@WlaQa&gSpZ{q{`SabzVUh-+UIWzW37n zuBE+HwCAW}6&6&JUq6ScfXIQbat-%z)( zY5b-9wt>vVv5h}Yr_k;)c9A-Q9@|Q0E6DL1-A8i!*p0(0w_xEdB zOP+cu8FZGG)*C7q@Q8_DTL~)IZ Date: Wed, 9 Aug 2023 15:22:14 +0200 Subject: [PATCH 45/64] whole day test fix --- test/calendar.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/calendar.ts b/test/calendar.ts index 1c0b31db..f88762d7 100644 --- a/test/calendar.ts +++ b/test/calendar.ts @@ -87,8 +87,10 @@ describe('calendar', function () { assert.equal(mappedObject.title, "All Day Event"); assert.equal(mappedObject.isAllDay, true); // Ignoring time component, because it's not important in full day events - assert.equal(new Date(mappedObject.startDate).toDateString(), new Date('2023-08-04 00:00:00').toDateString()); - assert.equal(new Date(mappedObject.endDate).toDateString(), new Date('2023-08-04 00:00:00').toDateString()); + assert.equal(new Date(mappedObject.startDate).toDateString(), + new Date('2023-08-04 00:00:00').toDateString()); + assert.equal(new Date(mappedObject.endDate).toDateString(), + new Date('2023-08-04 00:00:00').toDateString()); }); it('should update event when table data is changed', async function () { From 98f92c1a0cc8b8f971a2df65608def00e1925a64 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 10 Aug 2023 10:27:08 +0200 Subject: [PATCH 46/64] test if this would fix on the StaleElementReferenceError: stale element reference: stale element not found problem while testing binding columns to widgets --- test/getGrist.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/getGrist.ts b/test/getGrist.ts index 6bb90a7d..3e56ccd9 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -238,7 +238,13 @@ export class GristUtils extends GristWebDriverUtils { } public async setCustomWidgetMapping(name: string, value: string | RegExp) { - const click = (selector: string) => driver.findWait(`${selector}`, 2000).click(); + const click = (selector: string) => { + try { + driver.findWait(`${selector}`, 2000).click(); + } catch (e) { + driver.findWait(`${selector}`, 2000).click(); + } + }; const toggleDrop = (selector: string) => click(`${selector} .test-select-open`); const pickerDrop = (name: string) => `.test-config-widget-mapping-for-${name}`; await toggleDrop(pickerDrop(name)); From 5b2708d2bc1e40c15d8398f7c19986a7ea056828 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 10 Aug 2023 12:14:42 +0200 Subject: [PATCH 47/64] Update calendar.ts commented code removed --- test/calendar.ts | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/test/calendar.ts b/test/calendar.ts index f88762d7..47703c63 100644 --- a/test/calendar.ts +++ b/test/calendar.ts @@ -36,30 +36,6 @@ describe('calendar', function () { await grist.setCustomWidgetMapping('isAllDay', /IsFullDay/); }); - // it('should show valid event', async function () { - // //const obj = await grist.getCustomWidgetObject('); - // const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(1)); - // assert.deepEqual(mappedObject, { - // title: "Event1", - // startDate: new Date('2023-08-01 13:00').toString(), - // endDate: new Date('2023-08-01 14:00').toString(), - // isAllDay: false - // }) - // await grist.waitToPass(async () => { - // const txt = await grist.getCustomWidgetBody('[data-testid*="Event1"]'); - // assert.equal(txt, 'Event1'); - // }); - // }); - // it('should show valid whole-day event', async function () { - // const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(2)); - // assert.deepEqual(mappedObject, { - // title: "Event2", - // startDate: new Date('2023-08-02 00:00:00').toString(), - // endDate: new Date('2023-08-02 23:59:59').toString(), - // isAllDay: true - // }) - // }); - it('should create new event when new row is added', async function () { await grist.sendActions([['AddRecord', 'Table1', -1, { From: new Date('2023-08-03 13:00'), @@ -118,4 +94,4 @@ describe('calendar', function () { //TODO: test adding new events and moving existing one on the calendar. ToastUI is not best optimalized for drag and drop tests in mocha and i cannot yet make it working correctly. -}); \ No newline at end of file +}); From 327a72d5197e4b24a21ab517749e61142d858b8c Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 10 Aug 2023 12:16:58 +0200 Subject: [PATCH 48/64] Update getGrist.ts explanation of try-catch in SteCustomWidgetMapping --- test/getGrist.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/getGrist.ts b/test/getGrist.ts index 3e56ccd9..401eb285 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -242,6 +242,8 @@ export class GristUtils extends GristWebDriverUtils { try { driver.findWait(`${selector}`, 2000).click(); } catch (e) { + //sometimes here we get into "detached" state and test fail. + //if this happend, just try one more time driver.findWait(`${selector}`, 2000).click(); } }; From 114ce45b30782c8e4d75c377d64b308cf10b43ea Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 16 Aug 2023 10:29:10 +0200 Subject: [PATCH 49/64] awaiting in setCustomWidgetMapping --- test/getGrist.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/getGrist.ts b/test/getGrist.ts index 3e56ccd9..8bff4110 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -238,14 +238,14 @@ export class GristUtils extends GristWebDriverUtils { } public async setCustomWidgetMapping(name: string, value: string | RegExp) { - const click = (selector: string) => { + const click = async (selector: string) => { try { - driver.findWait(`${selector}`, 2000).click(); + await driver.findWait(`${selector}`, 2000).click(); } catch (e) { - driver.findWait(`${selector}`, 2000).click(); + await driver.findWait(`${selector}`, 2000).click(); } }; - const toggleDrop = (selector: string) => click(`${selector} .test-select-open`); + const toggleDrop = async (selector: string) => await click(`${selector} .test-select-open`); const pickerDrop = (name: string) => `.test-config-widget-mapping-for-${name}`; await toggleDrop(pickerDrop(name)); const clickOption = async (text: string | RegExp) => { From b71136671b789f678390de6cf3e91a8d9484c93b Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 16 Aug 2023 10:34:06 +0200 Subject: [PATCH 50/64] widget name changed from calendar-map to widget-calendar --- calendar/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calendar/package.json b/calendar/package.json index e7562daa..d85a74a0 100644 --- a/calendar/package.json +++ b/calendar/package.json @@ -1,5 +1,5 @@ { - "name": "@gristlabs/calendar-map", + "name": "@gristlabs/widget-calendar", "description": "Widget for visualizing data as an calendar", "homePage": "https://github.com/gristlabs/grist-widget", "version": "0.0.1", From 9341245b0792c439e65fc4b6c934b15bd15ac7a5 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 16 Aug 2023 10:37:41 +0200 Subject: [PATCH 51/64] widget name changed from calendar-map to widget-calendar --- calendar/package.json | 2 +- calendar/page.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/calendar/package.json b/calendar/package.json index d85a74a0..9875c31e 100644 --- a/calendar/package.json +++ b/calendar/package.json @@ -10,7 +10,7 @@ { "name": "Calendar", "url": "https://gristlabs.github.io/grist-widget/calendar/index.html", - "widgetId": "@gristlabs/widget-calendar#calendar", + "widgetId": "@gristlabs/widget-calendar", "published": true, "accessLevel": "read table" } diff --git a/calendar/page.js b/calendar/page.js index 8090e771..6d570bdc 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -1,4 +1,4 @@ -// lets assume that it's imported in a html file +// let's assume that it's imported in an html file var grist; class CalendarHandler { From 6c9a82959bdfd0aee3a7e59a46058407066fd02c Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 16 Aug 2023 11:10:23 +0200 Subject: [PATCH 52/64] Calendar name separated to const --- calendar/page.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 6d570bdc..42d96324 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -1,5 +1,6 @@ // let's assume that it's imported in an html file var grist; +const CALENDAR_NAME = 'standardCalendar'; class CalendarHandler { static _mainColor = getComputedStyle(document.documentElement) @@ -26,7 +27,7 @@ class CalendarHandler { }, calendars: [ { - id: 'cal1', + id: CALENDAR_NAME, name: 'Personal', backgroundColor: CalendarHandler._mainColor, }, @@ -36,6 +37,7 @@ class CalendarHandler { constructor() { const container = document.getElementById('calendar'); const options = CalendarHandler.getCalendarOptions(); + this.previousIds = new Set(); this.calendar = new tui.Calendar(container, options); this.calendar.on('beforeUpdateEvent', onCalendarEventBeingUpdated); this.calendar.on('clickEvent', async (info) => { @@ -50,9 +52,9 @@ class CalendarHandler { // navigate to the selected date in the calendar and scroll to the time period of the event selectRecord(record) { if (this._selectedRecordId) { - this.calendar.updateEvent(this._selectedRecordId, 'cal1', {backgroundColor: CalendarHandler._mainColor}); + this.calendar.updateEvent(this._selectedRecordId, CALENDAR_NAME, {backgroundColor: CalendarHandler._mainColor}); } - this.calendar.updateEvent(record.id, 'cal1', {backgroundColor: CalendarHandler._selectedColor}); + this.calendar.updateEvent(record.id, CALENDAR_NAME, {backgroundColor: CalendarHandler._selectedColor}); this._selectedRecordId = record.id; this.calendar.setDate(record.startDate); var dom = document.querySelector('.toastui-calendar-time'); @@ -87,15 +89,14 @@ class CalendarHandler { // we need to keep track of the ids of the events that are currently in the calendar to compare it // with the new set of events when they come. const currentIds = new Set(); - for (const record of calendarEvents) { //chek if event already exist in the calendar - update it if so, create new otherwise - const event = this.calendar.getEvent(record.id, 'cal1'); + const event = this.calendar.getEvent(record.id, CALENDAR_NAME); const eventData = record; if (!event) { this.calendar.createEvents([eventData]); } else { - this.calendar.updateEvent(record.id, 'cal1', eventData); + this.calendar.updateEvent(record.id, CALENDAR_NAME, eventData); } currentIds.add(record.id); } @@ -103,7 +104,7 @@ class CalendarHandler { if(this.previousIds) { for (const id of this.previousIds) { if (!currentIds.has(id)) { - this.calendar.deleteEvent(id, 'cal1'); + this.calendar.deleteEvent(id, CALENDAR_NAME); } } } @@ -265,7 +266,7 @@ function selectRadioButton(value) { function buildCalendarEventObject(record) { return { id: record.id, - calendarId: 'cal1', + calendarId: CALENDAR_NAME, title: record.title, start: record.startDate, end: record.endDate, From 6906ae86211b59f23099630e6a26f005fbd6acb4 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 16 Aug 2023 12:20:12 +0200 Subject: [PATCH 53/64] read function improved to a more modern version --- calendar/page.js | 23 ++++++++++++++++++----- test/calendar.ts | 24 ------------------------ 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 42d96324..3d3eecc8 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -1,7 +1,19 @@ // let's assume that it's imported in an html file var grist; + +// to keep all calendar related logic; +let calendarHandler; const CALENDAR_NAME = 'standardCalendar'; +//registering code to run when a document is ready +function ready(fn) { + if (document.readyState !== 'loading') { + fn(); + } else { + document.addEventListener('DOMContentLoaded', fn); + } +} + class CalendarHandler { static _mainColor = getComputedStyle(document.documentElement) .getPropertyValue('--main-color'); @@ -101,7 +113,7 @@ class CalendarHandler { currentIds.add(record.id); } // if some events are not in the new set of events, we need to remove them from the calendar - if(this.previousIds) { + if (this.previousIds) { for (const id of this.previousIds) { if (!currentIds.has(id)) { this.calendar.deleteEvent(id, CALENDAR_NAME); @@ -112,12 +124,13 @@ class CalendarHandler { } } -// when document is ready, register calendar and subscribe to grist events -document.addEventListener('DOMContentLoaded', ()=> { - this.calendarHandler = new CalendarHandler(); - configureGristSettings(); +// when a document is ready, register the calendar and subscribe to grist events +ready(async () => { + calendarHandler = new CalendarHandler(); + await configureGristSettings(); }); + //to update the table, grist require other format that it is returning in onRecords event (it's flat there), // so it need to be converted function convertEventToGristTableFormat(event) { diff --git a/test/calendar.ts b/test/calendar.ts index f88762d7..bda15a42 100644 --- a/test/calendar.ts +++ b/test/calendar.ts @@ -36,30 +36,6 @@ describe('calendar', function () { await grist.setCustomWidgetMapping('isAllDay', /IsFullDay/); }); - // it('should show valid event', async function () { - // //const obj = await grist.getCustomWidgetObject('); - // const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(1)); - // assert.deepEqual(mappedObject, { - // title: "Event1", - // startDate: new Date('2023-08-01 13:00').toString(), - // endDate: new Date('2023-08-01 14:00').toString(), - // isAllDay: false - // }) - // await grist.waitToPass(async () => { - // const txt = await grist.getCustomWidgetBody('[data-testid*="Event1"]'); - // assert.equal(txt, 'Event1'); - // }); - // }); - // it('should show valid whole-day event', async function () { - // const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(2)); - // assert.deepEqual(mappedObject, { - // title: "Event2", - // startDate: new Date('2023-08-02 00:00:00').toString(), - // endDate: new Date('2023-08-02 23:59:59').toString(), - // isAllDay: true - // }) - // }); - it('should create new event when new row is added', async function () { await grist.sendActions([['AddRecord', 'Table1', -1, { From: new Date('2023-08-03 13:00'), From 476612adf82da6a935f6fdfb11adaf8bfde70530 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 16 Aug 2023 12:23:39 +0200 Subject: [PATCH 54/64] rewording comment to convertEventToGristTableFormat --- calendar/page.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 3d3eecc8..ac50f870 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -131,8 +131,8 @@ ready(async () => { }); -//to update the table, grist require other format that it is returning in onRecords event (it's flat there), -// so it need to be converted +//to update the table, grist requires another format that it is returning by grist in onRecords event (it's flat is +// onRecords event and nested ({id:..., fields:{}}) in grist table), so it needs to be converted function convertEventToGristTableFormat(event) { const mappedRecord = grist.mapColumnNamesBack(event); // we cannot save record is some unexpected columns are defined in fields, so we need to remove them From 2ac80fac5bb4e732c43efc6b6ceb63d54d185e5b Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 16 Aug 2023 12:39:27 +0200 Subject: [PATCH 55/64] various typos and --- calendar/page.js | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index ac50f870..ff557baa 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -130,17 +130,7 @@ ready(async () => { await configureGristSettings(); }); - -//to update the table, grist requires another format that it is returning by grist in onRecords event (it's flat is -// onRecords event and nested ({id:..., fields:{}}) in grist table), so it needs to be converted -function convertEventToGristTableFormat(event) { - const mappedRecord = grist.mapColumnNamesBack(event); - // we cannot save record is some unexpected columns are defined in fields, so we need to remove them - delete mappedRecord.id; - return { id: event.id, fields: mappedRecord }; -} - -// Data for column mapping fileds in Widget GUI +// Data for column mapping fields in Widget GUI function getGristOptions() { return [ { @@ -177,9 +167,9 @@ function getGristOptions() { ]; } -// let subscribe all the events that we need +// let's subscribe to all the events that we need async function configureGristSettings() { - // table selection should change when other event is selected + // table selection should change when another event is selected grist.allowSelectBy(); // CRUD operations on records in table grist.onRecords(updateCalendar); @@ -193,16 +183,16 @@ async function configureGristSettings() { grist.ready({ requiredAccess: 'read table', columns: columnsMappingOptions }); } -// when user select record in the table, we want to select it on the calendar - function gristSelectedRecordChanged(record, mappings) { - const mappedRecord = grist.mapColumnNames(record, mappings); - if (mappedRecord && this.calendarHandler) { - this.calendarHandler.selectRecord(mappedRecord); - } +// when a user selects a record in the table, we want to select it on the calendar +function gristSelectedRecordChanged(record, mappings) { + const mappedRecord = grist.mapColumnNames(record, mappings); + if (mappedRecord && CalendarHandler) { + CalendarHandler.selectRecord(mappedRecord); + } } -// when user change the perspective in the GUI, we want to save it as grist option -// - rest of logic is in reaction to grist option changed +// when a user changes the perspective in the GUI, we want to save it as grist option +// - rest of logic is in reaction to the grist option changed async function calendarViewChanges(radiobutton) { await grist.setOption('calendarViewPerspective', radiobutton.value); } @@ -233,7 +223,12 @@ const onCalendarEventBeingUpdated = async (info) => { // saving events to the table or updating existing one - basing on if ID is present or not in the send event async function upsertGristRecord(gristEvent){ - const eventInValidFormat = convertEventToGristTableFormat(gristEvent); + //to update the table, grist requires another format that it is returning by grist in onRecords event (it's flat is + // onRecords event and nested ({id:..., fields:{}}) in grist table), so it needs to be converted + const mappedRecord = grist.mapColumnNamesBack(gristEvent); + // we cannot save record is some unexpected columns are defined in fields, so we need to remove them + delete mappedRecord.id; + const eventInValidFormat = { id: gristEvent.id, fields: mappedRecord }; const table = await grist.getTable(); if (gristEvent.id) { await table.update(eventInValidFormat); @@ -242,7 +237,7 @@ async function upsertGristRecord(gristEvent){ } } -// grist expect date in seconds, but calendar is returning it in miliseconds, so we need to convert it +// grist expects date in seconds, but the calendar is returning it in milliseconds, so we need to convert it function roundEpochDateToSeconds(date) { return date/1000; } From 453b3a272f0a31d3bcb9a31aede022d029dd8a6c Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 16 Aug 2023 13:49:55 +0200 Subject: [PATCH 56/64] more typos and code quality fixes --- calendar/page.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index ff557baa..9f6fc441 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -198,16 +198,16 @@ async function calendarViewChanges(radiobutton) { } -// when user change a perspective of calendar we want this to be persisted in grist options between sessions. -// This is the place where we can react to this change and update calendar view, or when new session is started +// When a user changes a perspective of calendar, we want this to be persisted in grist options between sessions. +// this is the place where we can react to this change and update calendar view, or when new session is started // (so we are loading previous settings) let onGristSettingsChanged = function(options) { - let option = options?.calendarViewPerspective??'week'; + let option = options?.calendarViewPerspective ?? 'week'; this.calendarHandler.changeView(option); selectRadioButton(option); }; -// when user move or resize event on the calendar, we want to update the record in the table +// when user moves or resizes event on the calendar, we want to update the record in the table const onCalendarEventBeingUpdated = async (info) => { if (info.changes?.start || info.changes?.end) { const record = await grist.fetchSelectedRecord(info.event.id); @@ -244,21 +244,21 @@ function roundEpochDateToSeconds(date) { // conversion between calendar event object and grist flat format (so the one that is returned in onRecords event // and can be mapped by grist.mapColumnNamesBack) -function buildGristFlatFormatFromEventObject(TUIEvent) { +function buildGristFlatFormatFromEventObject(tuiEvent) { const gristEvent = { - startDate: roundEpochDateToSeconds(TUIEvent.start?.valueOf()), - endDate: roundEpochDateToSeconds(TUIEvent.end?.valueOf()), - isAllDay: TUIEvent.isAllday ? 1 : 0, - title: TUIEvent.title??"New Event" + startDate: roundEpochDateToSeconds(tuiEvent.start?.valueOf()), + endDate: roundEpochDateToSeconds(tuiEvent.end?.valueOf()), + isAllDay: tuiEvent.isAllday ? 1 : 0, + title: tuiEvent.title??"New Event" } - if(TUIEvent.id) gristEvent.id = TUIEvent.id; + if(tuiEvent.id) { gristEvent.id = tuiEvent.id; } return gristEvent; } -// when user select new date range on the calendar, we want to create new record in the table -const onNewDateBeingSelectedOnCalendar = async (info) => { +// when user selects new date range on the calendar, we want to create new record in the table +async function onNewDateBeingSelectedOnCalendar(info){ const gristEvent = buildGristFlatFormatFromEventObject(info); - upsertGristRecord(gristEvent); + await upsertGristRecord(gristEvent); } //helper function to select radio button in the GUI @@ -270,7 +270,7 @@ function selectRadioButton(value) { } } -// helper function to build calendar event object from grist flat record +// helper function to build a calendar event object from grist flat record function buildCalendarEventObject(record) { return { id: record.id, @@ -287,9 +287,9 @@ function buildCalendarEventObject(record) { // when some CRUD operation is performed on the table, we want to update calendar async function updateCalendar(records, mappings) { const mappedRecords = grist.mapColumnNames(records, mappings); - // if any records was successfully mapped, create or update them in the calendar + // if any records were successfully mapped, create or update them in the calendar if (mappedRecords) { const CalendarEventObjects = mappedRecords.map(buildCalendarEventObject); await this.calendarHandler.updateCalendarEvents(CalendarEventObjects); } -} +} \ No newline at end of file From 85e306472724e133bab4fe0ef26ec1be4c99c8e2 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Wed, 16 Aug 2023 16:43:37 +0200 Subject: [PATCH 57/64] unit tests fixes, waiting for the calendar being refreshed before asserting --- calendar/page.js | 36 +++++-- test/calendar.ts | 96 ++++++++++-------- ...Calendar-UnitTest.grist => Calendar.grist} | Bin test/getGrist.ts | 6 +- 4 files changed, 88 insertions(+), 50 deletions(-) rename test/fixtures/docs/{Calendar-UnitTest.grist => Calendar.grist} (100%) diff --git a/calendar/page.js b/calendar/page.js index 9f6fc441..d2f00d84 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -5,6 +5,12 @@ var grist; let calendarHandler; const CALENDAR_NAME = 'standardCalendar'; +//for tests +let dataVersion = Date.now(); +function testGetDataVersion(){ + return dataVersion; +} + //registering code to run when a document is ready function ready(fn) { if (document.readyState !== 'loading') { @@ -55,8 +61,8 @@ class CalendarHandler { this.calendar.on('clickEvent', async (info) => { await grist.setSelectedRows([info.event.id]); }); - this.calendar.on('selectDateTime', (info)=> { - onNewDateBeingSelectedOnCalendar(info); + this.calendar.on('selectDateTime', async (info)=> { + await onNewDateBeingSelectedOnCalendar(info); this.calendar.clearGridSelections(); }); } @@ -186,8 +192,8 @@ async function configureGristSettings() { // when a user selects a record in the table, we want to select it on the calendar function gristSelectedRecordChanged(record, mappings) { const mappedRecord = grist.mapColumnNames(record, mappings); - if (mappedRecord && CalendarHandler) { - CalendarHandler.selectRecord(mappedRecord); + if (mappedRecord && calendarHandler) { + calendarHandler.selectRecord(mappedRecord); } } @@ -203,7 +209,7 @@ async function calendarViewChanges(radiobutton) { // (so we are loading previous settings) let onGristSettingsChanged = function(options) { let option = options?.calendarViewPerspective ?? 'week'; - this.calendarHandler.changeView(option); + calendarHandler.changeView(option); selectRadioButton(option); }; @@ -284,12 +290,28 @@ function buildCalendarEventObject(record) { }; } -// when some CRUD operation is performed on the table, we want to update calendar +// when some CRUD operation is performed on the table, we want to update the calendar async function updateCalendar(records, mappings) { const mappedRecords = grist.mapColumnNames(records, mappings); // if any records were successfully mapped, create or update them in the calendar if (mappedRecords) { const CalendarEventObjects = mappedRecords.map(buildCalendarEventObject); - await this.calendarHandler.updateCalendarEvents(CalendarEventObjects); + await calendarHandler.updateCalendarEvents(CalendarEventObjects); + } + dataVersion = Date.now(); +} + +function testGetCalendarEvent(eventId){ + const calendarObject = calendarHandler.calendar.getEvent(eventId,CALENDAR_NAME); + if(calendarObject) + { + return{ + title: calendarObject?.title, + startDate: calendarObject?.start.toString(), + endDate: calendarObject?.end.toString(), + isAllDay: calendarObject?.isAllday??false + } + }else{ + return calendarObject } } \ No newline at end of file diff --git a/test/calendar.ts b/test/calendar.ts index bda15a42..29041dd6 100644 --- a/test/calendar.ts +++ b/test/calendar.ts @@ -1,29 +1,37 @@ -import {assert} from 'mocha-webdriver'; +import {assert, driver} from 'mocha-webdriver'; import {getGrist} from "./getGrist"; -//not to pretty way to get events from currently used calendar control. but it's working. -function getAbstractFromCalendarObject(eventId: number) { - return ` - const calendarObject = this.calendarHandler.calendar.getEvent(${eventId},"cal1"); - if(calendarObject) - { - return{ - title: calendarObject?.title, - startDate: calendarObject?.start.toString(), - endDate: calendarObject?.end.toString(), - isAllDay: calendarObject?.isAllday??false - } - }else{ - return calendarObject - }` +//not a pretty way to get events from currently used calendar control. but it's working. +function buildGetCalendarObjectScript(eventId: number) { + return `return testGetCalendarEvent(${eventId});` } describe('calendar', function () { this.timeout(20000); const grist = getGrist(); + async function executeAndWaitForCalendar(action: () => Promise) { + const oldDataVersion = await getDateVersion(); + await action(); + await driver.wait(async ()=> { + const dataVersion = await getDateVersion(); + return dataVersion > oldDataVersion; + }); + } + + //wait until the event is loaded on the calendar + async function getCalendarEvent(eventId: number) { + let mappedObject:any; + mappedObject = await grist.executeScriptOnCustomWidget(buildGetCalendarObjectScript(eventId)); + return mappedObject; + } + + async function getDateVersion(){ + return await grist.executeScriptOnCustomWidget('return testGetDataVersion()'); + } + before(async function () { - const docId = await grist.upload('test/fixtures/docs/Calendar-UnitTest.grist'); + const docId = await grist.upload('test/fixtures/docs/Calendar.grist'); await grist.openDoc(docId); await grist.toggleSidePanel('right', 'open'); await grist.addNewSection(/Custom/, /Table1/); @@ -37,13 +45,15 @@ describe('calendar', function () { }); it('should create new event when new row is added', async function () { - await grist.sendActions([['AddRecord', 'Table1', -1, { - From: new Date('2023-08-03 13:00'), - To: new Date('2023-08-03 14:00'), - Label: "New Event", - IsFullDay: false - }]]); - const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(1)); + await executeAndWaitForCalendar(async () => { + await grist.sendActionsAndWaitForServer([['AddRecord', 'Table1', -1, { + From: new Date('2023-08-03 13:00'), + To: new Date('2023-08-03 14:00'), + Label: "New Event", + IsFullDay: false + }]]); + }); + const mappedObject = await getCalendarEvent(1); assert.deepEqual(mappedObject, { title: "New Event", startDate: new Date('2023-08-03 13:00').toString(), @@ -53,13 +63,15 @@ describe('calendar', function () { }); it('should create new all day event when new row is added', async function () { - await grist.sendActions([['AddRecord', 'Table1', -1, { - From: new Date('2023-08-04 13:00'), - To: new Date('2023-08-04 14:00'), - Label: "All Day Event", - IsFullDay: true - }]]); - const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(2)); + await executeAndWaitForCalendar(async () => { + await grist.sendActionsAndWaitForServer([['AddRecord', 'Table1', -1, { + From: new Date('2023-08-04 13:00'), + To: new Date('2023-08-04 14:00'), + Label: "All Day Event", + IsFullDay: true + }]]); + }); + const mappedObject = await getCalendarEvent(2); assert.equal(mappedObject.title, "All Day Event"); assert.equal(mappedObject.isAllDay, true); // Ignoring time component, because it's not important in full day events @@ -70,13 +82,15 @@ describe('calendar', function () { }); it('should update event when table data is changed', async function () { - await grist.sendActions([['UpdateRecord', 'Table1', 1, { - From: new Date('2023-08-03 13:00'), - To: new Date('2023-08-03 15:00'), - Label: "New Event", - IsFullDay: false - }]]); - const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(1)); + await executeAndWaitForCalendar(async () => { + await grist.sendActionsAndWaitForServer([['UpdateRecord', 'Table1', 1, { + From: new Date('2023-08-03 13:00'), + To: new Date('2023-08-03 15:00'), + Label: "New Event", + IsFullDay: false + }]]); + }); + const mappedObject = await getCalendarEvent(1); assert.deepEqual(mappedObject, { title: "New Event", startDate: new Date('2023-08-03 13:00').toString(), @@ -86,8 +100,10 @@ describe('calendar', function () { }); it('should remove event when row is deleted', async function () { - await grist.sendActions([['RemoveRecord', 'Table1', 1]]); - const mappedObject = await grist.getCustomWidgetObject(getAbstractFromCalendarObject(1)); + await executeAndWaitForCalendar(async () => { + await grist.sendActionsAndWaitForServer([['RemoveRecord', 'Table1', 1]]); + }); + const mappedObject = await getCalendarEvent(1) assert.notExists(mappedObject); }); diff --git a/test/fixtures/docs/Calendar-UnitTest.grist b/test/fixtures/docs/Calendar.grist similarity index 100% rename from test/fixtures/docs/Calendar-UnitTest.grist rename to test/fixtures/docs/Calendar.grist diff --git a/test/getGrist.ts b/test/getGrist.ts index 8bff4110..9dd36c77 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -192,7 +192,7 @@ export class GristUtils extends GristWebDriverUtils { await this.waitForServer(); } - public async sendActions(actions: UserAction[]) { + public async sendActionsAndWaitForServer(actions: UserAction[], optTimeout: number=2000){ const result = await driver.executeAsyncScript(` const done = arguments[arguments.length - 1]; const prom = gristDocPageModel.gristDoc.get().docModel.docData.sendActions(${JSON.stringify(actions)}); @@ -202,7 +202,7 @@ export class GristUtils extends GristWebDriverUtils { if (result) { throw new Error(result as string); } - await this.waitForServer(); + await this.waitForServer(optTimeout); } public async waitForServer(optTimeout: number = 2000) { @@ -276,7 +276,7 @@ export class GristUtils extends GristWebDriverUtils { } } - public async getCustomWidgetObject(script: string): Promise { + public async executeScriptOnCustomWidget(script: string): Promise { const iframe = this.driver.find('iframe'); try { await this.driver.switchTo().frame(iframe); From c407635f69eb87ba512e24361c92ef14330c5e52 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 17 Aug 2023 11:10:41 +0200 Subject: [PATCH 58/64] revert unnecessary changes --- test/getGrist.ts | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/test/getGrist.ts b/test/getGrist.ts index 716d0f25..40fdbb17 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -52,16 +52,6 @@ const serverSettings = { export class GristTestServer { private _assetServer?: ChildProcess; - public get gristUrl() { - const {gristPort} = serverSettings; - return `http://localhost:${gristPort}`; - } - - public get assetUrl() { - const {contentPort} = serverSettings; - return `http://localhost:${contentPort}`; - } - public async start() { await this.stop(); const {gristContainerName, gristImage, gristPort, contentPort} = serverSettings; @@ -82,10 +72,8 @@ export class GristTestServer { } const pwd = process.cwd(); this._assetServer = spawn('live-server', [ - `--port=${contentPort}`, - `--middleware=${pwd}/buildtools/rewriteUrl.js`, - `-q`, - `--no-browser` + `--port=${contentPort}`, '--no-browser', '-q', + `--middleware=${pwd}/buildtools/rewriteUrl.js` ], { env: { ...process.env, @@ -114,6 +102,16 @@ export class GristTestServer { this._assetServer = undefined; } } + + public get gristUrl() { + const {gristPort} = serverSettings; + return `http://localhost:${gristPort}`; + } + + public get assetUrl() { + const {contentPort} = serverSettings; + return `http://localhost:${contentPort}`; + } } export class GristUtils extends GristWebDriverUtils { @@ -150,9 +148,7 @@ export class GristUtils extends GristWebDriverUtils { } try { const resp = await fetch(this.server.assetUrl); - if (resp.status === 200) { - break; - } + if (resp.status === 200) { break; } } catch (e) { // we expect fetch failures initially. } From 727e2cfb4d59ea45204d84f23af1272bc0dca327 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 17 Aug 2023 12:27:18 +0200 Subject: [PATCH 59/64] sendActionsAndWaitForServer goes from string to function --- test/getGrist.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/getGrist.ts b/test/getGrist.ts index 40fdbb17..26a7276b 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -189,12 +189,12 @@ export class GristUtils extends GristWebDriverUtils { } public async sendActionsAndWaitForServer(actions: UserAction[], optTimeout: number=2000){ - const result = await driver.executeAsyncScript(` - const done = arguments[arguments.length - 1]; - const prom = gristDocPageModel.gristDoc.get().docModel.docData.sendActions(${JSON.stringify(actions)}); - prom.then(() => done(null)); - prom.catch((err) => done(String(err?.message || err))); - `); + //const flatActions = JSON.stringify(actions); + const result = await driver.executeAsyncScript(async (actions:any, done:Function)=> { + const prom = (window as any).gristDocPageModel.gristDoc.get().docModel.docData.sendActions(actions); + prom.then(() => done(null)); + prom.catch((err:any) => done(String(err?.message || err))); + },actions); if (result) { throw new Error(result as string); } From d5ec8de7d73bb2d26cd29fb89f9e12c205ab2e62 Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 17 Aug 2023 14:13:53 +0200 Subject: [PATCH 60/64] removing unused function --- test/getGrist.ts | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/test/getGrist.ts b/test/getGrist.ts index 26a7276b..e82cf8ac 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -1,7 +1,7 @@ import {ChildProcess, execSync, spawn} from 'child_process'; import FormData from 'form-data'; import fs from 'fs'; -import {driver, WebDriver} from 'mocha-webdriver'; +import {driver} from 'mocha-webdriver'; import fetch from 'node-fetch'; import {GristWebDriverUtils} from 'test/gristWebDriverUtils'; @@ -236,11 +236,11 @@ export class GristUtils extends GristWebDriverUtils { public async setCustomWidgetMapping(name: string, value: string | RegExp) { const click = async (selector: string) => { try { - await driver.findWait(`${selector}`, 2000).click(); + await driver.findWait(selector, 2000).click(); } catch (e) { //sometimes here we get into "detached" state and test fail. //if this happened, just try one more time - await driver.findWait(`${selector}`, 2000).click(); + await driver.findWait(selector, 2000).click(); } }; const toggleDrop = async (selector: string) => await click(`${selector} .test-select-open`); @@ -264,16 +264,6 @@ export class GristUtils extends GristWebDriverUtils { } } - public async executeInIframe(fnc: (driver: WebDriver) => void) { - const iframe = this.driver.find('iframe'); - try { - await this.driver.switchTo().frame(iframe); - await fnc(this.driver); - } finally { - await this.driver.switchTo().defaultContent(); - } - } - public async executeScriptOnCustomWidget(script: string): Promise { const iframe = this.driver.find('iframe'); try { From 301fb988905953833ec636d690b65ce3bc86a17a Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 17 Aug 2023 15:23:13 +0200 Subject: [PATCH 61/64] tests for changing perspective and date --- calendar/index.html | 17 +++++++------- calendar/page.js | 5 ++++ test/calendar.ts | 56 +++++++++++++++++++++++++++++++++++++++++++-- test/getGrist.ts | 4 ++-- 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/calendar/index.html b/calendar/index.html index 18b7a012..116d0786 100644 --- a/calendar/index.html +++ b/calendar/index.html @@ -6,22 +6,23 @@ + Calendar Widget
- - - + + +
- - - - - + + + + +
diff --git a/calendar/page.js b/calendar/page.js index d2f00d84..69535be8 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -314,4 +314,9 @@ function testGetCalendarEvent(eventId){ }else{ return calendarObject } +} + +function testGetCalendarViewName(){ + // noinspection JSUnresolvedReference + return calendarHandler.calendar.getViewName(); } \ No newline at end of file diff --git a/test/calendar.ts b/test/calendar.ts index f4667cd1..019898b2 100644 --- a/test/calendar.ts +++ b/test/calendar.ts @@ -26,8 +26,12 @@ describe('calendar', function () { return mappedObject; } - async function getDateVersion(){ - return await grist.executeScriptOnCustomWidget('return testGetDataVersion()'); + async function getCalendarSettings():Promise { + return await grist.executeScriptOnCustomWidget('return testGetCalendarViewName()'); + } + + async function getDateVersion(): Promise{ + return await grist.executeScriptOnCustomWidget('return testGetDataVersion()'); } before(async function () { @@ -107,6 +111,54 @@ describe('calendar', function () { assert.notExists(mappedObject); }); + it('should change calendar perspective when button is pressed', async function () { + await grist.inCustomWidget(async () => { + await driver.findWait('#calendar-day-label', 200).click(); + }); + let viewType = await getCalendarSettings(); + assert.equal(viewType, 'day'); + await grist.inCustomWidget(async () => { + await driver.findWait('#calendar-month-label', 200).click(); + }); + viewType = await getCalendarSettings(); + assert.equal(viewType, 'month'); + await grist.inCustomWidget(async () => { + await driver.findWait('#calendar-week-label', 200).click(); + }); + viewType = await getCalendarSettings(); + assert.equal(viewType, 'week'); + }) + + it('should navigate to appropriate time periods when button is pressed', async function () { + const today = new Date(); + + // Function to navigate and validate date change + const navigateAndValidate = async (buttonSelector:string, daysToAdd:number) => { + await grist.inCustomWidget(async () => { + await driver.findWait(buttonSelector, 200).click(); + }); + + const newDate = await grist.executeScriptOnCustomWidget( + 'return calendarHandler.calendar.getDate().d.toDate().toDateString()' + ); + + const expectedDate = new Date(today); + expectedDate.setDate(today.getDate() + daysToAdd); + + assert.equal(newDate, expectedDate.toDateString()); + }; + + // Navigate to the previous week + await navigateAndValidate('#calendar-button-previous', -7); + + // Navigate to today + await navigateAndValidate('#calendar-button-today', 0); + + // Navigate to next week + await navigateAndValidate('#calendar-button-next', 7); + }); + + //TODO: test adding new events and moving existing one on the calendar. ToastUI is not best optimalized for drag and drop tests in mocha and i cannot yet make it working correctly. diff --git a/test/getGrist.ts b/test/getGrist.ts index e82cf8ac..92ca868f 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -264,12 +264,12 @@ export class GristUtils extends GristWebDriverUtils { } } - public async executeScriptOnCustomWidget(script: string): Promise { + public async executeScriptOnCustomWidget(script: string|Function): Promise { const iframe = this.driver.find('iframe'); try { await this.driver.switchTo().frame(iframe); const jsValue = await this.driver.executeScript(script); - return await jsValue; + return jsValue as T; } finally { await this.driver.switchTo().defaultContent(); } From 591896671aa16b4a80bcdccf1f390f6c9b070e8c Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 17 Aug 2023 16:37:07 +0200 Subject: [PATCH 62/64] filtering data for table.update --- calendar/page.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index 69535be8..9470295f 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -104,7 +104,7 @@ class CalendarHandler { // update calendar events based on the collection of records from the grist table. async updateCalendarEvents(calendarEvents) { - // we need to keep track of the ids of the events that are currently in the calendar to compare it + // we need to keep track the ids of the events that are currently in the calendar to compare it // with the new set of events when they come. const currentIds = new Set(); for (const record of calendarEvents) { @@ -216,14 +216,12 @@ let onGristSettingsChanged = function(options) { // when user moves or resizes event on the calendar, we want to update the record in the table const onCalendarEventBeingUpdated = async (info) => { if (info.changes?.start || info.changes?.end) { - const record = await grist.fetchSelectedRecord(info.event.id); - if (record) { - // get all the record data from the event, and update only start and end date - const gristEvent = buildGristFlatFormatFromEventObject(info.event) + let gristEvent = {}; + gristEvent.id = info.event.id; if(info.changes.start) gristEvent.startDate = roundEpochDateToSeconds(info.changes.start.valueOf()); if(info.changes.end) gristEvent.endDate = roundEpochDateToSeconds(info.changes.end.valueOf()); await upsertGristRecord(gristEvent); - } + //} } }; @@ -234,7 +232,10 @@ async function upsertGristRecord(gristEvent){ const mappedRecord = grist.mapColumnNamesBack(gristEvent); // we cannot save record is some unexpected columns are defined in fields, so we need to remove them delete mappedRecord.id; - const eventInValidFormat = { id: gristEvent.id, fields: mappedRecord }; + //mapColumnNamesBack is returning undefined for all absent fields, so we need to remove them as well + const filteredRecord = Object.fromEntries(Object.entries(mappedRecord) + .filter(([key, value]) => value !== undefined)); + const eventInValidFormat = { id: gristEvent.id, fields: filteredRecord }; const table = await grist.getTable(); if (gristEvent.id) { await table.update(eventInValidFormat); From d71488b73d21b849f8528b36b729b54d4a81f44f Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Thu, 17 Aug 2023 17:08:13 +0200 Subject: [PATCH 63/64] build script fixes, cheking record types when grist selection is updated --- .github/workflows/main.yml | 2 +- calendar/page.js | 29 ++++++++++++++++++----------- package.json | 1 - 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5b0cd14e..da3ed852 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: run: yarn install - name: Build Node.js test code - run: yarn run build:test + run: yarn run build http://localhost:9998 - name: Cache Docker images. uses: ScribeMD/docker-cache@0.3.3 diff --git a/calendar/page.js b/calendar/page.js index 9470295f..a58e4d76 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -20,6 +20,12 @@ function ready(fn) { } } +function isRecordValid(record){ + return record.startDate instanceof Date && + record.endDate instanceof Date && + typeof record.title === 'string' +} + class CalendarHandler { static _mainColor = getComputedStyle(document.documentElement) .getPropertyValue('--main-color'); @@ -69,17 +75,18 @@ class CalendarHandler { // navigate to the selected date in the calendar and scroll to the time period of the event selectRecord(record) { - if (this._selectedRecordId) { - this.calendar.updateEvent(this._selectedRecordId, CALENDAR_NAME, {backgroundColor: CalendarHandler._mainColor}); - } - this.calendar.updateEvent(record.id, CALENDAR_NAME, {backgroundColor: CalendarHandler._selectedColor}); - this._selectedRecordId = record.id; - this.calendar.setDate(record.startDate); - var dom = document.querySelector('.toastui-calendar-time'); - const middleHour = record.startDate.getHours() + if(isRecordValid(record)) { + if (this._selectedRecordId) { + this.calendar.updateEvent(this._selectedRecordId, CALENDAR_NAME, {backgroundColor: CalendarHandler._mainColor}); + } + this.calendar.updateEvent(record.id, CALENDAR_NAME, {backgroundColor: CalendarHandler._selectedColor}); + this._selectedRecordId = record.id; + this.calendar.setDate(record.startDate); + var dom = document.querySelector('.toastui-calendar-time'); + const middleHour = record.startDate.getHours() + (record.endDate.getHours() - record.startDate.getHours()) / 2; - dom.scrollTo({top: (dom.clientHeight / 24) * middleHour, behavior: 'smooth'}); - + dom.scrollTo({top: (dom.clientHeight / 24) * middleHour, behavior: 'smooth'}); + } } // change calendar perspective between week, month and day. @@ -296,7 +303,7 @@ async function updateCalendar(records, mappings) { const mappedRecords = grist.mapColumnNames(records, mappings); // if any records were successfully mapped, create or update them in the calendar if (mappedRecords) { - const CalendarEventObjects = mappedRecords.map(buildCalendarEventObject); + const CalendarEventObjects = mappedRecords.filter(isRecordValid).map(buildCalendarEventObject); await calendarHandler.updateCalendarEvents(CalendarEventObjects); } dataVersion = Date.now(); diff --git a/package.json b/package.json index 06863e62..137d79f6 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "build": "tsc --build && node ./buildtools/publish.js", "serve": "live-server --port=8585 --no-browser -q", "build:dev": "node ./buildtools/publish.js http://localhost:8585", - "build:test": "tsc --build && node ./buildtools/publish.js http://localhost:9998", "serve:dev": "live-server --port=8585 --no-browser -q --middleware=$(pwd)/buildtools/rewriteUrl.js", "watch": "nodemon --ignore manifest.json -e js,json --exec 'npm run build:dev'", "dev": "echo 'Starting local server and watching for changes.\nStart Grist with an environmental variable GRIST_WIDGET_LIST_URL=http://localhost:8585/manifest.json' && npm run watch 1> /dev/null & npm run serve:dev 1> /dev/null", From e24c24a265c5bde43cf6032e8893b555eca5b06b Mon Sep 17 00:00:00 2001 From: Jakub Serafin Date: Fri, 18 Aug 2023 10:36:33 +0200 Subject: [PATCH 64/64] review fixes --- calendar/page.js | 12 ++++++------ test/calendar.ts | 6 ++---- test/getGrist.ts | 29 +++++++++++------------------ 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/calendar/page.js b/calendar/page.js index a58e4d76..37dd8a8c 100644 --- a/calendar/page.js +++ b/calendar/page.js @@ -20,7 +20,7 @@ function ready(fn) { } } -function isRecordValid(record){ +function isRecordValid(record) { return record.startDate instanceof Date && record.endDate instanceof Date && typeof record.title === 'string' @@ -75,14 +75,14 @@ class CalendarHandler { // navigate to the selected date in the calendar and scroll to the time period of the event selectRecord(record) { - if(isRecordValid(record)) { + if (isRecordValid(record)) { if (this._selectedRecordId) { this.calendar.updateEvent(this._selectedRecordId, CALENDAR_NAME, {backgroundColor: CalendarHandler._mainColor}); } this.calendar.updateEvent(record.id, CALENDAR_NAME, {backgroundColor: CalendarHandler._selectedColor}); this._selectedRecordId = record.id; this.calendar.setDate(record.startDate); - var dom = document.querySelector('.toastui-calendar-time'); + const dom = document.querySelector('.toastui-calendar-time'); const middleHour = record.startDate.getHours() + (record.endDate.getHours() - record.startDate.getHours()) / 2; dom.scrollTo({top: (dom.clientHeight / 24) * middleHour, behavior: 'smooth'}); @@ -265,12 +265,12 @@ function buildGristFlatFormatFromEventObject(tuiEvent) { isAllDay: tuiEvent.isAllday ? 1 : 0, title: tuiEvent.title??"New Event" } - if(tuiEvent.id) { gristEvent.id = tuiEvent.id; } + if (tuiEvent.id) { gristEvent.id = tuiEvent.id; } return gristEvent; } -// when user selects new date range on the calendar, we want to create new record in the table -async function onNewDateBeingSelectedOnCalendar(info){ +// when user selects new date range on the calendar, we want to create a new record in the table +async function onNewDateBeingSelectedOnCalendar(info) { const gristEvent = buildGristFlatFormatFromEventObject(info); await upsertGristRecord(gristEvent); } diff --git a/test/calendar.ts b/test/calendar.ts index 019898b2..0dd8cb24 100644 --- a/test/calendar.ts +++ b/test/calendar.ts @@ -78,7 +78,7 @@ describe('calendar', function () { const mappedObject = await getCalendarEvent(2); assert.equal(mappedObject.title, "All Day Event"); assert.equal(mappedObject.isAllDay, true); - // Ignoring time component, because it's not important in full day events + // Ignoring a time component, because it's not important in full day events assert.equal(new Date(mappedObject.startDate).toDateString(), new Date('2023-08-04 00:00:00').toDateString()); assert.equal(new Date(mappedObject.endDate).toDateString(), @@ -158,8 +158,6 @@ describe('calendar', function () { await navigateAndValidate('#calendar-button-next', 7); }); - - - //TODO: test adding new events and moving existing one on the calendar. ToastUI is not best optimalized for drag and drop tests in mocha and i cannot yet make it working correctly. + //TODO: test adding new events and moving existing one on the calendar. ToastUI is not best optimized for drag and drop tests in mocha and i cannot yet make it working correctly. }); diff --git a/test/getGrist.ts b/test/getGrist.ts index 92ca868f..333d9ef7 100644 --- a/test/getGrist.ts +++ b/test/getGrist.ts @@ -188,28 +188,21 @@ export class GristUtils extends GristWebDriverUtils { await this.waitForServer(); } - public async sendActionsAndWaitForServer(actions: UserAction[], optTimeout: number=2000){ - //const flatActions = JSON.stringify(actions); - const result = await driver.executeAsyncScript(async (actions:any, done:Function)=> { - const prom = (window as any).gristDocPageModel.gristDoc.get().docModel.docData.sendActions(actions); - prom.then(() => done(null)); - prom.catch((err:any) => done(String(err?.message || err))); - },actions); + public async sendActionsAndWaitForServer(actions: UserAction[], optTimeout: number = 2000) { + const result = await driver.executeAsyncScript(async (actions: any, done: Function) => { + try { + await (window as any).gristDocPageModel.gristDoc.get().docModel.docData.sendActions(actions); + done(null); + } catch (err) { + done(String(err?.message || err)); + } + }, actions); if (result) { throw new Error(result as string); } await this.waitForServer(optTimeout); } - public async waitForServer(optTimeout: number = 2000) { - await this.driver.wait(() => this.driver.executeScript( - "return window.gristApp && (!window.gristApp.comm || !window.gristApp.comm.hasActiveRequests())" - + " && window.gristApp.testNumPendingApiRequests() === 0", - optTimeout, - "Timed out waiting for server requests to complete" - )); - } - public async clickWidgetPane() { const elem = this.driver.find('.test-config-widget-select .test-select-open'); if (await elem.isPresent()) { @@ -240,7 +233,7 @@ export class GristUtils extends GristWebDriverUtils { } catch (e) { //sometimes here we get into "detached" state and test fail. //if this happened, just try one more time - await driver.findWait(selector, 2000).click(); + await driver.findWait(selector, 2000).click(); } }; const toggleDrop = async (selector: string) => await click(`${selector} .test-select-open`); @@ -264,7 +257,7 @@ export class GristUtils extends GristWebDriverUtils { } } - public async executeScriptOnCustomWidget(script: string|Function): Promise { + public async executeScriptOnCustomWidget(script: string | Function): Promise { const iframe = this.driver.find('iframe'); try { await this.driver.switchTo().frame(iframe);