diff --git a/api/Dockerfile.bundle b/api/Dockerfile.bundle index 54709db89..a1577d8c3 100644 --- a/api/Dockerfile.bundle +++ b/api/Dockerfile.bundle @@ -1,4 +1,4 @@ -FROM python:3.6-slim +FROM python:3.9.7-slim LABEL Maintainer="Rajesh Rajendran" WORKDIR /work COPY . . diff --git a/api/chalicelib/core/alerts_processor.py b/api/chalicelib/core/alerts_processor.py index 80973fadd..21249773c 100644 --- a/api/chalicelib/core/alerts_processor.py +++ b/api/chalicelib/core/alerts_processor.py @@ -119,12 +119,6 @@ def Build(a): q = f"""SELECT coalesce(value,0) AS value, coalesce(value,0) {a["query"]["operator"]} {a["query"]["right"]} AS valid""" - # if len(colDef.group) > 0 { - # subQ = subQ.Column(colDef.group + " AS group_value") - # subQ = subQ.GroupBy(colDef.group) - # q = q.Column("group_value") - # } - if a["detectionMethod"] == schemas.AlertDetectionMethod.threshold: if a["seriesId"] is not None: q += f""" FROM ({subQ}) AS stat""" @@ -134,16 +128,6 @@ def Build(a): params = {**params, **full_args, "startDate": TimeUTC.now() - a["options"]["currentPeriod"] * 60 * 1000} else: if a["options"]["change"] == schemas.AlertDetectionChangeType.change: - # if len(colDef.group) > 0: - # subq1 := subQ.Where(sq.Expr("timestamp>=$2 ", time.Now().Unix()-a.Options.CurrentPeriod * 60)) - # sub2, args2, _ := subQ.Where( - # sq.And{ - # sq.Expr("timestamp<$3 ", time.Now().Unix()-a.Options.CurrentPeriod * 60), - # sq.Expr("timestamp>=$4 ", time.Now().Unix()-2 * a.Options.CurrentPeriod * 60), - # }).ToSql() - # sub1 := sq.Select("group_value", "(stat1.value-stat2.value) AS value").FromSelect(subq1, "stat1").JoinClause("INNER JOIN ("+sub2+") AS stat2 USING(group_value)", args2...) - # q = q.FromSelect(sub1, "stat") - # else: if a["seriesId"] is not None: sub2 = subQ.replace("%(startDate)s", "%(timestamp_sub2)s").replace("%(endDate)s", "%(startDate)s") sub1 = f"SELECT (({subQ})-({sub2})) AS value" @@ -163,16 +147,6 @@ def Build(a): q += f" FROM ( {sub1} ) AS stat" else: - # if len(colDef.group) >0 { - # subq1 := subQ.Where(sq.Expr("timestamp>=$2 ", time.Now().Unix()-a.Options.CurrentPeriod * 60)) - # sub2, args2, _ := subQ.Where( - # sq.And{ - # sq.Expr("timestamp<$3 ", time.Now().Unix()-a.Options.CurrentPeriod * 60), - # sq.Expr("timestamp>=$4 ", time.Now().Unix()-a.Options.PreviousPeriod * 60-a.Options.CurrentPeriod * 60), - # }).ToSql() - # sub1 := sq.Select("group_value", "(stat1.value/stat2.value-1)*100 AS value").FromSelect(subq1, "stat1").JoinClause("INNER JOIN ("+sub2+") AS stat2 USING(group_value)", args2...) - # q = q.FromSelect(sub1, "stat") - # } else { if a["seriesId"] is not None: sub2 = subQ.replace("%(startDate)s", "%(timestamp_sub2)s").replace("%(endDate)s", "%(startDate)s") sub1 = f"SELECT (({subQ})/NULLIF(({sub2}),0)-1)*100 AS value" diff --git a/api/chalicelib/core/custom_metrics.py b/api/chalicelib/core/custom_metrics.py index eb918b222..6c8e7ddc3 100644 --- a/api/chalicelib/core/custom_metrics.py +++ b/api/chalicelib/core/custom_metrics.py @@ -1,35 +1,50 @@ import json +from typing import Union import schemas from chalicelib.core import sessions from chalicelib.utils import helper, pg_client from chalicelib.utils.TimeUTC import TimeUTC +PIE_CHART_GROUP = 5 -def try_live(project_id, data: schemas.TryCustomMetricsSchema): + +def __try_live(project_id, data: schemas.CreateCustomMetricsSchema): results = [] for i, s in enumerate(data.series): s.filter.startDate = data.startDate s.filter.endDate = data.endDate results.append(sessions.search2_series(data=s.filter, project_id=project_id, density=data.density, - view_type=data.viewType)) - if data.viewType == schemas.MetricViewType.progress: + view_type=data.view_type, metric_type=data.metric_type, + metric_of=data.metric_of, metric_value=data.metric_value)) + if data.view_type == schemas.MetricTimeseriesViewType.progress: r = {"count": results[-1]} diff = s.filter.endDate - s.filter.startDate s.filter.startDate = data.endDate s.filter.endDate = data.endDate - diff r["previousCount"] = sessions.search2_series(data=s.filter, project_id=project_id, density=data.density, - view_type=data.viewType) + view_type=data.view_type, metric_type=data.metric_type, + metric_of=data.metric_of, metric_value=data.metric_value) r["countProgress"] = helper.__progress(old_val=r["previousCount"], new_val=r["count"]) + # r["countProgress"] = ((r["count"] - r["previousCount"]) / r["previousCount"]) * 100 \ + # if r["previousCount"] > 0 else 0 r["seriesName"] = s.name if s.name else i + 1 r["seriesId"] = s.series_id if s.series_id else None results[-1] = r + elif data.view_type == schemas.MetricTableViewType.pie_chart: + if len(results[i].get("values", [])) > PIE_CHART_GROUP: + results[i]["values"] = results[i]["values"][:PIE_CHART_GROUP] \ + + [{ + "name": "Others", "group": True, + "sessionCount": sum(r["sessionCount"] for r in results[i]["values"][PIE_CHART_GROUP:]) + }] + return results -def merged_live(project_id, data: schemas.TryCustomMetricsSchema): - series_charts = try_live(project_id=project_id, data=data) - if data.viewType == schemas.MetricViewType.progress: +def merged_live(project_id, data: schemas.CreateCustomMetricsSchema): + series_charts = __try_live(project_id=project_id, data=data) + if data.view_type == schemas.MetricTimeseriesViewType.progress or data.metric_type == schemas.MetricType.table: return series_charts results = [{}] * len(series_charts[0]) for i in range(len(results)): @@ -39,13 +54,30 @@ def merged_live(project_id, data: schemas.TryCustomMetricsSchema): return results -def make_chart(project_id, user_id, metric_id, data: schemas.CustomMetricChartPayloadSchema): +def __get_merged_metric(project_id, user_id, metric_id, + data: Union[schemas.CustomMetricChartPayloadSchema, + schemas.CustomMetricSessionsPayloadSchema]) \ + -> Union[schemas.CreateCustomMetricsSchema, None]: metric = get(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False) if metric is None: return None - metric: schemas.TryCustomMetricsSchema = schemas.TryCustomMetricsSchema.parse_obj({**data.dict(), **metric}) - series_charts = try_live(project_id=project_id, data=metric) - if data.viewType == schemas.MetricViewType.progress: + metric: schemas.CreateCustomMetricsSchema = schemas.CreateCustomMetricsSchema.parse_obj({**data.dict(), **metric}) + if len(data.filters) > 0 or len(data.events) > 0: + for s in metric.series: + if len(data.filters) > 0: + s.filter.filters += data.filters + if len(data.events) > 0: + s.filter.events += data.events + return metric + + +def make_chart(project_id, user_id, metric_id, data: schemas.CustomMetricChartPayloadSchema): + metric: schemas.CreateCustomMetricsSchema = __get_merged_metric(project_id=project_id, user_id=user_id, + metric_id=metric_id, data=data) + if metric is None: + return None + series_charts = __try_live(project_id=project_id, data=metric) + if metric.view_type == schemas.MetricTimeseriesViewType.progress or metric.metric_type == schemas.MetricType.table: return series_charts results = [{}] * len(series_charts[0]) for i in range(len(results)): @@ -55,11 +87,11 @@ def make_chart(project_id, user_id, metric_id, data: schemas.CustomMetricChartPa return results -def get_sessions(project_id, user_id, metric_id, data: schemas.CustomMetricRawPayloadSchema): - metric = get(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False) +def get_sessions(project_id, user_id, metric_id, data: schemas.CustomMetricSessionsPayloadSchema): + metric: schemas.CreateCustomMetricsSchema = __get_merged_metric(project_id=project_id, user_id=user_id, + metric_id=metric_id, data=data) if metric is None: return None - metric: schemas.TryCustomMetricsSchema = schemas.TryCustomMetricsSchema.parse_obj({**data.dict(), **metric}) results = [] for s in metric.series: s.filter.startDate = data.startDate @@ -82,8 +114,10 @@ def create(project_id, user_id, data: schemas.CreateCustomMetricsSchema): data.series = None params = {"user_id": user_id, "project_id": project_id, **data.dict(), **_data} query = cur.mogrify(f"""\ - WITH m AS (INSERT INTO metrics (project_id, user_id, name) - VALUES (%(project_id)s, %(user_id)s, %(name)s) + WITH m AS (INSERT INTO metrics (project_id, user_id, name, is_public, + view_type, metric_type, metric_of, metric_value, metric_format) + VALUES (%(project_id)s, %(user_id)s, %(name)s, %(is_public)s, + %(view_type)s, %(metric_type)s, %(metric_of)s, %(metric_value)s, %(metric_format)s) RETURNING *) INSERT INTO metric_series(metric_id, index, name, filter) @@ -98,32 +132,22 @@ def create(project_id, user_id, data: schemas.CreateCustomMetricsSchema): return {"data": get(metric_id=r["metric_id"], project_id=project_id, user_id=user_id)} -def __get_series_id(metric_id): - with pg_client.PostgresClient() as cur: - cur.execute( - cur.mogrify( - """SELECT series_id - FROM metric_series - WHERE metric_series.metric_id = %(metric_id)s - AND metric_series.deleted_at ISNULL;""", - {"metric_id": metric_id} - ) - ) - rows = cur.fetchall() - return [r["series_id"] for r in rows] - - def update(metric_id, user_id, project_id, data: schemas.UpdateCustomMetricsSchema): - series_ids = __get_series_id(metric_id) + metric = get(metric_id=metric_id, project_id=project_id, user_id=user_id, flatten=False) + if metric is None: + return None + series_ids = [r["seriesId"] for r in metric["series"]] n_series = [] d_series_ids = [] u_series = [] u_series_ids = [] params = {"metric_id": metric_id, "is_public": data.is_public, "name": data.name, - "user_id": user_id, "project_id": project_id} + "user_id": user_id, "project_id": project_id, "view_type": data.view_type, + "metric_type": data.metric_type, "metric_of": data.metric_of, + "metric_value": data.metric_value, "metric_format": data.metric_format} for i, s in enumerate(data.series): prefix = "u_" - if s.series_id is None: + if s.series_id is None or s.series_id not in series_ids: n_series.append({"i": i, "s": s}) prefix = "n_" s.index = i @@ -165,7 +189,10 @@ def update(metric_id, user_id, project_id, data: schemas.UpdateCustomMetricsSche query = cur.mogrify(f"""\ {"WITH " if len(sub_queries) > 0 else ""}{",".join(sub_queries)} UPDATE metrics - SET name = %(name)s, is_public= %(is_public)s + SET name = %(name)s, is_public= %(is_public)s, + view_type= %(view_type)s, metric_type= %(metric_type)s, + metric_of= %(metric_of)s, metric_value= %(metric_value)s, + metric_format= %(metric_format)s WHERE metric_id = %(metric_id)s AND project_id = %(project_id)s AND (user_id = %(user_id)s OR is_public) @@ -224,7 +251,7 @@ def get(metric_id, project_id, user_id, flatten=True): cur.mogrify( """SELECT * FROM metrics - LEFT JOIN LATERAL (SELECT jsonb_agg(metric_series.* ORDER BY index) AS series + LEFT JOIN LATERAL (SELECT COALESCE(jsonb_agg(metric_series.* ORDER BY index),'[]'::jsonb) AS series FROM metric_series WHERE metric_series.metric_id = metrics.metric_id AND metric_series.deleted_at ISNULL @@ -261,6 +288,7 @@ def get_series_for_alert(project_id, user_id): INNER JOIN metrics USING (metric_id) WHERE metrics.deleted_at ISNULL AND metrics.project_id = %(project_id)s + AND metrics.metric_type = 'timeseries' AND (user_id = %(user_id)s OR is_public) ORDER BY name;""", {"project_id": project_id, "user_id": user_id} diff --git a/api/chalicelib/core/projects.py b/api/chalicelib/core/projects.py index 2536ee956..c5ae912aa 100644 --- a/api/chalicelib/core/projects.py +++ b/api/chalicelib/core/projects.py @@ -69,20 +69,25 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st ) rows = cur.fetchall() if recording_state: + project_ids = [f'({r["project_id"]})' for r in rows] + query = f"""SELECT projects.project_id, COALESCE(MAX(start_ts), 0) AS last + FROM (VALUES {",".join(project_ids)}) AS projects(project_id) + LEFT JOIN sessions USING (project_id) + GROUP BY project_id;""" + cur.execute( + query=query + ) + status = cur.fetchall() for r in rows: - query = cur.mogrify( - "select COALESCE(MAX(start_ts),0) AS last from public.sessions where project_id=%(project_id)s;", - {"project_id": r["project_id"]}) - cur.execute( - query=query - ) - status = cur.fetchone() - if status["last"] < TimeUTC.now(-2): - r["status"] = "red" - elif status["last"] < TimeUTC.now(-1): - r["status"] = "yellow" - else: - r["status"] = "green" + for s in status: + if s["project_id"] == r["project_id"]: + if s["last"] < TimeUTC.now(-2): + r["status"] = "red" + elif s["last"] < TimeUTC.now(-1): + r["status"] = "yellow" + else: + r["status"] = "green" + break return helper.list_to_camel_case(rows) diff --git a/api/chalicelib/core/sessions.py b/api/chalicelib/core/sessions.py index d180cccc7..bb5e9b974 100644 --- a/api/chalicelib/core/sessions.py +++ b/api/chalicelib/core/sessions.py @@ -1,3 +1,5 @@ +from typing import List + import schemas from chalicelib.core import events, metadata, events_ios, \ sessions_mobs, issues, projects, errors, resources, assist, performance_event @@ -198,7 +200,7 @@ def search2_pg(data: schemas.SessionsSearchPayloadSchema, project_id, user_id, f ROW_NUMBER() OVER (ORDER BY count(full_sessions) DESC) AS rn FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY start_ts DESC) AS rn FROM (SELECT DISTINCT ON(s.session_id) {SESSION_PROJECTION_COLS} - {"," if len(meta_keys)>0 else ""}{",".join([f'metadata_{m["index"]}' for m in meta_keys])} + {"," if len(meta_keys) > 0 else ""}{",".join([f'metadata_{m["index"]}' for m in meta_keys])} {query_part} ORDER BY s.session_id desc) AS filtred_sessions ORDER BY favorite DESC, issue_score DESC, {sort} {data.order}) AS full_sessions @@ -210,7 +212,7 @@ def search2_pg(data: schemas.SessionsSearchPayloadSchema, project_id, user_id, f main_query = cur.mogrify(f"""SELECT COUNT(full_sessions) AS count, COALESCE(JSONB_AGG(full_sessions) FILTER (WHERE rn <= 200), '[]'::JSONB) AS sessions FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY favorite DESC, issue_score DESC, session_id desc, start_ts desc) AS rn FROM (SELECT DISTINCT ON(s.session_id) {SESSION_PROJECTION_COLS} - {"," if len(meta_keys)>0 else ""}{",".join([f'metadata_{m["index"]}' for m in meta_keys])} + {"," if len(meta_keys) > 0 else ""}{",".join([f'metadata_{m["index"]}' for m in meta_keys])} {query_part} ORDER BY s.session_id desc) AS filtred_sessions ORDER BY favorite DESC, issue_score DESC, {sort} {data.order}) AS full_sessions;""", @@ -225,9 +227,9 @@ def search2_pg(data: schemas.SessionsSearchPayloadSchema, project_id, user_id, f # print("--------------------") # print(main_query) - - cur.execute(main_query) # print("--------------------") + cur.execute(main_query) + if count_only: return helper.dict_to_camel_case(cur.fetchone()) sessions = cur.fetchone() @@ -264,44 +266,103 @@ def search2_pg(data: schemas.SessionsSearchPayloadSchema, project_id, user_id, f } -@dev.timed def search2_series(data: schemas.SessionsSearchPayloadSchema, project_id: int, density: int, - view_type: schemas.MetricViewType): + view_type: schemas.MetricTimeseriesViewType, metric_type: schemas.MetricType, + metric_of: schemas.TableMetricOfType, metric_value: List): step_size = int(metrics_helper.__get_step_size(endTimestamp=data.endDate, startTimestamp=data.startDate, density=density, factor=1, decimal=True)) + extra_event = None + if metric_of == schemas.TableMetricOfType.visited_url: + extra_event = "events.pages" + elif metric_of == schemas.TableMetricOfType.issues and len(metric_value) > 0: + data.filters.append(schemas.SessionSearchFilterSchema(value=metric_value, type=schemas.FilterType.issue, + operator=schemas.SearchEventOperator._is)) full_args, query_part, sort = search_query_parts(data=data, error_status=None, errors_only=False, favorite_only=False, issue=None, project_id=project_id, - user_id=None) + user_id=None, extra_event=extra_event) full_args["step_size"] = step_size + sessions = [] with pg_client.PostgresClient() as cur: - if view_type == schemas.MetricViewType.line_chart: - main_query = cur.mogrify(f"""WITH full_sessions AS (SELECT DISTINCT ON(s.session_id) s.session_id, s.start_ts - {query_part}) - SELECT generated_timestamp AS timestamp, - COUNT(s) AS count - FROM generate_series(%(startDate)s, %(endDate)s, %(step_size)s) AS generated_timestamp - LEFT JOIN LATERAL ( SELECT 1 AS s - FROM full_sessions - WHERE start_ts >= generated_timestamp - AND start_ts <= generated_timestamp + %(step_size)s) AS sessions ON (TRUE) - GROUP BY generated_timestamp - ORDER BY generated_timestamp;""", full_args) - else: - main_query = cur.mogrify(f"""SELECT count(DISTINCT s.session_id) AS count - {query_part};""", full_args) + if metric_type == schemas.MetricType.timeseries: + if view_type == schemas.MetricTimeseriesViewType.line_chart: + main_query = cur.mogrify(f"""WITH full_sessions AS (SELECT DISTINCT ON(s.session_id) s.session_id, s.start_ts + {query_part}) + SELECT generated_timestamp AS timestamp, + COUNT(s) AS count + FROM generate_series(%(startDate)s, %(endDate)s, %(step_size)s) AS generated_timestamp + LEFT JOIN LATERAL ( SELECT 1 AS s + FROM full_sessions + WHERE start_ts >= generated_timestamp + AND start_ts <= generated_timestamp + %(step_size)s) AS sessions ON (TRUE) + GROUP BY generated_timestamp + ORDER BY generated_timestamp;""", full_args) + else: + main_query = cur.mogrify(f"""SELECT count(DISTINCT s.session_id) AS count + {query_part};""", full_args) + + # print("--------------------") + # print(main_query) + # print("--------------------") + cur.execute(main_query) + if view_type == schemas.MetricTimeseriesViewType.line_chart: + sessions = cur.fetchall() + else: + sessions = cur.fetchone()["count"] + elif metric_type == schemas.MetricType.table: + if isinstance(metric_of, schemas.TableMetricOfType): + main_col = "user_id" + extra_col = "" + extra_where = "" + pre_query = "" + if metric_of == schemas.TableMetricOfType.user_country: + main_col = "user_country" + elif metric_of == schemas.TableMetricOfType.user_device: + main_col = "user_device" + elif metric_of == schemas.TableMetricOfType.user_browser: + main_col = "user_browser" + elif metric_of == schemas.TableMetricOfType.issues: + main_col = "issue" + extra_col = f", UNNEST(s.issue_types) AS {main_col}" + if len(metric_value) > 0: + extra_where = [] + for i in range(len(metric_value)): + arg_name = f"selected_issue_{i}" + extra_where.append(f"{main_col} = %({arg_name})s") + full_args[arg_name] = metric_value[i] + extra_where = f"WHERE ({' OR '.join(extra_where)})" + elif metric_of == schemas.TableMetricOfType.visited_url: + main_col = "base_path" + extra_col = ", base_path" + main_query = cur.mogrify(f"""{pre_query} + SELECT COUNT(*) AS count, COALESCE(JSONB_AGG(users_sessions) FILTER ( WHERE rn <= 200 ), '[]'::JSONB) AS values + FROM (SELECT {main_col} AS name, + count(full_sessions) AS session_count, + ROW_NUMBER() OVER (ORDER BY count(full_sessions) DESC) AS rn + FROM (SELECT * + FROM (SELECT DISTINCT ON(s.session_id) s.session_id, s.user_uuid, + s.user_id, s.user_os, + s.user_browser, s.user_device, + s.user_device_type, s.user_country, s.issue_types{extra_col} + {query_part} + ORDER BY s.session_id desc) AS filtred_sessions + ) AS full_sessions + {extra_where} + GROUP BY {main_col} + ORDER BY session_count DESC) AS users_sessions;""", + full_args) + # print("--------------------") + # print(main_query) + # print("--------------------") + cur.execute(main_query) + sessions = cur.fetchone() + for s in sessions["values"]: + s.pop("rn") + sessions["values"] = helper.list_to_camel_case(sessions["values"]) - # print("--------------------") - # print(main_query) - cur.execute(main_query) - # print("--------------------") - if view_type == schemas.MetricViewType.line_chart: - sessions = cur.fetchall() - else: - sessions = cur.fetchone()["count"] return sessions -def search_query_parts(data, error_status, errors_only, favorite_only, issue, project_id, user_id): +def search_query_parts(data, error_status, errors_only, favorite_only, issue, project_id, user_id, extra_event=None): ss_constraints = [] full_args = {"project_id": project_id, "startDate": data.startDate, "endDate": data.endDate, "projectId": project_id, "userId": user_id} @@ -521,7 +582,6 @@ def search_query_parts(data, error_status, errors_only, favorite_only, issue, pr value_key=f_k)) # --------------------------------------------------------------------------- if len(data.events) > 0: - # ss_constraints = [s.decode('UTF-8') for s in ss_constraints] events_query_from = [] event_index = 0 or_events = data.events_order == schemas.SearchEventOrder._or @@ -532,13 +592,16 @@ def search_query_parts(data, error_status, errors_only, favorite_only, issue, pr is_any = _isAny_opreator(event.operator) if not isinstance(event.value, list): event.value = [event.value] - if not is_any and len(event.value) == 0 \ + if not is_any and len(event.value) == 0 and event_type not in [schemas.EventType.request_details, + schemas.EventType.graphql_details] \ or event_type in [schemas.PerformanceEventType.location_dom_complete, schemas.PerformanceEventType.location_largest_contentful_paint_time, schemas.PerformanceEventType.location_ttfb, schemas.PerformanceEventType.location_avg_cpu_load, schemas.PerformanceEventType.location_avg_memory_usage - ] and (event.source is None or len(event.source) == 0): + ] and (event.source is None or len(event.source) == 0) \ + or event_type in [schemas.EventType.request_details, schemas.EventType.graphql_details] and ( + event.filters is None or len(event.filters) == 0): continue op = __get_sql_operator(event.operator) is_not = False @@ -737,15 +800,19 @@ def search_query_parts(data, error_status, errors_only, favorite_only, issue, pr event_where += ["main2.timestamp >= %(startDate)s", "main2.timestamp <= %(endDate)s"] if event_index > 0 and not or_events: event_where.append("main2.session_id=event_0.session_id") - event_where.append( - _multiple_conditions( - f"main.{getattr(events.event_type, event.value[0].type).column} {s_op} %({e_k1})s", - event.value[0].value, value_key=e_k1)) + is_any = _isAny_opreator(event.value[0].operator) + if not is_any: + event_where.append( + _multiple_conditions( + f"main.{getattr(events.event_type, event.value[0].type).column} {s_op} %({e_k1})s", + event.value[0].value, value_key=e_k1)) s_op = __get_sql_operator(event.value[1].operator) - event_where.append( - _multiple_conditions( - f"main2.{getattr(events.event_type, event.value[1].type).column} {s_op} %({e_k2})s", - event.value[1].value, value_key=e_k2)) + is_any = _isAny_opreator(event.value[1].operator) + if not is_any: + event_where.append( + _multiple_conditions( + f"main2.{getattr(events.event_type, event.value[1].type).column} {s_op} %({e_k2})s", + event.value[1].value, value_key=e_k2)) e_k += "_custom" full_args = {**full_args, **_multiple_values(event.source, value_key=e_k)} @@ -753,7 +820,66 @@ def search_query_parts(data, error_status, errors_only, favorite_only, issue, pr _multiple_conditions(f"main2.timestamp - main.timestamp {event.sourceOperator} %({e_k})s", event.source, value_key=e_k)) - + elif event_type == schemas.EventType.request_details: + event_from = event_from % f"{events.event_type.REQUEST.table} AS main " + for j, f in enumerate(event.filters): + is_any = _isAny_opreator(f.operator) + if is_any or len(f.value) == 0: + continue + op = __get_sql_operator(f.operator) + e_k_f = e_k + f"_fetch{j}" + full_args = {**full_args, **_multiple_values(f.value, value_key=e_k_f)} + if f.type == schemas.FetchFilterType._url: + event_where.append( + _multiple_conditions(f"main.{events.event_type.REQUEST.column} {op} %({e_k_f})s", f.value, + value_key=e_k_f)) + elif f.type == schemas.FetchFilterType._status_code: + event_where.append( + _multiple_conditions(f"main.status_code {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.FetchFilterType._method: + event_where.append( + _multiple_conditions(f"main.method {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.FetchFilterType._duration: + event_where.append( + _multiple_conditions(f"main.duration {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.FetchFilterType._request_body: + event_where.append( + _multiple_conditions(f"main.request_body {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.FetchFilterType._response_body: + event_where.append( + _multiple_conditions(f"main.response_body {op} %({e_k_f})s", f.value, value_key=e_k_f)) + else: + print(f"undefined FETCH filter: {f.type}") + elif event_type == schemas.EventType.graphql_details: + event_from = event_from % f"{events.event_type.GRAPHQL.table} AS main " + for j, f in enumerate(event.filters): + is_any = _isAny_opreator(f.operator) + if is_any or len(f.value) == 0: + continue + op = __get_sql_operator(f.operator) + e_k_f = e_k + f"_graphql{j}" + full_args = {**full_args, **_multiple_values(f.value, value_key=e_k_f)} + if f.type == schemas.GraphqlFilterType._name: + event_where.append( + _multiple_conditions(f"main.{events.event_type.GRAPHQL.column} {op} %({e_k_f})s", f.value, + value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._status_code: + event_where.append( + _multiple_conditions(f"main.status_code {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._method: + event_where.append( + _multiple_conditions(f"main.method {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._duration: + event_where.append( + _multiple_conditions(f"main.duration {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._request_body: + event_where.append( + _multiple_conditions(f"main.request_body {op} %({e_k_f})s", f.value, value_key=e_k_f)) + elif f.type == schemas.GraphqlFilterType._response_body: + event_where.append( + _multiple_conditions(f"main.response_body {op} %({e_k_f})s", f.value, value_key=e_k_f)) + else: + print(f"undefined GRAPHQL filter: {f.type}") else: continue if event_index == 0 or or_events: @@ -856,6 +982,10 @@ def search_query_parts(data, error_status, errors_only, favorite_only, issue, pr """ full_args["issue_contextString"] = issue["contextString"] full_args["issue_type"] = issue["type"] + if extra_event: + extra_join += f"""INNER JOIN {extra_event} AS ev USING(session_id)""" + extra_constraints.append("ev.timestamp>=%(startDate)s") + extra_constraints.append("ev.timestamp<=%(endDate)s") query_part = f"""\ FROM {f"({events_query_part}) AS f" if len(events_query_part) > 0 else "public.sessions AS s"} {extra_join} diff --git a/api/chalicelib/core/signup.py b/api/chalicelib/core/signup.py index b4f02f0b8..ab23eef68 100644 --- a/api/chalicelib/core/signup.py +++ b/api/chalicelib/core/signup.py @@ -63,13 +63,12 @@ def create_step1(data: schemas.UserSignupSchema): "fullname": fullname, "projectName": project_name, "data": json.dumps({"lastAnnouncementView": TimeUTC.now()}), - "organizationName": company_name, - "versionNumber": config("version_number") + "organizationName": company_name } query = f"""\ WITH t AS ( INSERT INTO public.tenants (name, version_number, edition) - VALUES (%(organizationName)s, %(versionNumber)s, 'fos') + VALUES (%(organizationName)s, (SELECT openreplay_version()), 'fos') RETURNING api_key ), u AS ( diff --git a/api/routers/core.py b/api/routers/core.py index 59bede0ae..d01b8ee94 100644 --- a/api/routers/core.py +++ b/api/routers/core.py @@ -101,12 +101,15 @@ def comment_assignment(projectId: int, sessionId: int, issueId: str, data: schem @app.get('/{projectId}/events/search', tags=["events"]) def events_search(projectId: int, q: str, - type: Union[schemas.FilterType, schemas.EventType, schemas.PerformanceEventType] = None, + type: Union[schemas.FilterType, schemas.EventType, + schemas.PerformanceEventType, schemas.FetchFilterType] = None, key: str = None, source: str = None, context: schemas.CurrentContext = Depends(OR_context)): if len(q) == 0: return {"data": []} - if isinstance(type, schemas.PerformanceEventType): + if type in [schemas.FetchFilterType._url]: + type = schemas.EventType.request + elif isinstance(type, schemas.PerformanceEventType): if type in [schemas.PerformanceEventType.location_dom_complete, schemas.PerformanceEventType.location_largest_contentful_paint_time, schemas.PerformanceEventType.location_ttfb, @@ -1088,25 +1091,9 @@ def change_client_password(data: schemas.EditUserPasswordSchema = Body(...), @app.post('/{projectId}/custom_metrics/try', tags=["customMetrics"]) @app.put('/{projectId}/custom_metrics/try', tags=["customMetrics"]) -def try_custom_metric(projectId: int, data: schemas.TryCustomMetricsSchema = Body(...), +def try_custom_metric(projectId: int, data: schemas.CreateCustomMetricsSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): - return {"data": custom_metrics.merged_live - (project_id=projectId, data=data)} - - -@app.post('/{projectId}/custom_metrics/sessions', tags=["customMetrics"]) -def get_custom_metric_sessions(projectId: int, data: schemas.CustomMetricRawPayloadSchema2 = Body(...), - context: schemas.CurrentContext = Depends(OR_context)): - return {"data": custom_metrics.get_sessions(project_id=projectId, user_id=context.user_id, metric_id=data.metric_id, - data=data)} - - -@app.post('/{projectId}/custom_metrics/chart', tags=["customMetrics"]) -@app.put('/{projectId}/custom_metrics/chart', tags=["customMetrics"]) -def get_custom_metric_chart(projectId: int, data: schemas.CustomMetricChartPayloadSchema2 = Body(...), - context: schemas.CurrentContext = Depends(OR_context)): - return {"data": custom_metrics.make_chart(project_id=projectId, user_id=context.user_id, metric_id=data.metric_id, - data=data)} + return {"data": custom_metrics.merged_live(project_id=projectId, data=data)} @app.post('/{projectId}/custom_metrics', tags=["customMetrics"]) @@ -1123,29 +1110,40 @@ def get_custom_metrics(projectId: int, context: schemas.CurrentContext = Depends @app.get('/{projectId}/custom_metrics/{metric_id}', tags=["customMetrics"]) def get_custom_metric(projectId: int, metric_id: int, context: schemas.CurrentContext = Depends(OR_context)): - return {"data": custom_metrics.get(project_id=projectId, user_id=context.user_id, metric_id=metric_id)} + data = custom_metrics.get(project_id=projectId, user_id=context.user_id, metric_id=metric_id) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} @app.post('/{projectId}/custom_metrics/{metric_id}/sessions', tags=["customMetrics"]) -def get_custom_metric_sessions(projectId: int, metric_id: int, data: schemas.CustomMetricRawPayloadSchema = Body(...), +def get_custom_metric_sessions(projectId: int, metric_id: int, + data: schemas.CustomMetricSessionsPayloadSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): - return {"data": custom_metrics.get_sessions(project_id=projectId, user_id=context.user_id, metric_id=metric_id, - data=data)} + data = custom_metrics.get_sessions(project_id=projectId, user_id=context.user_id, metric_id=metric_id, data=data) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} @app.post('/{projectId}/custom_metrics/{metric_id}/chart', tags=["customMetrics"]) def get_custom_metric_chart(projectId: int, metric_id: int, data: schemas.CustomMetricChartPayloadSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): - return {"data": custom_metrics.make_chart(project_id=projectId, user_id=context.user_id, metric_id=metric_id, - data=data)} + data = custom_metrics.make_chart(project_id=projectId, user_id=context.user_id, metric_id=metric_id, + data=data) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} @app.post('/{projectId}/custom_metrics/{metric_id}', tags=["customMetrics"]) @app.put('/{projectId}/custom_metrics/{metric_id}', tags=["customMetrics"]) def update_custom_metric(projectId: int, metric_id: int, data: schemas.UpdateCustomMetricsSchema = Body(...), context: schemas.CurrentContext = Depends(OR_context)): - return { - "data": custom_metrics.update(project_id=projectId, user_id=context.user_id, metric_id=metric_id, data=data)} + data = custom_metrics.update(project_id=projectId, user_id=context.user_id, metric_id=metric_id, data=data) + if data is None: + return {"errors": ["custom metric not found"]} + return {"data": data} @app.post('/{projectId}/custom_metrics/{metric_id}/status', tags=["customMetrics"]) diff --git a/api/schemas.py b/api/schemas.py index 400dd94cc..062900fc2 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -384,7 +384,9 @@ class EventType(str, Enum): location = "LOCATION" custom = "CUSTOM" request = "REQUEST" + request_details = "FETCH" graphql = "GRAPHQL" + graphql_details = "GRAPHQL_DETAILS" state_action = "STATEACTION" error = "ERROR" click_ios = "CLICK_IOS" @@ -480,7 +482,8 @@ class __MixedSearchFilter(BaseModel): @root_validator(pre=True) def remove_duplicate_values(cls, values): if values.get("value") is not None: - if len(values["value"]) > 0 and isinstance(values["value"][0], int): + if len(values["value"]) > 0 \ + and (isinstance(values["value"][0], int) or isinstance(values["value"][0], dict)): return values values["value"] = list(set(values["value"])) return values @@ -489,6 +492,42 @@ class __MixedSearchFilter(BaseModel): alias_generator = attribute_to_camel_case +class HttpMethod(str, Enum): + _get = 'GET' + _head = 'HEAD' + _post = 'POST' + _put = 'PUT' + _delete = 'DELETE' + _connect = 'CONNECT' + _option = 'OPTIONS' + _trace = 'TRACE' + _patch = 'PATCH' + + +class FetchFilterType(str, Enum): + _url = "FETCH_URL" + _status_code = "FETCH_STATUS_CODE" + _method = "FETCH_METHOD" + _duration = "FETCH_DURATION" + _request_body = "FETCH_REQUEST_BODY" + _response_body = "FETCH_RESPONSE_BODY" + + +class GraphqlFilterType(str, Enum): + _name = "GRAPHQL_NAME" + _status_code = "GRAPHQL_STATUS_CODE" + _method = "GRAPHQL_METHOD" + _duration = "GRAPHQL_DURATION" + _request_body = "GRAPHQL_REQUEST_BODY" + _response_body = "GRAPHQL_RESPONSE_BODY" + + +class RequestGraphqlFilterSchema(BaseModel): + type: Union[FetchFilterType, GraphqlFilterType] = Field(...) + value: List[Union[int, str]] = Field(...) + operator: Union[SearchEventOperator, MathOperator] = Field(...) + + class _SessionSearchEventRaw(__MixedSearchFilter): is_event: bool = Field(default=True, const=True) value: List[str] = Field(...) @@ -496,6 +535,7 @@ class _SessionSearchEventRaw(__MixedSearchFilter): operator: SearchEventOperator = Field(...) source: Optional[List[Union[ErrorSource, int, str]]] = Field(None) sourceOperator: Optional[MathOperator] = Field(None) + filters: Optional[List[RequestGraphqlFilterSchema]] = Field(None) @root_validator def event_validator(cls, values): @@ -513,20 +553,28 @@ class _SessionSearchEventRaw(__MixedSearchFilter): assert isinstance(values["value"][0], _SessionSearchEventRaw) \ and isinstance(values["value"][1], _SessionSearchEventRaw), \ f"event should be of type _SessionSearchEventRaw for {PerformanceEventType.time_between_events}" + assert len(values["source"]) > 0 and isinstance(values["source"][0], int), \ + f"source of type int if required for {PerformanceEventType.time_between_events}" else: for c in values["source"]: assert isinstance(c, int), f"source value should be of type int for {values.get('type')}" elif values.get("type") == EventType.error and values.get("source") is None: values["source"] = [ErrorSource.js_exception] + elif values.get("type") == EventType.request_details: + assert isinstance(values.get("filters"), List) and len(values.get("filters", [])) > 0, \ + f"filters should be defined for {EventType.request_details.value}" + elif values.get("type") == EventType.graphql_details: + assert isinstance(values.get("filters"), List) and len(values.get("filters", [])) > 0, \ + f"filters should be defined for {EventType.graphql_details.value}" return values class _SessionSearchEventSchema(_SessionSearchEventRaw): - value: Union[List[_SessionSearchEventRaw], str, List[str]] = Field(...) + value: Union[List[Union[_SessionSearchEventRaw, str]], str] = Field(...) -class _SessionSearchFilterSchema(__MixedSearchFilter): +class SessionSearchFilterSchema(__MixedSearchFilter): is_event: bool = Field(False, const=False) value: Union[Optional[Union[IssueType, PlatformType, int, str]], Optional[List[Union[IssueType, PlatformType, int, str]]]] = Field(...) @@ -559,7 +607,7 @@ class _SessionSearchFilterSchema(__MixedSearchFilter): class SessionsSearchPayloadSchema(BaseModel): events: List[_SessionSearchEventSchema] = Field([]) - filters: List[_SessionSearchFilterSchema] = Field([]) + filters: List[SessionSearchFilterSchema] = Field([]) startDate: int = Field(None) endDate: int = Field(None) sort: str = Field(default="startTs") @@ -571,9 +619,9 @@ class SessionsSearchPayloadSchema(BaseModel): alias_generator = attribute_to_camel_case -class FlatSessionsSearchPayloadSchema(SessionsSearchPayloadSchema): +class FlatSessionsSearch(BaseModel): events: Optional[List[_SessionSearchEventSchema]] = Field([]) - filters: List[Union[_SessionSearchFilterSchema, _SessionSearchEventSchema]] = Field([]) + filters: List[Union[SessionSearchFilterSchema, _SessionSearchEventSchema]] = Field([]) @root_validator(pre=True) def flat_to_original(cls, values): @@ -597,6 +645,10 @@ class FlatSessionsSearchPayloadSchema(SessionsSearchPayloadSchema): return values +class FlatSessionsSearchPayloadSchema(FlatSessionsSearch, SessionsSearchPayloadSchema): + pass + + class SessionsSearchCountSchema(FlatSessionsSearchPayloadSchema): # class SessionsSearchCountSchema(SessionsSearchPayloadSchema): sort: Optional[str] = Field(default=None) @@ -688,21 +740,36 @@ class CustomMetricCreateSeriesSchema(BaseModel): alias_generator = attribute_to_camel_case -class CreateCustomMetricsSchema(BaseModel): - name: str = Field(...) - series: List[CustomMetricCreateSeriesSchema] = Field(..., min_items=1) - is_public: Optional[bool] = Field(True) - - class Config: - alias_generator = attribute_to_camel_case - - -class MetricViewType(str, Enum): +class MetricTimeseriesViewType(str, Enum): line_chart = "lineChart" progress = "progress" -class CustomMetricRawPayloadSchema(BaseModel): +class MetricTableViewType(str, Enum): + table = "table" + pie_chart = "pieChart" + + +class MetricType(str, Enum): + timeseries = "timeseries" + table = "table" + + +class TableMetricOfType(str, Enum): + user_os = FilterType.user_os.value + user_browser = FilterType.user_browser.value + user_device = FilterType.user_device.value + user_country = FilterType.user_country.value + user_id = FilterType.user_id.value + issues = FilterType.issue.value + visited_url = EventType.location.value + + +class TimeseriesMetricOfType(str, Enum): + session_count = "sessionCount" + + +class CustomMetricSessionsPayloadSchema(FlatSessionsSearch): startDate: int = Field(TimeUTC.now(-7)) endDate: int = Field(TimeUTC.now()) @@ -710,23 +777,52 @@ class CustomMetricRawPayloadSchema(BaseModel): alias_generator = attribute_to_camel_case -class CustomMetricRawPayloadSchema2(CustomMetricRawPayloadSchema): - metric_id: int = Field(...) - - -class CustomMetricChartPayloadSchema(CustomMetricRawPayloadSchema): - startDate: int = Field(TimeUTC.now(-7)) - endDate: int = Field(TimeUTC.now()) +class CustomMetricChartPayloadSchema(CustomMetricSessionsPayloadSchema): density: int = Field(7) - viewType: MetricViewType = Field(MetricViewType.line_chart) + + class Config: + alias_generator = attribute_to_camel_case -class CustomMetricChartPayloadSchema2(CustomMetricChartPayloadSchema): - metric_id: int = Field(...) +class CreateCustomMetricsSchema(CustomMetricChartPayloadSchema): + name: str = Field(...) + series: List[CustomMetricCreateSeriesSchema] = Field(..., min_items=1) + is_public: bool = Field(default=True, const=True) + view_type: Union[MetricTimeseriesViewType, MetricTableViewType] = Field(MetricTimeseriesViewType.line_chart) + metric_type: MetricType = Field(MetricType.timeseries) + metric_of: Union[TableMetricOfType, TimeseriesMetricOfType] = Field(TableMetricOfType.user_id) + metric_value: List[IssueType] = Field([]) + metric_format: Optional[str] = Field(None) + # metricFraction: float = Field(None, gt=0, lt=1) + # This is used to handle wrong values sent by the UI + @root_validator(pre=True) + def remove_metric_value(cls, values): + if values.get("metricType") == MetricType.timeseries \ + or values.get("metricType") == MetricType.table \ + and values.get("metricOf") != TableMetricOfType.issues: + values["metricValue"] = [] + return values -class TryCustomMetricsSchema(CreateCustomMetricsSchema, CustomMetricChartPayloadSchema): - name: Optional[str] = Field(None) + @root_validator + def validator(cls, values): + if values.get("metric_type") == MetricType.table: + assert isinstance(values.get("view_type"), MetricTableViewType), \ + f"viewType must be of type {MetricTableViewType} for metricType:{MetricType.table.value}" + assert isinstance(values.get("metric_of"), TableMetricOfType), \ + f"metricOf must be of type {TableMetricOfType} for metricType:{MetricType.table.value}" + if values.get("metric_of") != TableMetricOfType.issues: + assert values.get("metric_value") is None or len(values.get("metric_value")) == 0, \ + f"metricValue is only available for metricOf:{TableMetricOfType.issues.value}" + elif values.get("metric_type") == MetricType.timeseries: + assert isinstance(values.get("view_type"), MetricTimeseriesViewType), \ + f"viewType must be of type {MetricTimeseriesViewType} for metricType:{MetricType.timeseries.value}" + assert isinstance(values.get("metric_of"), TimeseriesMetricOfType), \ + f"metricOf must be of type {TimeseriesMetricOfType} for metricType:{MetricType.timeseries.value}" + return values + + class Config: + alias_generator = attribute_to_camel_case class CustomMetricUpdateSeriesSchema(CustomMetricCreateSeriesSchema): diff --git a/backend/pkg/db/cache/messages_ios.go b/backend/pkg/db/cache/messages_ios.go index 0cced5472..4bbc8c1f5 100644 --- a/backend/pkg/db/cache/messages_ios.go +++ b/backend/pkg/db/cache/messages_ios.go @@ -1,41 +1,40 @@ package cache -import ( +import ( "errors" - . "openreplay/backend/pkg/messages" . "openreplay/backend/pkg/db/types" + . "openreplay/backend/pkg/messages" ) func (c *PGCache) InsertIOSSessionStart(sessionID uint64, s *IOSSessionStart) error { - if c.sessions[ sessionID ] != nil { + if c.sessions[sessionID] != nil { return errors.New("This session already in cache!") } - c.sessions[ sessionID ] = &Session{ - SessionID: sessionID, - Platform: "ios", - Timestamp: s.Timestamp, - ProjectID: uint32(s.ProjectID), + c.sessions[sessionID] = &Session{ + SessionID: sessionID, + Platform: "ios", + Timestamp: s.Timestamp, + ProjectID: uint32(s.ProjectID), TrackerVersion: s.TrackerVersion, - RevID: s.RevID, - UserUUID: s.UserUUID, - UserOS: s.UserOS, - UserOSVersion: s.UserOSVersion, - UserDevice: s.UserDevice, - UserCountry: s.UserCountry, + RevID: s.RevID, + UserUUID: s.UserUUID, + UserOS: s.UserOS, + UserOSVersion: s.UserOSVersion, + UserDevice: s.UserDevice, + UserCountry: s.UserCountry, UserDeviceType: s.UserDeviceType, } - if err := c.Conn.InsertSessionStart(sessionID, c.sessions[ sessionID ]); err != nil { - c.sessions[ sessionID ] = nil + if err := c.Conn.InsertSessionStart(sessionID, c.sessions[sessionID]); err != nil { + c.sessions[sessionID] = nil return err } - return nil; + return nil } func (c *PGCache) InsertIOSSessionEnd(sessionID uint64, e *IOSSessionEnd) error { return c.insertSessionEnd(sessionID, e.Timestamp) } - func (c *PGCache) InsertIOSScreenEnter(sessionID uint64, screenEnter *IOSScreenEnter) error { if err := c.Conn.InsertIOSScreenEnter(sessionID, screenEnter); err != nil { return err @@ -95,4 +94,3 @@ func (c *PGCache) InsertIOSIssueEvent(sessionID uint64, issueEvent *IOSIssueEven // } return nil } - diff --git a/backend/pkg/db/cache/messages_web.go b/backend/pkg/db/cache/messages_web.go index 4aa4dfa7b..71f2c38d0 100644 --- a/backend/pkg/db/cache/messages_web.go +++ b/backend/pkg/db/cache/messages_web.go @@ -53,3 +53,27 @@ func (c *PGCache) InsertWebErrorEvent(sessionID uint64, e *ErrorEvent) error { session.ErrorsCount += 1 return nil } + +func (c *PGCache) InsertWebFetchEvent(sessionID uint64, e *FetchEvent) error { + session, err := c.GetSession(sessionID) + if err != nil { + return err + } + project, err := c.GetProject(session.ProjectID) + if err != nil { + return err + } + return c.Conn.InsertWebFetchEvent(sessionID, project.SaveRequestPayloads, e) +} + +func (c *PGCache) InsertWebGraphQLEvent(sessionID uint64, e *GraphQLEvent) error { + session, err := c.GetSession(sessionID) + if err != nil { + return err + } + project, err := c.GetProject(session.ProjectID) + if err != nil { + return err + } + return c.Conn.InsertWebGraphQLEvent(sessionID, project.SaveRequestPayloads, e) +} diff --git a/backend/pkg/db/cache/pg_cache.go b/backend/pkg/db/cache/pg_cache.go index 9a62354f1..6422209d4 100644 --- a/backend/pkg/db/cache/pg_cache.go +++ b/backend/pkg/db/cache/pg_cache.go @@ -1,8 +1,8 @@ package cache -import ( - "time" +import ( "sync" + "time" "openreplay/backend/pkg/db/postgres" . "openreplay/backend/pkg/db/types" @@ -10,32 +10,29 @@ import ( type ProjectMeta struct { *Project - expirationTime time.Time + expirationTime time.Time } // !TODO: remove old sessions by timeout to avoid memleaks -/* +/* * Cache layer around the stateless PG adapter **/ type PGCache struct { *postgres.Conn - sessions map[uint64]*Session - projects map[uint32]*ProjectMeta - projectsByKeys sync.Map // map[string]*ProjectMeta + sessions map[uint64]*Session + projects map[uint32]*ProjectMeta + projectsByKeys sync.Map // map[string]*ProjectMeta projectExpirationTimeout time.Duration } // TODO: create conn automatically func NewPGCache(pgConn *postgres.Conn, projectExpirationTimeoutMs int64) *PGCache { return &PGCache{ - Conn: pgConn, + Conn: pgConn, sessions: make(map[uint64]*Session), projects: make(map[uint32]*ProjectMeta), //projectsByKeys: make(map[string]*ProjectMeta), projectExpirationTimeout: time.Duration(1000 * projectExpirationTimeoutMs), } } - - - diff --git a/backend/pkg/db/cache/project.go b/backend/pkg/db/cache/project.go index daf498d32..35d952302 100644 --- a/backend/pkg/db/cache/project.go +++ b/backend/pkg/db/cache/project.go @@ -1,8 +1,8 @@ package cache -import ( - "time" +import ( . "openreplay/backend/pkg/db/types" + "time" ) func (c *PGCache) GetProjectByKey(projectKey string) (*Project, error) { @@ -24,19 +24,16 @@ func (c *PGCache) GetProjectByKey(projectKey string) (*Project, error) { return p, nil } - - func (c *PGCache) GetProject(projectID uint32) (*Project, error) { - if c.projects[ projectID ] != nil && - time.Now().Before(c.projects[ projectID ].expirationTime) { - return c.projects[ projectID ].Project, nil + if c.projects[projectID] != nil && + time.Now().Before(c.projects[projectID].expirationTime) { + return c.projects[projectID].Project, nil } p, err := c.Conn.GetProject(projectID) if err != nil { return nil, err } - c.projects[ projectID ] = &ProjectMeta{ p, time.Now().Add(c.projectExpirationTimeout) } + c.projects[projectID] = &ProjectMeta{p, time.Now().Add(c.projectExpirationTimeout)} //c.projectsByKeys.Store(p.ProjectKey, c.projects[ projectID ]) return p, nil } - diff --git a/backend/pkg/db/cache/session.go b/backend/pkg/db/cache/session.go index 2038fd1bd..a79462022 100644 --- a/backend/pkg/db/cache/session.go +++ b/backend/pkg/db/cache/session.go @@ -1,13 +1,13 @@ package cache -import ( +import ( "github.com/jackc/pgx/v4" . "openreplay/backend/pkg/db/types" ) func (c *PGCache) GetSession(sessionID uint64) (*Session, error) { - if s, inCache := c.sessions[ sessionID ]; inCache { + if s, inCache := c.sessions[sessionID]; inCache { // TODO: review. Might cause bugs in case of multiple instances if s == nil { return nil, pgx.ErrNoRows @@ -16,12 +16,12 @@ func (c *PGCache) GetSession(sessionID uint64) (*Session, error) { } s, err := c.Conn.GetSession(sessionID) if err == pgx.ErrNoRows { - c.sessions[ sessionID ] = nil + c.sessions[sessionID] = nil } if err != nil { return nil, err } - c.sessions[ sessionID ] = s + c.sessions[sessionID] = s return s, nil } diff --git a/backend/pkg/db/postgres/errors.go b/backend/pkg/db/postgres/errors.go index a83c8f03a..de105f7ce 100644 --- a/backend/pkg/db/postgres/errors.go +++ b/backend/pkg/db/postgres/errors.go @@ -3,14 +3,14 @@ package postgres import ( "errors" - "github.com/jackc/pgx/v4" "github.com/jackc/pgconn" "github.com/jackc/pgerrcode" + "github.com/jackc/pgx/v4" ) func IsPkeyViolation(err error) bool { var pgErr *pgconn.PgError - return errors.As(err, &pgErr) && pgErr.Code == pgerrcode.UniqueViolation + return errors.As(err, &pgErr) && pgErr.Code == pgerrcode.UniqueViolation } func IsNoRowsErr(err error) bool { diff --git a/backend/pkg/db/postgres/helpers.go b/backend/pkg/db/postgres/helpers.go index e6e9747e8..2d4c96e28 100644 --- a/backend/pkg/db/postgres/helpers.go +++ b/backend/pkg/db/postgres/helpers.go @@ -8,7 +8,7 @@ func getIssueScore(issueEvent *messages.IssueEvent) int { switch issueEvent.Type { case "crash", "dead_click", "memory", "cpu": return 1000 - case "bad_request", "excessive_scrolling", "click_rage", "missing_resource" : + case "bad_request", "excessive_scrolling", "click_rage", "missing_resource": return 500 case "slow_resource", "slow_page_load": return 100 @@ -32,4 +32,4 @@ func calcResponseTime(pe *messages.PageEvent) uint64 { return pe.ResponseEnd - pe.ResponseStart } return 0 -} \ No newline at end of file +} diff --git a/backend/pkg/db/postgres/listener.go b/backend/pkg/db/postgres/listener.go index 0f6d73ef7..f90d83485 100644 --- a/backend/pkg/db/postgres/listener.go +++ b/backend/pkg/db/postgres/listener.go @@ -6,8 +6,6 @@ import ( "fmt" "github.com/jackc/pgx/v4" - - ) type Listener struct { diff --git a/backend/pkg/db/postgres/messages_ios.go b/backend/pkg/db/postgres/messages_ios.go index b54a88af7..e75ff2acd 100644 --- a/backend/pkg/db/postgres/messages_ios.go +++ b/backend/pkg/db/postgres/messages_ios.go @@ -1,8 +1,8 @@ package postgres import ( - "openreplay/backend/pkg/messages" "openreplay/backend/pkg/hashid" + "openreplay/backend/pkg/messages" "openreplay/backend/pkg/url" ) @@ -33,7 +33,7 @@ func (conn *Conn) InsertIOSUserAnonymousID(sessionID uint64, userAnonymousID *me func (conn *Conn) InsertIOSNetworkCall(sessionID uint64, e *messages.IOSNetworkCall) error { err := conn.InsertRequest(sessionID, e.Timestamp, e.Index, e.URL, e.Duration, e.Success) if err == nil { - conn.insertAutocompleteValue(sessionID, "REQUEST_IOS", url.DiscardURLQuery(e.URL)) + conn.insertAutocompleteValue(sessionID, "REQUEST_IOS", url.DiscardURLQuery(e.URL)) } return err } @@ -65,7 +65,7 @@ func (conn *Conn) InsertIOSScreenEnter(sessionID uint64, screenEnter *messages.I if err = tx.commit(); err != nil { return err } - conn.insertAutocompleteValue(sessionID, "VIEW_IOS", screenEnter.ViewName) + conn.insertAutocompleteValue(sessionID, "VIEW_IOS", screenEnter.ViewName) return nil } @@ -81,7 +81,7 @@ func (conn *Conn) InsertIOSClickEvent(sessionID uint64, clickEvent *messages.IOS session_id, timestamp, seq_index, label ) VALUES ( $1, $2, $3, $4 - )`, + )`, sessionID, clickEvent.Timestamp, clickEvent.Index, clickEvent.Label, ); err != nil { return err @@ -153,7 +153,7 @@ func (conn *Conn) InsertIOSCrash(sessionID uint64, projectID uint32, crash *mess project_id, $2, $3, $4, $5 FROM sessions WHERE session_id = $1 - )ON CONFLICT DO NOTHING`, + )ON CONFLICT DO NOTHING`, sessionID, crashID, crash.Name, crash.Reason, crash.Stacktrace, ); err != nil { return err @@ -163,7 +163,7 @@ func (conn *Conn) InsertIOSCrash(sessionID uint64, projectID uint32, crash *mess session_id, timestamp, seq_index, crash_id ) VALUES ( $1, $2, $3, $4 - )`, + )`, sessionID, crash.Timestamp, crash.Index, crashID, ); err != nil { return err @@ -177,5 +177,3 @@ func (conn *Conn) InsertIOSCrash(sessionID uint64, projectID uint32, crash *mess } return tx.commit() } - - diff --git a/backend/pkg/db/postgres/messages_web.go b/backend/pkg/db/postgres/messages_web.go index 64d7ba561..4ff59cc63 100644 --- a/backend/pkg/db/postgres/messages_web.go +++ b/backend/pkg/db/postgres/messages_web.go @@ -13,9 +13,8 @@ func getSqIdx(messageID uint64) uint { return uint(messageID % math.MaxInt32) } - func (conn *Conn) InsertWebCustomEvent(sessionID uint64, e *CustomEvent) error { - err := conn.InsertCustomEvent(sessionID, e.Timestamp, + err := conn.InsertCustomEvent(sessionID, e.Timestamp, e.MessageID, e.Name, e.Payload) if err == nil { @@ -40,19 +39,19 @@ func (conn *Conn) InsertWebUserAnonymousID(sessionID uint64, userAnonymousID *Us return err } -func (conn *Conn) InsertWebResourceEvent(sessionID uint64, e *ResourceEvent) error { - if e.Type != "fetch" { - return nil - } - err := conn.InsertRequest(sessionID, e.Timestamp, - e.MessageID, - e.URL, e.Duration, e.Success, - ) - if err == nil { - conn.insertAutocompleteValue(sessionID, "REQUEST", url.DiscardURLQuery(e.URL)) - } - return err -} +// func (conn *Conn) InsertWebResourceEvent(sessionID uint64, e *ResourceEvent) error { +// if e.Type != "fetch" { +// return nil +// } +// err := conn.InsertRequest(sessionID, e.Timestamp, +// e.MessageID, +// e.URL, e.Duration, e.Success, +// ) +// if err == nil { +// conn.insertAutocompleteValue(sessionID, "REQUEST", url.DiscardURLQuery(e.URL)) +// } +// return err +// } // TODO: fix column "dom_content_loaded_event_end" of relation "pages" func (conn *Conn) InsertWebPageEvent(sessionID uint64, e *PageEvent) error { @@ -62,7 +61,7 @@ func (conn *Conn) InsertWebPageEvent(sessionID uint64, e *PageEvent) error { } tx, err := conn.begin() if err != nil { - return err + return err } defer tx.rollback() if err := tx.exec(` @@ -79,7 +78,7 @@ func (conn *Conn) InsertWebPageEvent(sessionID uint64, e *PageEvent) error { ) `, sessionID, e.MessageID, e.Timestamp, e.Referrer, url.DiscardURLQuery(e.Referrer), host, path, url.DiscardURLQuery(path), - e.DomContentLoadedEventEnd, e.LoadEventEnd, e.ResponseEnd, e.FirstPaint, e.FirstContentfulPaint, + e.DomContentLoadedEventEnd, e.LoadEventEnd, e.ResponseEnd, e.FirstPaint, e.FirstContentfulPaint, e.SpeedIndex, e.VisuallyComplete, e.TimeToInteractive, calcResponseTime(e), calcDomBuildingTime(e), ); err != nil { @@ -133,7 +132,6 @@ func (conn *Conn) InsertWebClickEvent(sessionID uint64, e *ClickEvent) error { return nil } - func (conn *Conn) InsertWebInputEvent(sessionID uint64, e *InputEvent) error { tx, err := conn.begin() if err != nil { @@ -205,3 +203,50 @@ func (conn *Conn) InsertWebErrorEvent(sessionID uint64, projectID uint32, e *Err } return tx.commit() } + +func (conn *Conn) InsertWebFetchEvent(sessionID uint64, savePayload bool, e *FetchEvent) error { + var request, response *string + if savePayload { + request = &e.Request + response = &e.Response + } + conn.insertAutocompleteValue(sessionID, "REQUEST", url.DiscardURLQuery(e.URL)) + return conn.batchQueue(sessionID, ` + INSERT INTO events_common.requests ( + session_id, timestamp, + seq_index, url, duration, success, + request_body, response_body, status_code, method + ) VALUES ( + $1, $2, + $3, $4, $5, $6, + $7, $8, $9::smallint, NULLIF($10, '')::events_common.http_method + ) ON CONFLICT DO NOTHING`, + sessionID, e.Timestamp, + getSqIdx(e.MessageID), e.URL, e.Duration, e.Status < 400, + request, response, e.Status, url.EnsureMethod(e.Method), + ) + +} + +func (conn *Conn) InsertWebGraphQLEvent(sessionID uint64, savePayload bool, e *GraphQLEvent) error { + var request, response *string + if savePayload { + request = &e.Variables + response = &e.Response + } + conn.insertAutocompleteValue(sessionID, "GRAPHQL", e.OperationName) + return conn.batchQueue(sessionID, ` + INSERT INTO events.graphql ( + session_id, timestamp, message_id, + name, + request_body, response_body + ) VALUES ( + $1, $2, $3, + $4, + $5, $6 + ) ON CONFLICT DO NOTHING`, + sessionID, e.Timestamp, e.MessageID, + e.OperationName, + request, response, + ) +} diff --git a/backend/pkg/db/postgres/notification.go b/backend/pkg/db/postgres/notification.go index 063e92f7b..c9670b8bd 100644 --- a/backend/pkg/db/postgres/notification.go +++ b/backend/pkg/db/postgres/notification.go @@ -14,7 +14,7 @@ type TenantNotification struct { Title string `db:"title" json:"title"` Description string `db:"description" json:"description"` ButtonText string `db:"button_text" json:"buttonText"` - ButtonUrl string `db:"button_url" json:"buttonUrl"` + ButtonUrl string `db:"button_url" json:"buttonUrl"` ImageUrl *string `db:"image_url" json:"imageUrl"` Options map[string]interface{} `db:"options" json:"options"` } diff --git a/backend/pkg/db/postgres/project.go b/backend/pkg/db/postgres/project.go index 2eea30662..066339791 100644 --- a/backend/pkg/db/postgres/project.go +++ b/backend/pkg/db/postgres/project.go @@ -5,7 +5,7 @@ import ( ) func (conn *Conn) GetProjectByKey(projectKey string) (*Project, error) { - p := &Project{ ProjectKey: projectKey } + p := &Project{ProjectKey: projectKey} if err := conn.queryRow(` SELECT max_session_duration, sample_rate, project_id FROM projects @@ -20,19 +20,19 @@ func (conn *Conn) GetProjectByKey(projectKey string) (*Project, error) { // TODO: logical separation of metadata func (conn *Conn) GetProject(projectID uint32) (*Project, error) { - p := &Project{ ProjectID: projectID } + p := &Project{ProjectID: projectID} if err := conn.queryRow(` - SELECT project_key, max_session_duration, + SELECT project_key, max_session_duration, save_request_payloads, metadata_1, metadata_2, metadata_3, metadata_4, metadata_5, metadata_6, metadata_7, metadata_8, metadata_9, metadata_10 FROM projects WHERE project_id=$1 AND active = true `, projectID, - ).Scan(&p.ProjectKey,&p.MaxSessionDuration, - &p.Metadata1, &p.Metadata2, &p.Metadata3, &p.Metadata4, &p.Metadata5, - &p.Metadata6, &p.Metadata7, &p.Metadata8, &p.Metadata9, &p.Metadata10); err != nil { + ).Scan(&p.ProjectKey, &p.MaxSessionDuration, &p.SaveRequestPayloads, + &p.Metadata1, &p.Metadata2, &p.Metadata3, &p.Metadata4, &p.Metadata5, + &p.Metadata6, &p.Metadata7, &p.Metadata8, &p.Metadata9, &p.Metadata10); err != nil { return nil, err } return p, nil -} \ No newline at end of file +} diff --git a/backend/pkg/db/postgres/unstarted_session.go b/backend/pkg/db/postgres/unstarted_session.go index 162946e97..2a9a71037 100644 --- a/backend/pkg/db/postgres/unstarted_session.go +++ b/backend/pkg/db/postgres/unstarted_session.go @@ -1,18 +1,18 @@ package postgres type UnstartedSession struct { - ProjectKey string - TrackerVersion string - DoNotTrack bool - Platform string - UserAgent string - UserOS string - UserOSVersion string - UserBrowser string + ProjectKey string + TrackerVersion string + DoNotTrack bool + Platform string + UserAgent string + UserOS string + UserOSVersion string + UserBrowser string UserBrowserVersion string - UserDevice string - UserDeviceType string - UserCountry string + UserDevice string + UserDeviceType string + UserCountry string } func (conn *Conn) InsertUnstartedSession(s UnstartedSession) error { @@ -34,12 +34,12 @@ func (conn *Conn) InsertUnstartedSession(s UnstartedSession) error { $10, $11, $12 )`, - s.ProjectKey, + s.ProjectKey, s.TrackerVersion, s.DoNotTrack, s.Platform, s.UserAgent, s.UserOS, s.UserOSVersion, s.UserBrowser, s.UserBrowserVersion, - s.UserDevice, s.UserDeviceType, + s.UserDevice, s.UserDeviceType, s.UserCountry, ) } diff --git a/backend/pkg/db/types/project.go b/backend/pkg/db/types/project.go index 74ec90c47..a5bc2e82c 100644 --- a/backend/pkg/db/types/project.go +++ b/backend/pkg/db/types/project.go @@ -3,23 +3,23 @@ package types import "log" type Project struct { - ProjectID uint32 - ProjectKey string - MaxSessionDuration int64 - SampleRate byte - Metadata1 *string - Metadata2 *string - Metadata3 *string - Metadata4 *string - Metadata5 *string - Metadata6 *string - Metadata7 *string - Metadata8 *string - Metadata9 *string - Metadata10 *string + ProjectID uint32 + ProjectKey string + MaxSessionDuration int64 + SampleRate byte + SaveRequestPayloads bool + Metadata1 *string + Metadata2 *string + Metadata3 *string + Metadata4 *string + Metadata5 *string + Metadata6 *string + Metadata7 *string + Metadata8 *string + Metadata9 *string + Metadata10 *string } - func (p *Project) GetMetadataNo(key string) uint { if p == nil { log.Printf("GetMetadataNo: Project is nil") diff --git a/backend/pkg/db/types/session.go b/backend/pkg/db/types/session.go index 92607514d..4cf8dd1ea 100644 --- a/backend/pkg/db/types/session.go +++ b/backend/pkg/db/types/session.go @@ -12,10 +12,10 @@ type Session struct { UserDevice string UserCountry string - Duration *uint64 - PagesCount int - EventsCount int - ErrorsCount int + Duration *uint64 + PagesCount int + EventsCount int + ErrorsCount int UserID *string // pointer?? UserAnonymousID *string diff --git a/backend/pkg/messages/messages.go b/backend/pkg/messages/messages.go index cdff71e1d..38a1f61ba 100644 --- a/backend/pkg/messages/messages.go +++ b/backend/pkg/messages/messages.go @@ -8,8 +8,8 @@ type Message interface { type meta struct { Timestamp int64 - Index uint64 - TypeID uint64 + Index uint64 + TypeID uint64 } // Might also implement Encode() here (?) @@ -17,20 +17,20 @@ func (m *meta) Meta() *meta { return m } - type BatchMeta struct { *meta - PageNo uint64 -FirstIndex uint64 -Timestamp int64 + PageNo uint64 + FirstIndex uint64 + Timestamp int64 } -func (msg *BatchMeta) Encode() []byte{ - buf := make([]byte, 31 ) + +func (msg *BatchMeta) Encode() []byte { + buf := make([]byte, 31) buf[0] = 80 p := 1 p = WriteUint(msg.PageNo, buf, p) -p = WriteUint(msg.FirstIndex, buf, p) -p = WriteInt(msg.Timestamp, buf, p) + p = WriteUint(msg.FirstIndex, buf, p) + p = WriteInt(msg.Timestamp, buf, p) return buf[:p] } @@ -38,8 +38,9 @@ type Timestamp struct { *meta Timestamp uint64 } -func (msg *Timestamp) Encode() []byte{ - buf := make([]byte, 11 ) + +func (msg *Timestamp) Encode() []byte { + buf := make([]byte, 11) buf[0] = 0 p := 1 p = WriteUint(msg.Timestamp, buf, p) @@ -48,43 +49,44 @@ func (msg *Timestamp) Encode() []byte{ type SessionStart struct { *meta - Timestamp uint64 -ProjectID uint64 -TrackerVersion string -RevID string -UserUUID string -UserAgent string -UserOS string -UserOSVersion string -UserBrowser string -UserBrowserVersion string -UserDevice string -UserDeviceType string -UserDeviceMemorySize uint64 -UserDeviceHeapSize uint64 -UserCountry string -UserID string + Timestamp uint64 + ProjectID uint64 + TrackerVersion string + RevID string + UserUUID string + UserAgent string + UserOS string + UserOSVersion string + UserBrowser string + UserBrowserVersion string + UserDevice string + UserDeviceType string + UserDeviceMemorySize uint64 + UserDeviceHeapSize uint64 + UserCountry string + UserID string } -func (msg *SessionStart) Encode() []byte{ - buf := make([]byte, 161 + len(msg.TrackerVersion)+ len(msg.RevID)+ len(msg.UserUUID)+ len(msg.UserAgent)+ len(msg.UserOS)+ len(msg.UserOSVersion)+ len(msg.UserBrowser)+ len(msg.UserBrowserVersion)+ len(msg.UserDevice)+ len(msg.UserDeviceType)+ len(msg.UserCountry)+ len(msg.UserID)) + +func (msg *SessionStart) Encode() []byte { + buf := make([]byte, 161+len(msg.TrackerVersion)+len(msg.RevID)+len(msg.UserUUID)+len(msg.UserAgent)+len(msg.UserOS)+len(msg.UserOSVersion)+len(msg.UserBrowser)+len(msg.UserBrowserVersion)+len(msg.UserDevice)+len(msg.UserDeviceType)+len(msg.UserCountry)+len(msg.UserID)) buf[0] = 1 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.ProjectID, buf, p) -p = WriteString(msg.TrackerVersion, buf, p) -p = WriteString(msg.RevID, buf, p) -p = WriteString(msg.UserUUID, buf, p) -p = WriteString(msg.UserAgent, buf, p) -p = WriteString(msg.UserOS, buf, p) -p = WriteString(msg.UserOSVersion, buf, p) -p = WriteString(msg.UserBrowser, buf, p) -p = WriteString(msg.UserBrowserVersion, buf, p) -p = WriteString(msg.UserDevice, buf, p) -p = WriteString(msg.UserDeviceType, buf, p) -p = WriteUint(msg.UserDeviceMemorySize, buf, p) -p = WriteUint(msg.UserDeviceHeapSize, buf, p) -p = WriteString(msg.UserCountry, buf, p) -p = WriteString(msg.UserID, buf, p) + p = WriteUint(msg.ProjectID, buf, p) + p = WriteString(msg.TrackerVersion, buf, p) + p = WriteString(msg.RevID, buf, p) + p = WriteString(msg.UserUUID, buf, p) + p = WriteString(msg.UserAgent, buf, p) + p = WriteString(msg.UserOS, buf, p) + p = WriteString(msg.UserOSVersion, buf, p) + p = WriteString(msg.UserBrowser, buf, p) + p = WriteString(msg.UserBrowserVersion, buf, p) + p = WriteString(msg.UserDevice, buf, p) + p = WriteString(msg.UserDeviceType, buf, p) + p = WriteUint(msg.UserDeviceMemorySize, buf, p) + p = WriteUint(msg.UserDeviceHeapSize, buf, p) + p = WriteString(msg.UserCountry, buf, p) + p = WriteString(msg.UserID, buf, p) return buf[:p] } @@ -92,8 +94,9 @@ type SessionDisconnect struct { *meta Timestamp uint64 } -func (msg *SessionDisconnect) Encode() []byte{ - buf := make([]byte, 11 ) + +func (msg *SessionDisconnect) Encode() []byte { + buf := make([]byte, 11) buf[0] = 2 p := 1 p = WriteUint(msg.Timestamp, buf, p) @@ -104,8 +107,9 @@ type SessionEnd struct { *meta Timestamp uint64 } -func (msg *SessionEnd) Encode() []byte{ - buf := make([]byte, 11 ) + +func (msg *SessionEnd) Encode() []byte { + buf := make([]byte, 11) buf[0] = 3 p := 1 p = WriteUint(msg.Timestamp, buf, p) @@ -114,109 +118,115 @@ func (msg *SessionEnd) Encode() []byte{ type SetPageLocation struct { *meta - URL string -Referrer string -NavigationStart uint64 + URL string + Referrer string + NavigationStart uint64 } -func (msg *SetPageLocation) Encode() []byte{ - buf := make([]byte, 31 + len(msg.URL)+ len(msg.Referrer)) + +func (msg *SetPageLocation) Encode() []byte { + buf := make([]byte, 31+len(msg.URL)+len(msg.Referrer)) buf[0] = 4 p := 1 p = WriteString(msg.URL, buf, p) -p = WriteString(msg.Referrer, buf, p) -p = WriteUint(msg.NavigationStart, buf, p) + p = WriteString(msg.Referrer, buf, p) + p = WriteUint(msg.NavigationStart, buf, p) return buf[:p] } type SetViewportSize struct { *meta - Width uint64 -Height uint64 + Width uint64 + Height uint64 } -func (msg *SetViewportSize) Encode() []byte{ - buf := make([]byte, 21 ) + +func (msg *SetViewportSize) Encode() []byte { + buf := make([]byte, 21) buf[0] = 5 p := 1 p = WriteUint(msg.Width, buf, p) -p = WriteUint(msg.Height, buf, p) + p = WriteUint(msg.Height, buf, p) return buf[:p] } type SetViewportScroll struct { *meta X int64 -Y int64 + Y int64 } -func (msg *SetViewportScroll) Encode() []byte{ - buf := make([]byte, 21 ) + +func (msg *SetViewportScroll) Encode() []byte { + buf := make([]byte, 21) buf[0] = 6 p := 1 p = WriteInt(msg.X, buf, p) -p = WriteInt(msg.Y, buf, p) + p = WriteInt(msg.Y, buf, p) return buf[:p] } type CreateDocument struct { *meta - } -func (msg *CreateDocument) Encode() []byte{ - buf := make([]byte, 1 ) + +func (msg *CreateDocument) Encode() []byte { + buf := make([]byte, 1) buf[0] = 7 p := 1 - + return buf[:p] } type CreateElementNode struct { *meta - ID uint64 -ParentID uint64 -index uint64 -Tag string -SVG bool + ID uint64 + ParentID uint64 + index uint64 + Tag string + SVG bool } -func (msg *CreateElementNode) Encode() []byte{ - buf := make([]byte, 51 + len(msg.Tag)) + +func (msg *CreateElementNode) Encode() []byte { + buf := make([]byte, 51+len(msg.Tag)) buf[0] = 8 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteUint(msg.ParentID, buf, p) -p = WriteUint(msg.index, buf, p) -p = WriteString(msg.Tag, buf, p) -p = WriteBoolean(msg.SVG, buf, p) + p = WriteUint(msg.ParentID, buf, p) + p = WriteUint(msg.index, buf, p) + p = WriteString(msg.Tag, buf, p) + p = WriteBoolean(msg.SVG, buf, p) return buf[:p] } type CreateTextNode struct { *meta - ID uint64 -ParentID uint64 -Index uint64 + ID uint64 + ParentID uint64 + Index uint64 } -func (msg *CreateTextNode) Encode() []byte{ - buf := make([]byte, 31 ) + +func (msg *CreateTextNode) Encode() []byte { + buf := make([]byte, 31) buf[0] = 9 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteUint(msg.ParentID, buf, p) -p = WriteUint(msg.Index, buf, p) + p = WriteUint(msg.ParentID, buf, p) + p = WriteUint(msg.Index, buf, p) return buf[:p] } type MoveNode struct { *meta - ID uint64 -ParentID uint64 -Index uint64 + ID uint64 + ParentID uint64 + Index uint64 } -func (msg *MoveNode) Encode() []byte{ - buf := make([]byte, 31 ) + +func (msg *MoveNode) Encode() []byte { + buf := make([]byte, 31) buf[0] = 10 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteUint(msg.ParentID, buf, p) -p = WriteUint(msg.Index, buf, p) + p = WriteUint(msg.ParentID, buf, p) + p = WriteUint(msg.Index, buf, p) return buf[:p] } @@ -224,8 +234,9 @@ type RemoveNode struct { *meta ID uint64 } -func (msg *RemoveNode) Encode() []byte{ - buf := make([]byte, 11 ) + +func (msg *RemoveNode) Encode() []byte { + buf := make([]byte, 11) buf[0] = 11 p := 1 p = WriteUint(msg.ID, buf, p) @@ -234,257 +245,273 @@ func (msg *RemoveNode) Encode() []byte{ type SetNodeAttribute struct { *meta - ID uint64 -Name string -Value string + ID uint64 + Name string + Value string } -func (msg *SetNodeAttribute) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Name)+ len(msg.Value)) + +func (msg *SetNodeAttribute) Encode() []byte { + buf := make([]byte, 31+len(msg.Name)+len(msg.Value)) buf[0] = 12 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteString(msg.Name, buf, p) -p = WriteString(msg.Value, buf, p) + p = WriteString(msg.Name, buf, p) + p = WriteString(msg.Value, buf, p) return buf[:p] } type RemoveNodeAttribute struct { *meta - ID uint64 -Name string + ID uint64 + Name string } -func (msg *RemoveNodeAttribute) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Name)) + +func (msg *RemoveNodeAttribute) Encode() []byte { + buf := make([]byte, 21+len(msg.Name)) buf[0] = 13 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteString(msg.Name, buf, p) + p = WriteString(msg.Name, buf, p) return buf[:p] } type SetNodeData struct { *meta - ID uint64 -Data string + ID uint64 + Data string } -func (msg *SetNodeData) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Data)) + +func (msg *SetNodeData) Encode() []byte { + buf := make([]byte, 21+len(msg.Data)) buf[0] = 14 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteString(msg.Data, buf, p) + p = WriteString(msg.Data, buf, p) return buf[:p] } type SetCSSData struct { *meta - ID uint64 -Data string + ID uint64 + Data string } -func (msg *SetCSSData) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Data)) + +func (msg *SetCSSData) Encode() []byte { + buf := make([]byte, 21+len(msg.Data)) buf[0] = 15 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteString(msg.Data, buf, p) + p = WriteString(msg.Data, buf, p) return buf[:p] } type SetNodeScroll struct { *meta ID uint64 -X int64 -Y int64 + X int64 + Y int64 } -func (msg *SetNodeScroll) Encode() []byte{ - buf := make([]byte, 31 ) + +func (msg *SetNodeScroll) Encode() []byte { + buf := make([]byte, 31) buf[0] = 16 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteInt(msg.X, buf, p) -p = WriteInt(msg.Y, buf, p) + p = WriteInt(msg.X, buf, p) + p = WriteInt(msg.Y, buf, p) return buf[:p] } type SetInputTarget struct { *meta - ID uint64 -Label string + ID uint64 + Label string } -func (msg *SetInputTarget) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Label)) + +func (msg *SetInputTarget) Encode() []byte { + buf := make([]byte, 21+len(msg.Label)) buf[0] = 17 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteString(msg.Label, buf, p) + p = WriteString(msg.Label, buf, p) return buf[:p] } type SetInputValue struct { *meta - ID uint64 -Value string -Mask int64 + ID uint64 + Value string + Mask int64 } -func (msg *SetInputValue) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Value)) + +func (msg *SetInputValue) Encode() []byte { + buf := make([]byte, 31+len(msg.Value)) buf[0] = 18 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteString(msg.Value, buf, p) -p = WriteInt(msg.Mask, buf, p) + p = WriteString(msg.Value, buf, p) + p = WriteInt(msg.Mask, buf, p) return buf[:p] } type SetInputChecked struct { *meta - ID uint64 -Checked bool + ID uint64 + Checked bool } -func (msg *SetInputChecked) Encode() []byte{ - buf := make([]byte, 21 ) + +func (msg *SetInputChecked) Encode() []byte { + buf := make([]byte, 21) buf[0] = 19 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteBoolean(msg.Checked, buf, p) + p = WriteBoolean(msg.Checked, buf, p) return buf[:p] } type MouseMove struct { *meta X uint64 -Y uint64 + Y uint64 } -func (msg *MouseMove) Encode() []byte{ - buf := make([]byte, 21 ) + +func (msg *MouseMove) Encode() []byte { + buf := make([]byte, 21) buf[0] = 20 p := 1 p = WriteUint(msg.X, buf, p) -p = WriteUint(msg.Y, buf, p) + p = WriteUint(msg.Y, buf, p) return buf[:p] } type MouseClickDepricated struct { *meta - ID uint64 -HesitationTime uint64 -Label string + ID uint64 + HesitationTime uint64 + Label string } -func (msg *MouseClickDepricated) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Label)) + +func (msg *MouseClickDepricated) Encode() []byte { + buf := make([]byte, 31+len(msg.Label)) buf[0] = 21 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteUint(msg.HesitationTime, buf, p) -p = WriteString(msg.Label, buf, p) + p = WriteUint(msg.HesitationTime, buf, p) + p = WriteString(msg.Label, buf, p) return buf[:p] } type ConsoleLog struct { *meta Level string -Value string + Value string } -func (msg *ConsoleLog) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Level)+ len(msg.Value)) + +func (msg *ConsoleLog) Encode() []byte { + buf := make([]byte, 21+len(msg.Level)+len(msg.Value)) buf[0] = 22 p := 1 p = WriteString(msg.Level, buf, p) -p = WriteString(msg.Value, buf, p) + p = WriteString(msg.Value, buf, p) return buf[:p] } type PageLoadTiming struct { *meta - RequestStart uint64 -ResponseStart uint64 -ResponseEnd uint64 -DomContentLoadedEventStart uint64 -DomContentLoadedEventEnd uint64 -LoadEventStart uint64 -LoadEventEnd uint64 -FirstPaint uint64 -FirstContentfulPaint uint64 + RequestStart uint64 + ResponseStart uint64 + ResponseEnd uint64 + DomContentLoadedEventStart uint64 + DomContentLoadedEventEnd uint64 + LoadEventStart uint64 + LoadEventEnd uint64 + FirstPaint uint64 + FirstContentfulPaint uint64 } -func (msg *PageLoadTiming) Encode() []byte{ - buf := make([]byte, 91 ) + +func (msg *PageLoadTiming) Encode() []byte { + buf := make([]byte, 91) buf[0] = 23 p := 1 p = WriteUint(msg.RequestStart, buf, p) -p = WriteUint(msg.ResponseStart, buf, p) -p = WriteUint(msg.ResponseEnd, buf, p) -p = WriteUint(msg.DomContentLoadedEventStart, buf, p) -p = WriteUint(msg.DomContentLoadedEventEnd, buf, p) -p = WriteUint(msg.LoadEventStart, buf, p) -p = WriteUint(msg.LoadEventEnd, buf, p) -p = WriteUint(msg.FirstPaint, buf, p) -p = WriteUint(msg.FirstContentfulPaint, buf, p) + p = WriteUint(msg.ResponseStart, buf, p) + p = WriteUint(msg.ResponseEnd, buf, p) + p = WriteUint(msg.DomContentLoadedEventStart, buf, p) + p = WriteUint(msg.DomContentLoadedEventEnd, buf, p) + p = WriteUint(msg.LoadEventStart, buf, p) + p = WriteUint(msg.LoadEventEnd, buf, p) + p = WriteUint(msg.FirstPaint, buf, p) + p = WriteUint(msg.FirstContentfulPaint, buf, p) return buf[:p] } type PageRenderTiming struct { *meta - SpeedIndex uint64 -VisuallyComplete uint64 -TimeToInteractive uint64 + SpeedIndex uint64 + VisuallyComplete uint64 + TimeToInteractive uint64 } -func (msg *PageRenderTiming) Encode() []byte{ - buf := make([]byte, 31 ) + +func (msg *PageRenderTiming) Encode() []byte { + buf := make([]byte, 31) buf[0] = 24 p := 1 p = WriteUint(msg.SpeedIndex, buf, p) -p = WriteUint(msg.VisuallyComplete, buf, p) -p = WriteUint(msg.TimeToInteractive, buf, p) + p = WriteUint(msg.VisuallyComplete, buf, p) + p = WriteUint(msg.TimeToInteractive, buf, p) return buf[:p] } type JSException struct { *meta - Name string -Message string -Payload string + Name string + Message string + Payload string } -func (msg *JSException) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Name)+ len(msg.Message)+ len(msg.Payload)) + +func (msg *JSException) Encode() []byte { + buf := make([]byte, 31+len(msg.Name)+len(msg.Message)+len(msg.Payload)) buf[0] = 25 p := 1 p = WriteString(msg.Name, buf, p) -p = WriteString(msg.Message, buf, p) -p = WriteString(msg.Payload, buf, p) + p = WriteString(msg.Message, buf, p) + p = WriteString(msg.Payload, buf, p) return buf[:p] } type RawErrorEvent struct { *meta Timestamp uint64 -Source string -Name string -Message string -Payload string + Source string + Name string + Message string + Payload string } -func (msg *RawErrorEvent) Encode() []byte{ - buf := make([]byte, 51 + len(msg.Source)+ len(msg.Name)+ len(msg.Message)+ len(msg.Payload)) + +func (msg *RawErrorEvent) Encode() []byte { + buf := make([]byte, 51+len(msg.Source)+len(msg.Name)+len(msg.Message)+len(msg.Payload)) buf[0] = 26 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteString(msg.Source, buf, p) -p = WriteString(msg.Name, buf, p) -p = WriteString(msg.Message, buf, p) -p = WriteString(msg.Payload, buf, p) + p = WriteString(msg.Source, buf, p) + p = WriteString(msg.Name, buf, p) + p = WriteString(msg.Message, buf, p) + p = WriteString(msg.Payload, buf, p) return buf[:p] } type RawCustomEvent struct { *meta - Name string -Payload string + Name string + Payload string } -func (msg *RawCustomEvent) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Name)+ len(msg.Payload)) + +func (msg *RawCustomEvent) Encode() []byte { + buf := make([]byte, 21+len(msg.Name)+len(msg.Payload)) buf[0] = 27 p := 1 p = WriteString(msg.Name, buf, p) -p = WriteString(msg.Payload, buf, p) + p = WriteString(msg.Payload, buf, p) return buf[:p] } @@ -492,8 +519,9 @@ type UserID struct { *meta ID string } -func (msg *UserID) Encode() []byte{ - buf := make([]byte, 11 + len(msg.ID)) + +func (msg *UserID) Encode() []byte { + buf := make([]byte, 11+len(msg.ID)) buf[0] = 28 p := 1 p = WriteString(msg.ID, buf, p) @@ -504,8 +532,9 @@ type UserAnonymousID struct { *meta ID string } -func (msg *UserAnonymousID) Encode() []byte{ - buf := make([]byte, 11 + len(msg.ID)) + +func (msg *UserAnonymousID) Encode() []byte { + buf := make([]byte, 11+len(msg.ID)) buf[0] = 29 p := 1 p = WriteString(msg.ID, buf, p) @@ -514,259 +543,271 @@ func (msg *UserAnonymousID) Encode() []byte{ type Metadata struct { *meta - Key string -Value string + Key string + Value string } -func (msg *Metadata) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Key)+ len(msg.Value)) + +func (msg *Metadata) Encode() []byte { + buf := make([]byte, 21+len(msg.Key)+len(msg.Value)) buf[0] = 30 p := 1 p = WriteString(msg.Key, buf, p) -p = WriteString(msg.Value, buf, p) + p = WriteString(msg.Value, buf, p) return buf[:p] } type PageEvent struct { *meta - MessageID uint64 -Timestamp uint64 -URL string -Referrer string -Loaded bool -RequestStart uint64 -ResponseStart uint64 -ResponseEnd uint64 -DomContentLoadedEventStart uint64 -DomContentLoadedEventEnd uint64 -LoadEventStart uint64 -LoadEventEnd uint64 -FirstPaint uint64 -FirstContentfulPaint uint64 -SpeedIndex uint64 -VisuallyComplete uint64 -TimeToInteractive uint64 + MessageID uint64 + Timestamp uint64 + URL string + Referrer string + Loaded bool + RequestStart uint64 + ResponseStart uint64 + ResponseEnd uint64 + DomContentLoadedEventStart uint64 + DomContentLoadedEventEnd uint64 + LoadEventStart uint64 + LoadEventEnd uint64 + FirstPaint uint64 + FirstContentfulPaint uint64 + SpeedIndex uint64 + VisuallyComplete uint64 + TimeToInteractive uint64 } -func (msg *PageEvent) Encode() []byte{ - buf := make([]byte, 171 + len(msg.URL)+ len(msg.Referrer)) + +func (msg *PageEvent) Encode() []byte { + buf := make([]byte, 171+len(msg.URL)+len(msg.Referrer)) buf[0] = 31 p := 1 p = WriteUint(msg.MessageID, buf, p) -p = WriteUint(msg.Timestamp, buf, p) -p = WriteString(msg.URL, buf, p) -p = WriteString(msg.Referrer, buf, p) -p = WriteBoolean(msg.Loaded, buf, p) -p = WriteUint(msg.RequestStart, buf, p) -p = WriteUint(msg.ResponseStart, buf, p) -p = WriteUint(msg.ResponseEnd, buf, p) -p = WriteUint(msg.DomContentLoadedEventStart, buf, p) -p = WriteUint(msg.DomContentLoadedEventEnd, buf, p) -p = WriteUint(msg.LoadEventStart, buf, p) -p = WriteUint(msg.LoadEventEnd, buf, p) -p = WriteUint(msg.FirstPaint, buf, p) -p = WriteUint(msg.FirstContentfulPaint, buf, p) -p = WriteUint(msg.SpeedIndex, buf, p) -p = WriteUint(msg.VisuallyComplete, buf, p) -p = WriteUint(msg.TimeToInteractive, buf, p) + p = WriteUint(msg.Timestamp, buf, p) + p = WriteString(msg.URL, buf, p) + p = WriteString(msg.Referrer, buf, p) + p = WriteBoolean(msg.Loaded, buf, p) + p = WriteUint(msg.RequestStart, buf, p) + p = WriteUint(msg.ResponseStart, buf, p) + p = WriteUint(msg.ResponseEnd, buf, p) + p = WriteUint(msg.DomContentLoadedEventStart, buf, p) + p = WriteUint(msg.DomContentLoadedEventEnd, buf, p) + p = WriteUint(msg.LoadEventStart, buf, p) + p = WriteUint(msg.LoadEventEnd, buf, p) + p = WriteUint(msg.FirstPaint, buf, p) + p = WriteUint(msg.FirstContentfulPaint, buf, p) + p = WriteUint(msg.SpeedIndex, buf, p) + p = WriteUint(msg.VisuallyComplete, buf, p) + p = WriteUint(msg.TimeToInteractive, buf, p) return buf[:p] } type InputEvent struct { *meta - MessageID uint64 -Timestamp uint64 -Value string -ValueMasked bool -Label string + MessageID uint64 + Timestamp uint64 + Value string + ValueMasked bool + Label string } -func (msg *InputEvent) Encode() []byte{ - buf := make([]byte, 51 + len(msg.Value)+ len(msg.Label)) + +func (msg *InputEvent) Encode() []byte { + buf := make([]byte, 51+len(msg.Value)+len(msg.Label)) buf[0] = 32 p := 1 p = WriteUint(msg.MessageID, buf, p) -p = WriteUint(msg.Timestamp, buf, p) -p = WriteString(msg.Value, buf, p) -p = WriteBoolean(msg.ValueMasked, buf, p) -p = WriteString(msg.Label, buf, p) + p = WriteUint(msg.Timestamp, buf, p) + p = WriteString(msg.Value, buf, p) + p = WriteBoolean(msg.ValueMasked, buf, p) + p = WriteString(msg.Label, buf, p) return buf[:p] } type ClickEvent struct { *meta - MessageID uint64 -Timestamp uint64 -HesitationTime uint64 -Label string -Selector string + MessageID uint64 + Timestamp uint64 + HesitationTime uint64 + Label string + Selector string } -func (msg *ClickEvent) Encode() []byte{ - buf := make([]byte, 51 + len(msg.Label)+ len(msg.Selector)) + +func (msg *ClickEvent) Encode() []byte { + buf := make([]byte, 51+len(msg.Label)+len(msg.Selector)) buf[0] = 33 p := 1 p = WriteUint(msg.MessageID, buf, p) -p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.HesitationTime, buf, p) -p = WriteString(msg.Label, buf, p) -p = WriteString(msg.Selector, buf, p) + p = WriteUint(msg.Timestamp, buf, p) + p = WriteUint(msg.HesitationTime, buf, p) + p = WriteString(msg.Label, buf, p) + p = WriteString(msg.Selector, buf, p) return buf[:p] } type ErrorEvent struct { *meta MessageID uint64 -Timestamp uint64 -Source string -Name string -Message string -Payload string + Timestamp uint64 + Source string + Name string + Message string + Payload string } -func (msg *ErrorEvent) Encode() []byte{ - buf := make([]byte, 61 + len(msg.Source)+ len(msg.Name)+ len(msg.Message)+ len(msg.Payload)) + +func (msg *ErrorEvent) Encode() []byte { + buf := make([]byte, 61+len(msg.Source)+len(msg.Name)+len(msg.Message)+len(msg.Payload)) buf[0] = 34 p := 1 p = WriteUint(msg.MessageID, buf, p) -p = WriteUint(msg.Timestamp, buf, p) -p = WriteString(msg.Source, buf, p) -p = WriteString(msg.Name, buf, p) -p = WriteString(msg.Message, buf, p) -p = WriteString(msg.Payload, buf, p) + p = WriteUint(msg.Timestamp, buf, p) + p = WriteString(msg.Source, buf, p) + p = WriteString(msg.Name, buf, p) + p = WriteString(msg.Message, buf, p) + p = WriteString(msg.Payload, buf, p) return buf[:p] } type ResourceEvent struct { *meta - MessageID uint64 -Timestamp uint64 -Duration uint64 -TTFB uint64 -HeaderSize uint64 -EncodedBodySize uint64 -DecodedBodySize uint64 -URL string -Type string -Success bool -Method string -Status uint64 + MessageID uint64 + Timestamp uint64 + Duration uint64 + TTFB uint64 + HeaderSize uint64 + EncodedBodySize uint64 + DecodedBodySize uint64 + URL string + Type string + Success bool + Method string + Status uint64 } -func (msg *ResourceEvent) Encode() []byte{ - buf := make([]byte, 121 + len(msg.URL)+ len(msg.Type)+ len(msg.Method)) + +func (msg *ResourceEvent) Encode() []byte { + buf := make([]byte, 121+len(msg.URL)+len(msg.Type)+len(msg.Method)) buf[0] = 35 p := 1 p = WriteUint(msg.MessageID, buf, p) -p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Duration, buf, p) -p = WriteUint(msg.TTFB, buf, p) -p = WriteUint(msg.HeaderSize, buf, p) -p = WriteUint(msg.EncodedBodySize, buf, p) -p = WriteUint(msg.DecodedBodySize, buf, p) -p = WriteString(msg.URL, buf, p) -p = WriteString(msg.Type, buf, p) -p = WriteBoolean(msg.Success, buf, p) -p = WriteString(msg.Method, buf, p) -p = WriteUint(msg.Status, buf, p) + p = WriteUint(msg.Timestamp, buf, p) + p = WriteUint(msg.Duration, buf, p) + p = WriteUint(msg.TTFB, buf, p) + p = WriteUint(msg.HeaderSize, buf, p) + p = WriteUint(msg.EncodedBodySize, buf, p) + p = WriteUint(msg.DecodedBodySize, buf, p) + p = WriteString(msg.URL, buf, p) + p = WriteString(msg.Type, buf, p) + p = WriteBoolean(msg.Success, buf, p) + p = WriteString(msg.Method, buf, p) + p = WriteUint(msg.Status, buf, p) return buf[:p] } type CustomEvent struct { *meta MessageID uint64 -Timestamp uint64 -Name string -Payload string + Timestamp uint64 + Name string + Payload string } -func (msg *CustomEvent) Encode() []byte{ - buf := make([]byte, 41 + len(msg.Name)+ len(msg.Payload)) + +func (msg *CustomEvent) Encode() []byte { + buf := make([]byte, 41+len(msg.Name)+len(msg.Payload)) buf[0] = 36 p := 1 p = WriteUint(msg.MessageID, buf, p) -p = WriteUint(msg.Timestamp, buf, p) -p = WriteString(msg.Name, buf, p) -p = WriteString(msg.Payload, buf, p) + p = WriteUint(msg.Timestamp, buf, p) + p = WriteString(msg.Name, buf, p) + p = WriteString(msg.Payload, buf, p) return buf[:p] } type CSSInsertRule struct { *meta - ID uint64 -Rule string -Index uint64 + ID uint64 + Rule string + Index uint64 } -func (msg *CSSInsertRule) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Rule)) + +func (msg *CSSInsertRule) Encode() []byte { + buf := make([]byte, 31+len(msg.Rule)) buf[0] = 37 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteString(msg.Rule, buf, p) -p = WriteUint(msg.Index, buf, p) + p = WriteString(msg.Rule, buf, p) + p = WriteUint(msg.Index, buf, p) return buf[:p] } type CSSDeleteRule struct { *meta - ID uint64 -Index uint64 + ID uint64 + Index uint64 } -func (msg *CSSDeleteRule) Encode() []byte{ - buf := make([]byte, 21 ) + +func (msg *CSSDeleteRule) Encode() []byte { + buf := make([]byte, 21) buf[0] = 38 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteUint(msg.Index, buf, p) + p = WriteUint(msg.Index, buf, p) return buf[:p] } type Fetch struct { *meta - Method string -URL string -Request string -Response string -Status uint64 -Timestamp uint64 -Duration uint64 + Method string + URL string + Request string + Response string + Status uint64 + Timestamp uint64 + Duration uint64 } -func (msg *Fetch) Encode() []byte{ - buf := make([]byte, 71 + len(msg.Method)+ len(msg.URL)+ len(msg.Request)+ len(msg.Response)) + +func (msg *Fetch) Encode() []byte { + buf := make([]byte, 71+len(msg.Method)+len(msg.URL)+len(msg.Request)+len(msg.Response)) buf[0] = 39 p := 1 p = WriteString(msg.Method, buf, p) -p = WriteString(msg.URL, buf, p) -p = WriteString(msg.Request, buf, p) -p = WriteString(msg.Response, buf, p) -p = WriteUint(msg.Status, buf, p) -p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Duration, buf, p) + p = WriteString(msg.URL, buf, p) + p = WriteString(msg.Request, buf, p) + p = WriteString(msg.Response, buf, p) + p = WriteUint(msg.Status, buf, p) + p = WriteUint(msg.Timestamp, buf, p) + p = WriteUint(msg.Duration, buf, p) return buf[:p] } type Profiler struct { *meta - Name string -Duration uint64 -Args string -Result string + Name string + Duration uint64 + Args string + Result string } -func (msg *Profiler) Encode() []byte{ - buf := make([]byte, 41 + len(msg.Name)+ len(msg.Args)+ len(msg.Result)) + +func (msg *Profiler) Encode() []byte { + buf := make([]byte, 41+len(msg.Name)+len(msg.Args)+len(msg.Result)) buf[0] = 40 p := 1 p = WriteString(msg.Name, buf, p) -p = WriteUint(msg.Duration, buf, p) -p = WriteString(msg.Args, buf, p) -p = WriteString(msg.Result, buf, p) + p = WriteUint(msg.Duration, buf, p) + p = WriteString(msg.Args, buf, p) + p = WriteString(msg.Result, buf, p) return buf[:p] } type OTable struct { *meta - Key string -Value string + Key string + Value string } -func (msg *OTable) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Key)+ len(msg.Value)) + +func (msg *OTable) Encode() []byte { + buf := make([]byte, 21+len(msg.Key)+len(msg.Value)) buf[0] = 41 p := 1 p = WriteString(msg.Key, buf, p) -p = WriteString(msg.Value, buf, p) + p = WriteString(msg.Value, buf, p) return buf[:p] } @@ -774,8 +815,9 @@ type StateAction struct { *meta Type string } -func (msg *StateAction) Encode() []byte{ - buf := make([]byte, 11 + len(msg.Type)) + +func (msg *StateAction) Encode() []byte { + buf := make([]byte, 11+len(msg.Type)) buf[0] = 42 p := 1 p = WriteString(msg.Type, buf, p) @@ -785,128 +827,169 @@ func (msg *StateAction) Encode() []byte{ type StateActionEvent struct { *meta MessageID uint64 -Timestamp uint64 -Type string + Timestamp uint64 + Type string } -func (msg *StateActionEvent) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Type)) + +func (msg *StateActionEvent) Encode() []byte { + buf := make([]byte, 31+len(msg.Type)) buf[0] = 43 p := 1 p = WriteUint(msg.MessageID, buf, p) -p = WriteUint(msg.Timestamp, buf, p) -p = WriteString(msg.Type, buf, p) + p = WriteUint(msg.Timestamp, buf, p) + p = WriteString(msg.Type, buf, p) return buf[:p] } type Redux struct { *meta - Action string -State string -Duration uint64 + Action string + State string + Duration uint64 } -func (msg *Redux) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Action)+ len(msg.State)) + +func (msg *Redux) Encode() []byte { + buf := make([]byte, 31+len(msg.Action)+len(msg.State)) buf[0] = 44 p := 1 p = WriteString(msg.Action, buf, p) -p = WriteString(msg.State, buf, p) -p = WriteUint(msg.Duration, buf, p) + p = WriteString(msg.State, buf, p) + p = WriteUint(msg.Duration, buf, p) return buf[:p] } type Vuex struct { *meta Mutation string -State string + State string } -func (msg *Vuex) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Mutation)+ len(msg.State)) + +func (msg *Vuex) Encode() []byte { + buf := make([]byte, 21+len(msg.Mutation)+len(msg.State)) buf[0] = 45 p := 1 p = WriteString(msg.Mutation, buf, p) -p = WriteString(msg.State, buf, p) + p = WriteString(msg.State, buf, p) return buf[:p] } type MobX struct { *meta - Type string -Payload string + Type string + Payload string } -func (msg *MobX) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Type)+ len(msg.Payload)) + +func (msg *MobX) Encode() []byte { + buf := make([]byte, 21+len(msg.Type)+len(msg.Payload)) buf[0] = 46 p := 1 p = WriteString(msg.Type, buf, p) -p = WriteString(msg.Payload, buf, p) + p = WriteString(msg.Payload, buf, p) return buf[:p] } type NgRx struct { *meta - Action string -State string -Duration uint64 + Action string + State string + Duration uint64 } -func (msg *NgRx) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Action)+ len(msg.State)) + +func (msg *NgRx) Encode() []byte { + buf := make([]byte, 31+len(msg.Action)+len(msg.State)) buf[0] = 47 p := 1 p = WriteString(msg.Action, buf, p) -p = WriteString(msg.State, buf, p) -p = WriteUint(msg.Duration, buf, p) + p = WriteString(msg.State, buf, p) + p = WriteUint(msg.Duration, buf, p) return buf[:p] } type GraphQL struct { *meta OperationKind string -OperationName string -Variables string -Response string + OperationName string + Variables string + Response string } -func (msg *GraphQL) Encode() []byte{ - buf := make([]byte, 41 + len(msg.OperationKind)+ len(msg.OperationName)+ len(msg.Variables)+ len(msg.Response)) + +func (msg *GraphQL) Encode() []byte { + buf := make([]byte, 41+len(msg.OperationKind)+len(msg.OperationName)+len(msg.Variables)+len(msg.Response)) buf[0] = 48 p := 1 p = WriteString(msg.OperationKind, buf, p) -p = WriteString(msg.OperationName, buf, p) -p = WriteString(msg.Variables, buf, p) -p = WriteString(msg.Response, buf, p) + p = WriteString(msg.OperationName, buf, p) + p = WriteString(msg.Variables, buf, p) + p = WriteString(msg.Response, buf, p) return buf[:p] } type PerformanceTrack struct { *meta - Frames int64 -Ticks int64 -TotalJSHeapSize uint64 -UsedJSHeapSize uint64 + Frames int64 + Ticks int64 + TotalJSHeapSize uint64 + UsedJSHeapSize uint64 } -func (msg *PerformanceTrack) Encode() []byte{ - buf := make([]byte, 41 ) + +func (msg *PerformanceTrack) Encode() []byte { + buf := make([]byte, 41) buf[0] = 49 p := 1 p = WriteInt(msg.Frames, buf, p) -p = WriteInt(msg.Ticks, buf, p) -p = WriteUint(msg.TotalJSHeapSize, buf, p) -p = WriteUint(msg.UsedJSHeapSize, buf, p) + p = WriteInt(msg.Ticks, buf, p) + p = WriteUint(msg.TotalJSHeapSize, buf, p) + p = WriteUint(msg.UsedJSHeapSize, buf, p) return buf[:p] } type GraphQLEvent struct { *meta - MessageID uint64 -Timestamp uint64 -Name string + MessageID uint64 + Timestamp uint64 + OperationKind string + OperationName string + Variables string + Response string } -func (msg *GraphQLEvent) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Name)) + +func (msg *GraphQLEvent) Encode() []byte { + buf := make([]byte, 61+len(msg.OperationKind)+len(msg.OperationName)+len(msg.Variables)+len(msg.Response)) buf[0] = 50 p := 1 p = WriteUint(msg.MessageID, buf, p) -p = WriteUint(msg.Timestamp, buf, p) -p = WriteString(msg.Name, buf, p) + p = WriteUint(msg.Timestamp, buf, p) + p = WriteString(msg.OperationKind, buf, p) + p = WriteString(msg.OperationName, buf, p) + p = WriteString(msg.Variables, buf, p) + p = WriteString(msg.Response, buf, p) + return buf[:p] +} + +type FetchEvent struct { + *meta + MessageID uint64 + Timestamp uint64 + Method string + URL string + Request string + Response string + Status uint64 + Duration uint64 +} + +func (msg *FetchEvent) Encode() []byte { + buf := make([]byte, 81+len(msg.Method)+len(msg.URL)+len(msg.Request)+len(msg.Response)) + buf[0] = 51 + p := 1 + p = WriteUint(msg.MessageID, buf, p) + p = WriteUint(msg.Timestamp, buf, p) + p = WriteString(msg.Method, buf, p) + p = WriteString(msg.URL, buf, p) + p = WriteString(msg.Request, buf, p) + p = WriteString(msg.Response, buf, p) + p = WriteUint(msg.Status, buf, p) + p = WriteUint(msg.Duration, buf, p) return buf[:p] } @@ -914,8 +997,9 @@ type DOMDrop struct { *meta Timestamp uint64 } -func (msg *DOMDrop) Encode() []byte{ - buf := make([]byte, 11 ) + +func (msg *DOMDrop) Encode() []byte { + buf := make([]byte, 11) buf[0] = 52 p := 1 p = WriteUint(msg.Timestamp, buf, p) @@ -924,41 +1008,43 @@ func (msg *DOMDrop) Encode() []byte{ type ResourceTiming struct { *meta - Timestamp uint64 -Duration uint64 -TTFB uint64 -HeaderSize uint64 -EncodedBodySize uint64 -DecodedBodySize uint64 -URL string -Initiator string + Timestamp uint64 + Duration uint64 + TTFB uint64 + HeaderSize uint64 + EncodedBodySize uint64 + DecodedBodySize uint64 + URL string + Initiator string } -func (msg *ResourceTiming) Encode() []byte{ - buf := make([]byte, 81 + len(msg.URL)+ len(msg.Initiator)) + +func (msg *ResourceTiming) Encode() []byte { + buf := make([]byte, 81+len(msg.URL)+len(msg.Initiator)) buf[0] = 53 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Duration, buf, p) -p = WriteUint(msg.TTFB, buf, p) -p = WriteUint(msg.HeaderSize, buf, p) -p = WriteUint(msg.EncodedBodySize, buf, p) -p = WriteUint(msg.DecodedBodySize, buf, p) -p = WriteString(msg.URL, buf, p) -p = WriteString(msg.Initiator, buf, p) + p = WriteUint(msg.Duration, buf, p) + p = WriteUint(msg.TTFB, buf, p) + p = WriteUint(msg.HeaderSize, buf, p) + p = WriteUint(msg.EncodedBodySize, buf, p) + p = WriteUint(msg.DecodedBodySize, buf, p) + p = WriteString(msg.URL, buf, p) + p = WriteString(msg.Initiator, buf, p) return buf[:p] } type ConnectionInformation struct { *meta Downlink uint64 -Type string + Type string } -func (msg *ConnectionInformation) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Type)) + +func (msg *ConnectionInformation) Encode() []byte { + buf := make([]byte, 21+len(msg.Type)) buf[0] = 54 p := 1 p = WriteUint(msg.Downlink, buf, p) -p = WriteString(msg.Type, buf, p) + p = WriteString(msg.Type, buf, p) return buf[:p] } @@ -966,8 +1052,9 @@ type SetPageVisibility struct { *meta hidden bool } -func (msg *SetPageVisibility) Encode() []byte{ - buf := make([]byte, 11 ) + +func (msg *SetPageVisibility) Encode() []byte { + buf := make([]byte, 11) buf[0] = 55 p := 1 p = WriteBoolean(msg.hidden, buf, p) @@ -976,159 +1063,166 @@ func (msg *SetPageVisibility) Encode() []byte{ type PerformanceTrackAggr struct { *meta - TimestampStart uint64 -TimestampEnd uint64 -MinFPS uint64 -AvgFPS uint64 -MaxFPS uint64 -MinCPU uint64 -AvgCPU uint64 -MaxCPU uint64 -MinTotalJSHeapSize uint64 -AvgTotalJSHeapSize uint64 -MaxTotalJSHeapSize uint64 -MinUsedJSHeapSize uint64 -AvgUsedJSHeapSize uint64 -MaxUsedJSHeapSize uint64 + TimestampStart uint64 + TimestampEnd uint64 + MinFPS uint64 + AvgFPS uint64 + MaxFPS uint64 + MinCPU uint64 + AvgCPU uint64 + MaxCPU uint64 + MinTotalJSHeapSize uint64 + AvgTotalJSHeapSize uint64 + MaxTotalJSHeapSize uint64 + MinUsedJSHeapSize uint64 + AvgUsedJSHeapSize uint64 + MaxUsedJSHeapSize uint64 } -func (msg *PerformanceTrackAggr) Encode() []byte{ - buf := make([]byte, 141 ) + +func (msg *PerformanceTrackAggr) Encode() []byte { + buf := make([]byte, 141) buf[0] = 56 p := 1 p = WriteUint(msg.TimestampStart, buf, p) -p = WriteUint(msg.TimestampEnd, buf, p) -p = WriteUint(msg.MinFPS, buf, p) -p = WriteUint(msg.AvgFPS, buf, p) -p = WriteUint(msg.MaxFPS, buf, p) -p = WriteUint(msg.MinCPU, buf, p) -p = WriteUint(msg.AvgCPU, buf, p) -p = WriteUint(msg.MaxCPU, buf, p) -p = WriteUint(msg.MinTotalJSHeapSize, buf, p) -p = WriteUint(msg.AvgTotalJSHeapSize, buf, p) -p = WriteUint(msg.MaxTotalJSHeapSize, buf, p) -p = WriteUint(msg.MinUsedJSHeapSize, buf, p) -p = WriteUint(msg.AvgUsedJSHeapSize, buf, p) -p = WriteUint(msg.MaxUsedJSHeapSize, buf, p) + p = WriteUint(msg.TimestampEnd, buf, p) + p = WriteUint(msg.MinFPS, buf, p) + p = WriteUint(msg.AvgFPS, buf, p) + p = WriteUint(msg.MaxFPS, buf, p) + p = WriteUint(msg.MinCPU, buf, p) + p = WriteUint(msg.AvgCPU, buf, p) + p = WriteUint(msg.MaxCPU, buf, p) + p = WriteUint(msg.MinTotalJSHeapSize, buf, p) + p = WriteUint(msg.AvgTotalJSHeapSize, buf, p) + p = WriteUint(msg.MaxTotalJSHeapSize, buf, p) + p = WriteUint(msg.MinUsedJSHeapSize, buf, p) + p = WriteUint(msg.AvgUsedJSHeapSize, buf, p) + p = WriteUint(msg.MaxUsedJSHeapSize, buf, p) return buf[:p] } type LongTask struct { *meta - Timestamp uint64 -Duration uint64 -Context uint64 -ContainerType uint64 -ContainerSrc string -ContainerId string -ContainerName string + Timestamp uint64 + Duration uint64 + Context uint64 + ContainerType uint64 + ContainerSrc string + ContainerId string + ContainerName string } -func (msg *LongTask) Encode() []byte{ - buf := make([]byte, 71 + len(msg.ContainerSrc)+ len(msg.ContainerId)+ len(msg.ContainerName)) + +func (msg *LongTask) Encode() []byte { + buf := make([]byte, 71+len(msg.ContainerSrc)+len(msg.ContainerId)+len(msg.ContainerName)) buf[0] = 59 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Duration, buf, p) -p = WriteUint(msg.Context, buf, p) -p = WriteUint(msg.ContainerType, buf, p) -p = WriteString(msg.ContainerSrc, buf, p) -p = WriteString(msg.ContainerId, buf, p) -p = WriteString(msg.ContainerName, buf, p) + p = WriteUint(msg.Duration, buf, p) + p = WriteUint(msg.Context, buf, p) + p = WriteUint(msg.ContainerType, buf, p) + p = WriteString(msg.ContainerSrc, buf, p) + p = WriteString(msg.ContainerId, buf, p) + p = WriteString(msg.ContainerName, buf, p) return buf[:p] } type SetNodeAttributeURLBased struct { *meta - ID uint64 -Name string -Value string -BaseURL string + ID uint64 + Name string + Value string + BaseURL string } -func (msg *SetNodeAttributeURLBased) Encode() []byte{ - buf := make([]byte, 41 + len(msg.Name)+ len(msg.Value)+ len(msg.BaseURL)) + +func (msg *SetNodeAttributeURLBased) Encode() []byte { + buf := make([]byte, 41+len(msg.Name)+len(msg.Value)+len(msg.BaseURL)) buf[0] = 60 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteString(msg.Name, buf, p) -p = WriteString(msg.Value, buf, p) -p = WriteString(msg.BaseURL, buf, p) + p = WriteString(msg.Name, buf, p) + p = WriteString(msg.Value, buf, p) + p = WriteString(msg.BaseURL, buf, p) return buf[:p] } type SetCSSDataURLBased struct { *meta - ID uint64 -Data string -BaseURL string + ID uint64 + Data string + BaseURL string } -func (msg *SetCSSDataURLBased) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Data)+ len(msg.BaseURL)) + +func (msg *SetCSSDataURLBased) Encode() []byte { + buf := make([]byte, 31+len(msg.Data)+len(msg.BaseURL)) buf[0] = 61 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteString(msg.Data, buf, p) -p = WriteString(msg.BaseURL, buf, p) + p = WriteString(msg.Data, buf, p) + p = WriteString(msg.BaseURL, buf, p) return buf[:p] } type IssueEvent struct { *meta - MessageID uint64 -Timestamp uint64 -Type string -ContextString string -Context string -Payload string + MessageID uint64 + Timestamp uint64 + Type string + ContextString string + Context string + Payload string } -func (msg *IssueEvent) Encode() []byte{ - buf := make([]byte, 61 + len(msg.Type)+ len(msg.ContextString)+ len(msg.Context)+ len(msg.Payload)) + +func (msg *IssueEvent) Encode() []byte { + buf := make([]byte, 61+len(msg.Type)+len(msg.ContextString)+len(msg.Context)+len(msg.Payload)) buf[0] = 62 p := 1 p = WriteUint(msg.MessageID, buf, p) -p = WriteUint(msg.Timestamp, buf, p) -p = WriteString(msg.Type, buf, p) -p = WriteString(msg.ContextString, buf, p) -p = WriteString(msg.Context, buf, p) -p = WriteString(msg.Payload, buf, p) + p = WriteUint(msg.Timestamp, buf, p) + p = WriteString(msg.Type, buf, p) + p = WriteString(msg.ContextString, buf, p) + p = WriteString(msg.Context, buf, p) + p = WriteString(msg.Payload, buf, p) return buf[:p] } type TechnicalInfo struct { *meta - Type string -Value string + Type string + Value string } -func (msg *TechnicalInfo) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Type)+ len(msg.Value)) + +func (msg *TechnicalInfo) Encode() []byte { + buf := make([]byte, 21+len(msg.Type)+len(msg.Value)) buf[0] = 63 p := 1 p = WriteString(msg.Type, buf, p) -p = WriteString(msg.Value, buf, p) + p = WriteString(msg.Value, buf, p) return buf[:p] } type CustomIssue struct { *meta - Name string -Payload string + Name string + Payload string } -func (msg *CustomIssue) Encode() []byte{ - buf := make([]byte, 21 + len(msg.Name)+ len(msg.Payload)) + +func (msg *CustomIssue) Encode() []byte { + buf := make([]byte, 21+len(msg.Name)+len(msg.Payload)) buf[0] = 64 p := 1 p = WriteString(msg.Name, buf, p) -p = WriteString(msg.Payload, buf, p) + p = WriteString(msg.Payload, buf, p) return buf[:p] } type PageClose struct { *meta - } -func (msg *PageClose) Encode() []byte{ - buf := make([]byte, 1 ) + +func (msg *PageClose) Encode() []byte { + buf := make([]byte, 1) buf[0] = 65 p := 1 - + return buf[:p] } @@ -1136,8 +1230,9 @@ type AssetCache struct { *meta URL string } -func (msg *AssetCache) Encode() []byte{ - buf := make([]byte, 11 + len(msg.URL)) + +func (msg *AssetCache) Encode() []byte { + buf := make([]byte, 11+len(msg.URL)) buf[0] = 66 p := 1 p = WriteString(msg.URL, buf, p) @@ -1146,97 +1241,102 @@ func (msg *AssetCache) Encode() []byte{ type CSSInsertRuleURLBased struct { *meta - ID uint64 -Rule string -Index uint64 -BaseURL string + ID uint64 + Rule string + Index uint64 + BaseURL string } -func (msg *CSSInsertRuleURLBased) Encode() []byte{ - buf := make([]byte, 41 + len(msg.Rule)+ len(msg.BaseURL)) + +func (msg *CSSInsertRuleURLBased) Encode() []byte { + buf := make([]byte, 41+len(msg.Rule)+len(msg.BaseURL)) buf[0] = 67 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteString(msg.Rule, buf, p) -p = WriteUint(msg.Index, buf, p) -p = WriteString(msg.BaseURL, buf, p) + p = WriteString(msg.Rule, buf, p) + p = WriteUint(msg.Index, buf, p) + p = WriteString(msg.BaseURL, buf, p) return buf[:p] } type MouseClick struct { *meta - ID uint64 -HesitationTime uint64 -Label string -Selector string + ID uint64 + HesitationTime uint64 + Label string + Selector string } -func (msg *MouseClick) Encode() []byte{ - buf := make([]byte, 41 + len(msg.Label)+ len(msg.Selector)) + +func (msg *MouseClick) Encode() []byte { + buf := make([]byte, 41+len(msg.Label)+len(msg.Selector)) buf[0] = 69 p := 1 p = WriteUint(msg.ID, buf, p) -p = WriteUint(msg.HesitationTime, buf, p) -p = WriteString(msg.Label, buf, p) -p = WriteString(msg.Selector, buf, p) + p = WriteUint(msg.HesitationTime, buf, p) + p = WriteString(msg.Label, buf, p) + p = WriteString(msg.Selector, buf, p) return buf[:p] } type CreateIFrameDocument struct { *meta FrameID uint64 -ID uint64 + ID uint64 } -func (msg *CreateIFrameDocument) Encode() []byte{ - buf := make([]byte, 21 ) + +func (msg *CreateIFrameDocument) Encode() []byte { + buf := make([]byte, 21) buf[0] = 70 p := 1 p = WriteUint(msg.FrameID, buf, p) -p = WriteUint(msg.ID, buf, p) + p = WriteUint(msg.ID, buf, p) return buf[:p] } type IOSBatchMeta struct { *meta - Timestamp uint64 -Length uint64 -FirstIndex uint64 + Timestamp uint64 + Length uint64 + FirstIndex uint64 } -func (msg *IOSBatchMeta) Encode() []byte{ - buf := make([]byte, 31 ) + +func (msg *IOSBatchMeta) Encode() []byte { + buf := make([]byte, 31) buf[0] = 107 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteUint(msg.FirstIndex, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteUint(msg.FirstIndex, buf, p) return buf[:p] } type IOSSessionStart struct { *meta - Timestamp uint64 -ProjectID uint64 -TrackerVersion string -RevID string -UserUUID string -UserOS string -UserOSVersion string -UserDevice string -UserDeviceType string -UserCountry string + Timestamp uint64 + ProjectID uint64 + TrackerVersion string + RevID string + UserUUID string + UserOS string + UserOSVersion string + UserDevice string + UserDeviceType string + UserCountry string } -func (msg *IOSSessionStart) Encode() []byte{ - buf := make([]byte, 101 + len(msg.TrackerVersion)+ len(msg.RevID)+ len(msg.UserUUID)+ len(msg.UserOS)+ len(msg.UserOSVersion)+ len(msg.UserDevice)+ len(msg.UserDeviceType)+ len(msg.UserCountry)) + +func (msg *IOSSessionStart) Encode() []byte { + buf := make([]byte, 101+len(msg.TrackerVersion)+len(msg.RevID)+len(msg.UserUUID)+len(msg.UserOS)+len(msg.UserOSVersion)+len(msg.UserDevice)+len(msg.UserDeviceType)+len(msg.UserCountry)) buf[0] = 90 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.ProjectID, buf, p) -p = WriteString(msg.TrackerVersion, buf, p) -p = WriteString(msg.RevID, buf, p) -p = WriteString(msg.UserUUID, buf, p) -p = WriteString(msg.UserOS, buf, p) -p = WriteString(msg.UserOSVersion, buf, p) -p = WriteString(msg.UserDevice, buf, p) -p = WriteString(msg.UserDeviceType, buf, p) -p = WriteString(msg.UserCountry, buf, p) + p = WriteUint(msg.ProjectID, buf, p) + p = WriteString(msg.TrackerVersion, buf, p) + p = WriteString(msg.RevID, buf, p) + p = WriteString(msg.UserUUID, buf, p) + p = WriteString(msg.UserOS, buf, p) + p = WriteString(msg.UserOSVersion, buf, p) + p = WriteString(msg.UserDevice, buf, p) + p = WriteString(msg.UserDeviceType, buf, p) + p = WriteString(msg.UserCountry, buf, p) return buf[:p] } @@ -1244,8 +1344,9 @@ type IOSSessionEnd struct { *meta Timestamp uint64 } -func (msg *IOSSessionEnd) Encode() []byte{ - buf := make([]byte, 11 ) + +func (msg *IOSSessionEnd) Encode() []byte { + buf := make([]byte, 11) buf[0] = 91 p := 1 p = WriteUint(msg.Timestamp, buf, p) @@ -1255,324 +1356,339 @@ func (msg *IOSSessionEnd) Encode() []byte{ type IOSMetadata struct { *meta Timestamp uint64 -Length uint64 -Key string -Value string + Length uint64 + Key string + Value string } -func (msg *IOSMetadata) Encode() []byte{ - buf := make([]byte, 41 + len(msg.Key)+ len(msg.Value)) + +func (msg *IOSMetadata) Encode() []byte { + buf := make([]byte, 41+len(msg.Key)+len(msg.Value)) buf[0] = 92 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Key, buf, p) -p = WriteString(msg.Value, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Key, buf, p) + p = WriteString(msg.Value, buf, p) return buf[:p] } type IOSCustomEvent struct { *meta Timestamp uint64 -Length uint64 -Name string -Payload string + Length uint64 + Name string + Payload string } -func (msg *IOSCustomEvent) Encode() []byte{ - buf := make([]byte, 41 + len(msg.Name)+ len(msg.Payload)) + +func (msg *IOSCustomEvent) Encode() []byte { + buf := make([]byte, 41+len(msg.Name)+len(msg.Payload)) buf[0] = 93 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Name, buf, p) -p = WriteString(msg.Payload, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Name, buf, p) + p = WriteString(msg.Payload, buf, p) return buf[:p] } type IOSUserID struct { *meta Timestamp uint64 -Length uint64 -Value string + Length uint64 + Value string } -func (msg *IOSUserID) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Value)) + +func (msg *IOSUserID) Encode() []byte { + buf := make([]byte, 31+len(msg.Value)) buf[0] = 94 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Value, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Value, buf, p) return buf[:p] } type IOSUserAnonymousID struct { *meta Timestamp uint64 -Length uint64 -Value string + Length uint64 + Value string } -func (msg *IOSUserAnonymousID) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Value)) + +func (msg *IOSUserAnonymousID) Encode() []byte { + buf := make([]byte, 31+len(msg.Value)) buf[0] = 95 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Value, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Value, buf, p) return buf[:p] } type IOSScreenChanges struct { *meta Timestamp uint64 -Length uint64 -X uint64 -Y uint64 -Width uint64 -Height uint64 + Length uint64 + X uint64 + Y uint64 + Width uint64 + Height uint64 } -func (msg *IOSScreenChanges) Encode() []byte{ - buf := make([]byte, 61 ) + +func (msg *IOSScreenChanges) Encode() []byte { + buf := make([]byte, 61) buf[0] = 96 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteUint(msg.X, buf, p) -p = WriteUint(msg.Y, buf, p) -p = WriteUint(msg.Width, buf, p) -p = WriteUint(msg.Height, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteUint(msg.X, buf, p) + p = WriteUint(msg.Y, buf, p) + p = WriteUint(msg.Width, buf, p) + p = WriteUint(msg.Height, buf, p) return buf[:p] } type IOSCrash struct { *meta - Timestamp uint64 -Length uint64 -Name string -Reason string -Stacktrace string + Timestamp uint64 + Length uint64 + Name string + Reason string + Stacktrace string } -func (msg *IOSCrash) Encode() []byte{ - buf := make([]byte, 51 + len(msg.Name)+ len(msg.Reason)+ len(msg.Stacktrace)) + +func (msg *IOSCrash) Encode() []byte { + buf := make([]byte, 51+len(msg.Name)+len(msg.Reason)+len(msg.Stacktrace)) buf[0] = 97 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Name, buf, p) -p = WriteString(msg.Reason, buf, p) -p = WriteString(msg.Stacktrace, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Name, buf, p) + p = WriteString(msg.Reason, buf, p) + p = WriteString(msg.Stacktrace, buf, p) return buf[:p] } type IOSScreenEnter struct { *meta Timestamp uint64 -Length uint64 -Title string -ViewName string + Length uint64 + Title string + ViewName string } -func (msg *IOSScreenEnter) Encode() []byte{ - buf := make([]byte, 41 + len(msg.Title)+ len(msg.ViewName)) + +func (msg *IOSScreenEnter) Encode() []byte { + buf := make([]byte, 41+len(msg.Title)+len(msg.ViewName)) buf[0] = 98 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Title, buf, p) -p = WriteString(msg.ViewName, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Title, buf, p) + p = WriteString(msg.ViewName, buf, p) return buf[:p] } type IOSScreenLeave struct { *meta Timestamp uint64 -Length uint64 -Title string -ViewName string + Length uint64 + Title string + ViewName string } -func (msg *IOSScreenLeave) Encode() []byte{ - buf := make([]byte, 41 + len(msg.Title)+ len(msg.ViewName)) + +func (msg *IOSScreenLeave) Encode() []byte { + buf := make([]byte, 41+len(msg.Title)+len(msg.ViewName)) buf[0] = 99 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Title, buf, p) -p = WriteString(msg.ViewName, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Title, buf, p) + p = WriteString(msg.ViewName, buf, p) return buf[:p] } type IOSClickEvent struct { *meta Timestamp uint64 -Length uint64 -Label string -X uint64 -Y uint64 + Length uint64 + Label string + X uint64 + Y uint64 } -func (msg *IOSClickEvent) Encode() []byte{ - buf := make([]byte, 51 + len(msg.Label)) + +func (msg *IOSClickEvent) Encode() []byte { + buf := make([]byte, 51+len(msg.Label)) buf[0] = 100 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Label, buf, p) -p = WriteUint(msg.X, buf, p) -p = WriteUint(msg.Y, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Label, buf, p) + p = WriteUint(msg.X, buf, p) + p = WriteUint(msg.Y, buf, p) return buf[:p] } type IOSInputEvent struct { *meta - Timestamp uint64 -Length uint64 -Value string -ValueMasked bool -Label string + Timestamp uint64 + Length uint64 + Value string + ValueMasked bool + Label string } -func (msg *IOSInputEvent) Encode() []byte{ - buf := make([]byte, 51 + len(msg.Value)+ len(msg.Label)) + +func (msg *IOSInputEvent) Encode() []byte { + buf := make([]byte, 51+len(msg.Value)+len(msg.Label)) buf[0] = 101 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Value, buf, p) -p = WriteBoolean(msg.ValueMasked, buf, p) -p = WriteString(msg.Label, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Value, buf, p) + p = WriteBoolean(msg.ValueMasked, buf, p) + p = WriteString(msg.Label, buf, p) return buf[:p] } type IOSPerformanceEvent struct { *meta Timestamp uint64 -Length uint64 -Name string -Value uint64 + Length uint64 + Name string + Value uint64 } -func (msg *IOSPerformanceEvent) Encode() []byte{ - buf := make([]byte, 41 + len(msg.Name)) + +func (msg *IOSPerformanceEvent) Encode() []byte { + buf := make([]byte, 41+len(msg.Name)) buf[0] = 102 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Name, buf, p) -p = WriteUint(msg.Value, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Name, buf, p) + p = WriteUint(msg.Value, buf, p) return buf[:p] } type IOSLog struct { *meta Timestamp uint64 -Length uint64 -Severity string -Content string + Length uint64 + Severity string + Content string } -func (msg *IOSLog) Encode() []byte{ - buf := make([]byte, 41 + len(msg.Severity)+ len(msg.Content)) + +func (msg *IOSLog) Encode() []byte { + buf := make([]byte, 41+len(msg.Severity)+len(msg.Content)) buf[0] = 103 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Severity, buf, p) -p = WriteString(msg.Content, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Severity, buf, p) + p = WriteString(msg.Content, buf, p) return buf[:p] } type IOSInternalError struct { *meta Timestamp uint64 -Length uint64 -Content string + Length uint64 + Content string } -func (msg *IOSInternalError) Encode() []byte{ - buf := make([]byte, 31 + len(msg.Content)) + +func (msg *IOSInternalError) Encode() []byte { + buf := make([]byte, 31+len(msg.Content)) buf[0] = 104 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteString(msg.Content, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteString(msg.Content, buf, p) return buf[:p] } type IOSNetworkCall struct { *meta Timestamp uint64 -Length uint64 -Duration uint64 -Headers string -Body string -URL string -Success bool -Method string -Status uint64 + Length uint64 + Duration uint64 + Headers string + Body string + URL string + Success bool + Method string + Status uint64 } -func (msg *IOSNetworkCall) Encode() []byte{ - buf := make([]byte, 91 + len(msg.Headers)+ len(msg.Body)+ len(msg.URL)+ len(msg.Method)) + +func (msg *IOSNetworkCall) Encode() []byte { + buf := make([]byte, 91+len(msg.Headers)+len(msg.Body)+len(msg.URL)+len(msg.Method)) buf[0] = 105 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteUint(msg.Length, buf, p) -p = WriteUint(msg.Duration, buf, p) -p = WriteString(msg.Headers, buf, p) -p = WriteString(msg.Body, buf, p) -p = WriteString(msg.URL, buf, p) -p = WriteBoolean(msg.Success, buf, p) -p = WriteString(msg.Method, buf, p) -p = WriteUint(msg.Status, buf, p) + p = WriteUint(msg.Length, buf, p) + p = WriteUint(msg.Duration, buf, p) + p = WriteString(msg.Headers, buf, p) + p = WriteString(msg.Body, buf, p) + p = WriteString(msg.URL, buf, p) + p = WriteBoolean(msg.Success, buf, p) + p = WriteString(msg.Method, buf, p) + p = WriteUint(msg.Status, buf, p) return buf[:p] } type IOSPerformanceAggregated struct { *meta TimestampStart uint64 -TimestampEnd uint64 -MinFPS uint64 -AvgFPS uint64 -MaxFPS uint64 -MinCPU uint64 -AvgCPU uint64 -MaxCPU uint64 -MinMemory uint64 -AvgMemory uint64 -MaxMemory uint64 -MinBattery uint64 -AvgBattery uint64 -MaxBattery uint64 + TimestampEnd uint64 + MinFPS uint64 + AvgFPS uint64 + MaxFPS uint64 + MinCPU uint64 + AvgCPU uint64 + MaxCPU uint64 + MinMemory uint64 + AvgMemory uint64 + MaxMemory uint64 + MinBattery uint64 + AvgBattery uint64 + MaxBattery uint64 } -func (msg *IOSPerformanceAggregated) Encode() []byte{ - buf := make([]byte, 141 ) + +func (msg *IOSPerformanceAggregated) Encode() []byte { + buf := make([]byte, 141) buf[0] = 110 p := 1 p = WriteUint(msg.TimestampStart, buf, p) -p = WriteUint(msg.TimestampEnd, buf, p) -p = WriteUint(msg.MinFPS, buf, p) -p = WriteUint(msg.AvgFPS, buf, p) -p = WriteUint(msg.MaxFPS, buf, p) -p = WriteUint(msg.MinCPU, buf, p) -p = WriteUint(msg.AvgCPU, buf, p) -p = WriteUint(msg.MaxCPU, buf, p) -p = WriteUint(msg.MinMemory, buf, p) -p = WriteUint(msg.AvgMemory, buf, p) -p = WriteUint(msg.MaxMemory, buf, p) -p = WriteUint(msg.MinBattery, buf, p) -p = WriteUint(msg.AvgBattery, buf, p) -p = WriteUint(msg.MaxBattery, buf, p) + p = WriteUint(msg.TimestampEnd, buf, p) + p = WriteUint(msg.MinFPS, buf, p) + p = WriteUint(msg.AvgFPS, buf, p) + p = WriteUint(msg.MaxFPS, buf, p) + p = WriteUint(msg.MinCPU, buf, p) + p = WriteUint(msg.AvgCPU, buf, p) + p = WriteUint(msg.MaxCPU, buf, p) + p = WriteUint(msg.MinMemory, buf, p) + p = WriteUint(msg.AvgMemory, buf, p) + p = WriteUint(msg.MaxMemory, buf, p) + p = WriteUint(msg.MinBattery, buf, p) + p = WriteUint(msg.AvgBattery, buf, p) + p = WriteUint(msg.MaxBattery, buf, p) return buf[:p] } type IOSIssueEvent struct { *meta - Timestamp uint64 -Type string -ContextString string -Context string -Payload string + Timestamp uint64 + Type string + ContextString string + Context string + Payload string } -func (msg *IOSIssueEvent) Encode() []byte{ - buf := make([]byte, 51 + len(msg.Type)+ len(msg.ContextString)+ len(msg.Context)+ len(msg.Payload)) + +func (msg *IOSIssueEvent) Encode() []byte { + buf := make([]byte, 51+len(msg.Type)+len(msg.ContextString)+len(msg.Context)+len(msg.Payload)) buf[0] = 111 p := 1 p = WriteUint(msg.Timestamp, buf, p) -p = WriteString(msg.Type, buf, p) -p = WriteString(msg.ContextString, buf, p) -p = WriteString(msg.Context, buf, p) -p = WriteString(msg.Payload, buf, p) + p = WriteString(msg.Type, buf, p) + p = WriteString(msg.ContextString, buf, p) + p = WriteString(msg.Context, buf, p) + p = WriteString(msg.Payload, buf, p) return buf[:p] } - diff --git a/backend/pkg/messages/read_message.go b/backend/pkg/messages/read_message.go index c226df728..31512c9c8 100644 --- a/backend/pkg/messages/read_message.go +++ b/backend/pkg/messages/read_message.go @@ -7,704 +7,1425 @@ import ( ) func ReadMessage(reader io.Reader) (Message, error) { - t, err := ReadUint(reader); + t, err := ReadUint(reader) if err != nil { return nil, err } switch t { - - case 80: - msg := &BatchMeta{ meta: &meta{ TypeID: 80} } - if msg.PageNo, err = ReadUint(reader); err != nil { return nil, err } -if msg.FirstIndex, err = ReadUint(reader); err != nil { return nil, err } -if msg.Timestamp, err = ReadInt(reader); err != nil { return nil, err } - return msg, nil - - case 0: - msg := &Timestamp{ meta: &meta{ TypeID: 0} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 1: - msg := &SessionStart{ meta: &meta{ TypeID: 1} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.ProjectID, err = ReadUint(reader); err != nil { return nil, err } -if msg.TrackerVersion, err = ReadString(reader); err != nil { return nil, err } -if msg.RevID, err = ReadString(reader); err != nil { return nil, err } -if msg.UserUUID, err = ReadString(reader); err != nil { return nil, err } -if msg.UserAgent, err = ReadString(reader); err != nil { return nil, err } -if msg.UserOS, err = ReadString(reader); err != nil { return nil, err } -if msg.UserOSVersion, err = ReadString(reader); err != nil { return nil, err } -if msg.UserBrowser, err = ReadString(reader); err != nil { return nil, err } -if msg.UserBrowserVersion, err = ReadString(reader); err != nil { return nil, err } -if msg.UserDevice, err = ReadString(reader); err != nil { return nil, err } -if msg.UserDeviceType, err = ReadString(reader); err != nil { return nil, err } -if msg.UserDeviceMemorySize, err = ReadUint(reader); err != nil { return nil, err } -if msg.UserDeviceHeapSize, err = ReadUint(reader); err != nil { return nil, err } -if msg.UserCountry, err = ReadString(reader); err != nil { return nil, err } -if msg.UserID, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 2: - msg := &SessionDisconnect{ meta: &meta{ TypeID: 2} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 3: - msg := &SessionEnd{ meta: &meta{ TypeID: 3} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 4: - msg := &SetPageLocation{ meta: &meta{ TypeID: 4} } - if msg.URL, err = ReadString(reader); err != nil { return nil, err } -if msg.Referrer, err = ReadString(reader); err != nil { return nil, err } -if msg.NavigationStart, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 5: - msg := &SetViewportSize{ meta: &meta{ TypeID: 5} } - if msg.Width, err = ReadUint(reader); err != nil { return nil, err } -if msg.Height, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 6: - msg := &SetViewportScroll{ meta: &meta{ TypeID: 6} } - if msg.X, err = ReadInt(reader); err != nil { return nil, err } -if msg.Y, err = ReadInt(reader); err != nil { return nil, err } - return msg, nil - - case 7: - msg := &CreateDocument{ meta: &meta{ TypeID: 7} } - - return msg, nil - - case 8: - msg := &CreateElementNode{ meta: &meta{ TypeID: 8} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.ParentID, err = ReadUint(reader); err != nil { return nil, err } -if msg.index, err = ReadUint(reader); err != nil { return nil, err } -if msg.Tag, err = ReadString(reader); err != nil { return nil, err } -if msg.SVG, err = ReadBoolean(reader); err != nil { return nil, err } - return msg, nil - - case 9: - msg := &CreateTextNode{ meta: &meta{ TypeID: 9} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.ParentID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Index, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 10: - msg := &MoveNode{ meta: &meta{ TypeID: 10} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.ParentID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Index, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 11: - msg := &RemoveNode{ meta: &meta{ TypeID: 11} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 12: - msg := &SetNodeAttribute{ meta: &meta{ TypeID: 12} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 13: - msg := &RemoveNodeAttribute{ meta: &meta{ TypeID: 13} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Name, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 14: - msg := &SetNodeData{ meta: &meta{ TypeID: 14} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Data, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 15: - msg := &SetCSSData{ meta: &meta{ TypeID: 15} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Data, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 16: - msg := &SetNodeScroll{ meta: &meta{ TypeID: 16} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.X, err = ReadInt(reader); err != nil { return nil, err } -if msg.Y, err = ReadInt(reader); err != nil { return nil, err } - return msg, nil - - case 17: - msg := &SetInputTarget{ meta: &meta{ TypeID: 17} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Label, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 18: - msg := &SetInputValue{ meta: &meta{ TypeID: 18} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } -if msg.Mask, err = ReadInt(reader); err != nil { return nil, err } - return msg, nil - - case 19: - msg := &SetInputChecked{ meta: &meta{ TypeID: 19} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Checked, err = ReadBoolean(reader); err != nil { return nil, err } - return msg, nil - - case 20: - msg := &MouseMove{ meta: &meta{ TypeID: 20} } - if msg.X, err = ReadUint(reader); err != nil { return nil, err } -if msg.Y, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 21: - msg := &MouseClickDepricated{ meta: &meta{ TypeID: 21} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.HesitationTime, err = ReadUint(reader); err != nil { return nil, err } -if msg.Label, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 22: - msg := &ConsoleLog{ meta: &meta{ TypeID: 22} } - if msg.Level, err = ReadString(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 23: - msg := &PageLoadTiming{ meta: &meta{ TypeID: 23} } - if msg.RequestStart, err = ReadUint(reader); err != nil { return nil, err } -if msg.ResponseStart, err = ReadUint(reader); err != nil { return nil, err } -if msg.ResponseEnd, err = ReadUint(reader); err != nil { return nil, err } -if msg.DomContentLoadedEventStart, err = ReadUint(reader); err != nil { return nil, err } -if msg.DomContentLoadedEventEnd, err = ReadUint(reader); err != nil { return nil, err } -if msg.LoadEventStart, err = ReadUint(reader); err != nil { return nil, err } -if msg.LoadEventEnd, err = ReadUint(reader); err != nil { return nil, err } -if msg.FirstPaint, err = ReadUint(reader); err != nil { return nil, err } -if msg.FirstContentfulPaint, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 24: - msg := &PageRenderTiming{ meta: &meta{ TypeID: 24} } - if msg.SpeedIndex, err = ReadUint(reader); err != nil { return nil, err } -if msg.VisuallyComplete, err = ReadUint(reader); err != nil { return nil, err } -if msg.TimeToInteractive, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 25: - msg := &JSException{ meta: &meta{ TypeID: 25} } - if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Message, err = ReadString(reader); err != nil { return nil, err } -if msg.Payload, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 26: - msg := &RawErrorEvent{ meta: &meta{ TypeID: 26} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Source, err = ReadString(reader); err != nil { return nil, err } -if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Message, err = ReadString(reader); err != nil { return nil, err } -if msg.Payload, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 27: - msg := &RawCustomEvent{ meta: &meta{ TypeID: 27} } - if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Payload, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 28: - msg := &UserID{ meta: &meta{ TypeID: 28} } - if msg.ID, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 29: - msg := &UserAnonymousID{ meta: &meta{ TypeID: 29} } - if msg.ID, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 30: - msg := &Metadata{ meta: &meta{ TypeID: 30} } - if msg.Key, err = ReadString(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 31: - msg := &PageEvent{ meta: &meta{ TypeID: 31} } - if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.URL, err = ReadString(reader); err != nil { return nil, err } -if msg.Referrer, err = ReadString(reader); err != nil { return nil, err } -if msg.Loaded, err = ReadBoolean(reader); err != nil { return nil, err } -if msg.RequestStart, err = ReadUint(reader); err != nil { return nil, err } -if msg.ResponseStart, err = ReadUint(reader); err != nil { return nil, err } -if msg.ResponseEnd, err = ReadUint(reader); err != nil { return nil, err } -if msg.DomContentLoadedEventStart, err = ReadUint(reader); err != nil { return nil, err } -if msg.DomContentLoadedEventEnd, err = ReadUint(reader); err != nil { return nil, err } -if msg.LoadEventStart, err = ReadUint(reader); err != nil { return nil, err } -if msg.LoadEventEnd, err = ReadUint(reader); err != nil { return nil, err } -if msg.FirstPaint, err = ReadUint(reader); err != nil { return nil, err } -if msg.FirstContentfulPaint, err = ReadUint(reader); err != nil { return nil, err } -if msg.SpeedIndex, err = ReadUint(reader); err != nil { return nil, err } -if msg.VisuallyComplete, err = ReadUint(reader); err != nil { return nil, err } -if msg.TimeToInteractive, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 32: - msg := &InputEvent{ meta: &meta{ TypeID: 32} } - if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } -if msg.ValueMasked, err = ReadBoolean(reader); err != nil { return nil, err } -if msg.Label, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 33: - msg := &ClickEvent{ meta: &meta{ TypeID: 33} } - if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.HesitationTime, err = ReadUint(reader); err != nil { return nil, err } -if msg.Label, err = ReadString(reader); err != nil { return nil, err } -if msg.Selector, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 34: - msg := &ErrorEvent{ meta: &meta{ TypeID: 34} } - if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Source, err = ReadString(reader); err != nil { return nil, err } -if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Message, err = ReadString(reader); err != nil { return nil, err } -if msg.Payload, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 35: - msg := &ResourceEvent{ meta: &meta{ TypeID: 35} } - if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } -if msg.TTFB, err = ReadUint(reader); err != nil { return nil, err } -if msg.HeaderSize, err = ReadUint(reader); err != nil { return nil, err } -if msg.EncodedBodySize, err = ReadUint(reader); err != nil { return nil, err } -if msg.DecodedBodySize, err = ReadUint(reader); err != nil { return nil, err } -if msg.URL, err = ReadString(reader); err != nil { return nil, err } -if msg.Type, err = ReadString(reader); err != nil { return nil, err } -if msg.Success, err = ReadBoolean(reader); err != nil { return nil, err } -if msg.Method, err = ReadString(reader); err != nil { return nil, err } -if msg.Status, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 36: - msg := &CustomEvent{ meta: &meta{ TypeID: 36} } - if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Payload, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 37: - msg := &CSSInsertRule{ meta: &meta{ TypeID: 37} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Rule, err = ReadString(reader); err != nil { return nil, err } -if msg.Index, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 38: - msg := &CSSDeleteRule{ meta: &meta{ TypeID: 38} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Index, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 39: - msg := &Fetch{ meta: &meta{ TypeID: 39} } - if msg.Method, err = ReadString(reader); err != nil { return nil, err } -if msg.URL, err = ReadString(reader); err != nil { return nil, err } -if msg.Request, err = ReadString(reader); err != nil { return nil, err } -if msg.Response, err = ReadString(reader); err != nil { return nil, err } -if msg.Status, err = ReadUint(reader); err != nil { return nil, err } -if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 40: - msg := &Profiler{ meta: &meta{ TypeID: 40} } - if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } -if msg.Args, err = ReadString(reader); err != nil { return nil, err } -if msg.Result, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 41: - msg := &OTable{ meta: &meta{ TypeID: 41} } - if msg.Key, err = ReadString(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 42: - msg := &StateAction{ meta: &meta{ TypeID: 42} } - if msg.Type, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 43: - msg := &StateActionEvent{ meta: &meta{ TypeID: 43} } - if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Type, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 44: - msg := &Redux{ meta: &meta{ TypeID: 44} } - if msg.Action, err = ReadString(reader); err != nil { return nil, err } -if msg.State, err = ReadString(reader); err != nil { return nil, err } -if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 45: - msg := &Vuex{ meta: &meta{ TypeID: 45} } - if msg.Mutation, err = ReadString(reader); err != nil { return nil, err } -if msg.State, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 46: - msg := &MobX{ meta: &meta{ TypeID: 46} } - if msg.Type, err = ReadString(reader); err != nil { return nil, err } -if msg.Payload, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 47: - msg := &NgRx{ meta: &meta{ TypeID: 47} } - if msg.Action, err = ReadString(reader); err != nil { return nil, err } -if msg.State, err = ReadString(reader); err != nil { return nil, err } -if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 48: - msg := &GraphQL{ meta: &meta{ TypeID: 48} } - if msg.OperationKind, err = ReadString(reader); err != nil { return nil, err } -if msg.OperationName, err = ReadString(reader); err != nil { return nil, err } -if msg.Variables, err = ReadString(reader); err != nil { return nil, err } -if msg.Response, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 49: - msg := &PerformanceTrack{ meta: &meta{ TypeID: 49} } - if msg.Frames, err = ReadInt(reader); err != nil { return nil, err } -if msg.Ticks, err = ReadInt(reader); err != nil { return nil, err } -if msg.TotalJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } -if msg.UsedJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 50: - msg := &GraphQLEvent{ meta: &meta{ TypeID: 50} } - if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Name, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 52: - msg := &DOMDrop{ meta: &meta{ TypeID: 52} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 53: - msg := &ResourceTiming{ meta: &meta{ TypeID: 53} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } -if msg.TTFB, err = ReadUint(reader); err != nil { return nil, err } -if msg.HeaderSize, err = ReadUint(reader); err != nil { return nil, err } -if msg.EncodedBodySize, err = ReadUint(reader); err != nil { return nil, err } -if msg.DecodedBodySize, err = ReadUint(reader); err != nil { return nil, err } -if msg.URL, err = ReadString(reader); err != nil { return nil, err } -if msg.Initiator, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 54: - msg := &ConnectionInformation{ meta: &meta{ TypeID: 54} } - if msg.Downlink, err = ReadUint(reader); err != nil { return nil, err } -if msg.Type, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 55: - msg := &SetPageVisibility{ meta: &meta{ TypeID: 55} } - if msg.hidden, err = ReadBoolean(reader); err != nil { return nil, err } - return msg, nil - - case 56: - msg := &PerformanceTrackAggr{ meta: &meta{ TypeID: 56} } - if msg.TimestampStart, err = ReadUint(reader); err != nil { return nil, err } -if msg.TimestampEnd, err = ReadUint(reader); err != nil { return nil, err } -if msg.MinFPS, err = ReadUint(reader); err != nil { return nil, err } -if msg.AvgFPS, err = ReadUint(reader); err != nil { return nil, err } -if msg.MaxFPS, err = ReadUint(reader); err != nil { return nil, err } -if msg.MinCPU, err = ReadUint(reader); err != nil { return nil, err } -if msg.AvgCPU, err = ReadUint(reader); err != nil { return nil, err } -if msg.MaxCPU, err = ReadUint(reader); err != nil { return nil, err } -if msg.MinTotalJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } -if msg.AvgTotalJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } -if msg.MaxTotalJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } -if msg.MinUsedJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } -if msg.AvgUsedJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } -if msg.MaxUsedJSHeapSize, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 59: - msg := &LongTask{ meta: &meta{ TypeID: 59} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } -if msg.Context, err = ReadUint(reader); err != nil { return nil, err } -if msg.ContainerType, err = ReadUint(reader); err != nil { return nil, err } -if msg.ContainerSrc, err = ReadString(reader); err != nil { return nil, err } -if msg.ContainerId, err = ReadString(reader); err != nil { return nil, err } -if msg.ContainerName, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 60: - msg := &SetNodeAttributeURLBased{ meta: &meta{ TypeID: 60} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } -if msg.BaseURL, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 61: - msg := &SetCSSDataURLBased{ meta: &meta{ TypeID: 61} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Data, err = ReadString(reader); err != nil { return nil, err } -if msg.BaseURL, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 62: - msg := &IssueEvent{ meta: &meta{ TypeID: 62} } - if msg.MessageID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Type, err = ReadString(reader); err != nil { return nil, err } -if msg.ContextString, err = ReadString(reader); err != nil { return nil, err } -if msg.Context, err = ReadString(reader); err != nil { return nil, err } -if msg.Payload, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 63: - msg := &TechnicalInfo{ meta: &meta{ TypeID: 63} } - if msg.Type, err = ReadString(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 64: - msg := &CustomIssue{ meta: &meta{ TypeID: 64} } - if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Payload, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 65: - msg := &PageClose{ meta: &meta{ TypeID: 65} } - - return msg, nil - - case 66: - msg := &AssetCache{ meta: &meta{ TypeID: 66} } - if msg.URL, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 67: - msg := &CSSInsertRuleURLBased{ meta: &meta{ TypeID: 67} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.Rule, err = ReadString(reader); err != nil { return nil, err } -if msg.Index, err = ReadUint(reader); err != nil { return nil, err } -if msg.BaseURL, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 69: - msg := &MouseClick{ meta: &meta{ TypeID: 69} } - if msg.ID, err = ReadUint(reader); err != nil { return nil, err } -if msg.HesitationTime, err = ReadUint(reader); err != nil { return nil, err } -if msg.Label, err = ReadString(reader); err != nil { return nil, err } -if msg.Selector, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 70: - msg := &CreateIFrameDocument{ meta: &meta{ TypeID: 70} } - if msg.FrameID, err = ReadUint(reader); err != nil { return nil, err } -if msg.ID, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 107: - msg := &IOSBatchMeta{ meta: &meta{ TypeID: 107} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.FirstIndex, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 90: - msg := &IOSSessionStart{ meta: &meta{ TypeID: 90} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.ProjectID, err = ReadUint(reader); err != nil { return nil, err } -if msg.TrackerVersion, err = ReadString(reader); err != nil { return nil, err } -if msg.RevID, err = ReadString(reader); err != nil { return nil, err } -if msg.UserUUID, err = ReadString(reader); err != nil { return nil, err } -if msg.UserOS, err = ReadString(reader); err != nil { return nil, err } -if msg.UserOSVersion, err = ReadString(reader); err != nil { return nil, err } -if msg.UserDevice, err = ReadString(reader); err != nil { return nil, err } -if msg.UserDeviceType, err = ReadString(reader); err != nil { return nil, err } -if msg.UserCountry, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 91: - msg := &IOSSessionEnd{ meta: &meta{ TypeID: 91} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 92: - msg := &IOSMetadata{ meta: &meta{ TypeID: 92} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Key, err = ReadString(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 93: - msg := &IOSCustomEvent{ meta: &meta{ TypeID: 93} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Payload, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 94: - msg := &IOSUserID{ meta: &meta{ TypeID: 94} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 95: - msg := &IOSUserAnonymousID{ meta: &meta{ TypeID: 95} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 96: - msg := &IOSScreenChanges{ meta: &meta{ TypeID: 96} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.X, err = ReadUint(reader); err != nil { return nil, err } -if msg.Y, err = ReadUint(reader); err != nil { return nil, err } -if msg.Width, err = ReadUint(reader); err != nil { return nil, err } -if msg.Height, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 97: - msg := &IOSCrash{ meta: &meta{ TypeID: 97} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Reason, err = ReadString(reader); err != nil { return nil, err } -if msg.Stacktrace, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 98: - msg := &IOSScreenEnter{ meta: &meta{ TypeID: 98} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Title, err = ReadString(reader); err != nil { return nil, err } -if msg.ViewName, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 99: - msg := &IOSScreenLeave{ meta: &meta{ TypeID: 99} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Title, err = ReadString(reader); err != nil { return nil, err } -if msg.ViewName, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 100: - msg := &IOSClickEvent{ meta: &meta{ TypeID: 100} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Label, err = ReadString(reader); err != nil { return nil, err } -if msg.X, err = ReadUint(reader); err != nil { return nil, err } -if msg.Y, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 101: - msg := &IOSInputEvent{ meta: &meta{ TypeID: 101} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Value, err = ReadString(reader); err != nil { return nil, err } -if msg.ValueMasked, err = ReadBoolean(reader); err != nil { return nil, err } -if msg.Label, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 102: - msg := &IOSPerformanceEvent{ meta: &meta{ TypeID: 102} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Name, err = ReadString(reader); err != nil { return nil, err } -if msg.Value, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 103: - msg := &IOSLog{ meta: &meta{ TypeID: 103} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Severity, err = ReadString(reader); err != nil { return nil, err } -if msg.Content, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 104: - msg := &IOSInternalError{ meta: &meta{ TypeID: 104} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Content, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - - case 105: - msg := &IOSNetworkCall{ meta: &meta{ TypeID: 105} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Length, err = ReadUint(reader); err != nil { return nil, err } -if msg.Duration, err = ReadUint(reader); err != nil { return nil, err } -if msg.Headers, err = ReadString(reader); err != nil { return nil, err } -if msg.Body, err = ReadString(reader); err != nil { return nil, err } -if msg.URL, err = ReadString(reader); err != nil { return nil, err } -if msg.Success, err = ReadBoolean(reader); err != nil { return nil, err } -if msg.Method, err = ReadString(reader); err != nil { return nil, err } -if msg.Status, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 110: - msg := &IOSPerformanceAggregated{ meta: &meta{ TypeID: 110} } - if msg.TimestampStart, err = ReadUint(reader); err != nil { return nil, err } -if msg.TimestampEnd, err = ReadUint(reader); err != nil { return nil, err } -if msg.MinFPS, err = ReadUint(reader); err != nil { return nil, err } -if msg.AvgFPS, err = ReadUint(reader); err != nil { return nil, err } -if msg.MaxFPS, err = ReadUint(reader); err != nil { return nil, err } -if msg.MinCPU, err = ReadUint(reader); err != nil { return nil, err } -if msg.AvgCPU, err = ReadUint(reader); err != nil { return nil, err } -if msg.MaxCPU, err = ReadUint(reader); err != nil { return nil, err } -if msg.MinMemory, err = ReadUint(reader); err != nil { return nil, err } -if msg.AvgMemory, err = ReadUint(reader); err != nil { return nil, err } -if msg.MaxMemory, err = ReadUint(reader); err != nil { return nil, err } -if msg.MinBattery, err = ReadUint(reader); err != nil { return nil, err } -if msg.AvgBattery, err = ReadUint(reader); err != nil { return nil, err } -if msg.MaxBattery, err = ReadUint(reader); err != nil { return nil, err } - return msg, nil - - case 111: - msg := &IOSIssueEvent{ meta: &meta{ TypeID: 111} } - if msg.Timestamp, err = ReadUint(reader); err != nil { return nil, err } -if msg.Type, err = ReadString(reader); err != nil { return nil, err } -if msg.ContextString, err = ReadString(reader); err != nil { return nil, err } -if msg.Context, err = ReadString(reader); err != nil { return nil, err } -if msg.Payload, err = ReadString(reader); err != nil { return nil, err } - return msg, nil - + + case 80: + msg := &BatchMeta{meta: &meta{TypeID: 80}} + if msg.PageNo, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.FirstIndex, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadInt(reader); err != nil { + return nil, err + } + return msg, nil + + case 0: + msg := &Timestamp{meta: &meta{TypeID: 0}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 1: + msg := &SessionStart{meta: &meta{TypeID: 1}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ProjectID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.TrackerVersion, err = ReadString(reader); err != nil { + return nil, err + } + if msg.RevID, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserUUID, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserAgent, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserOS, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserOSVersion, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserBrowser, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserBrowserVersion, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserDevice, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserDeviceType, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserDeviceMemorySize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.UserDeviceHeapSize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.UserCountry, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserID, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 2: + msg := &SessionDisconnect{meta: &meta{TypeID: 2}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 3: + msg := &SessionEnd{meta: &meta{TypeID: 3}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 4: + msg := &SetPageLocation{meta: &meta{TypeID: 4}} + if msg.URL, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Referrer, err = ReadString(reader); err != nil { + return nil, err + } + if msg.NavigationStart, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 5: + msg := &SetViewportSize{meta: &meta{TypeID: 5}} + if msg.Width, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Height, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 6: + msg := &SetViewportScroll{meta: &meta{TypeID: 6}} + if msg.X, err = ReadInt(reader); err != nil { + return nil, err + } + if msg.Y, err = ReadInt(reader); err != nil { + return nil, err + } + return msg, nil + + case 7: + msg := &CreateDocument{meta: &meta{TypeID: 7}} + + return msg, nil + + case 8: + msg := &CreateElementNode{meta: &meta{TypeID: 8}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ParentID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.index, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Tag, err = ReadString(reader); err != nil { + return nil, err + } + if msg.SVG, err = ReadBoolean(reader); err != nil { + return nil, err + } + return msg, nil + + case 9: + msg := &CreateTextNode{meta: &meta{TypeID: 9}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ParentID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Index, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 10: + msg := &MoveNode{meta: &meta{TypeID: 10}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ParentID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Index, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 11: + msg := &RemoveNode{meta: &meta{TypeID: 11}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 12: + msg := &SetNodeAttribute{meta: &meta{TypeID: 12}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 13: + msg := &RemoveNodeAttribute{meta: &meta{TypeID: 13}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 14: + msg := &SetNodeData{meta: &meta{TypeID: 14}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Data, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 15: + msg := &SetCSSData{meta: &meta{TypeID: 15}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Data, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 16: + msg := &SetNodeScroll{meta: &meta{TypeID: 16}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.X, err = ReadInt(reader); err != nil { + return nil, err + } + if msg.Y, err = ReadInt(reader); err != nil { + return nil, err + } + return msg, nil + + case 17: + msg := &SetInputTarget{meta: &meta{TypeID: 17}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Label, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 18: + msg := &SetInputValue{meta: &meta{TypeID: 18}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Mask, err = ReadInt(reader); err != nil { + return nil, err + } + return msg, nil + + case 19: + msg := &SetInputChecked{meta: &meta{TypeID: 19}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Checked, err = ReadBoolean(reader); err != nil { + return nil, err + } + return msg, nil + + case 20: + msg := &MouseMove{meta: &meta{TypeID: 20}} + if msg.X, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Y, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 21: + msg := &MouseClickDepricated{meta: &meta{TypeID: 21}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.HesitationTime, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Label, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 22: + msg := &ConsoleLog{meta: &meta{TypeID: 22}} + if msg.Level, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 23: + msg := &PageLoadTiming{meta: &meta{TypeID: 23}} + if msg.RequestStart, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ResponseStart, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ResponseEnd, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.DomContentLoadedEventStart, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.DomContentLoadedEventEnd, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.LoadEventStart, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.LoadEventEnd, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.FirstPaint, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.FirstContentfulPaint, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 24: + msg := &PageRenderTiming{meta: &meta{TypeID: 24}} + if msg.SpeedIndex, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.VisuallyComplete, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.TimeToInteractive, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 25: + msg := &JSException{meta: &meta{TypeID: 25}} + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Message, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Payload, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 26: + msg := &RawErrorEvent{meta: &meta{TypeID: 26}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Source, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Message, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Payload, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 27: + msg := &RawCustomEvent{meta: &meta{TypeID: 27}} + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Payload, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 28: + msg := &UserID{meta: &meta{TypeID: 28}} + if msg.ID, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 29: + msg := &UserAnonymousID{meta: &meta{TypeID: 29}} + if msg.ID, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 30: + msg := &Metadata{meta: &meta{TypeID: 30}} + if msg.Key, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 31: + msg := &PageEvent{meta: &meta{TypeID: 31}} + if msg.MessageID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.URL, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Referrer, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Loaded, err = ReadBoolean(reader); err != nil { + return nil, err + } + if msg.RequestStart, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ResponseStart, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ResponseEnd, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.DomContentLoadedEventStart, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.DomContentLoadedEventEnd, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.LoadEventStart, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.LoadEventEnd, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.FirstPaint, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.FirstContentfulPaint, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.SpeedIndex, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.VisuallyComplete, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.TimeToInteractive, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 32: + msg := &InputEvent{meta: &meta{TypeID: 32}} + if msg.MessageID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + if msg.ValueMasked, err = ReadBoolean(reader); err != nil { + return nil, err + } + if msg.Label, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 33: + msg := &ClickEvent{meta: &meta{TypeID: 33}} + if msg.MessageID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.HesitationTime, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Label, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Selector, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 34: + msg := &ErrorEvent{meta: &meta{TypeID: 34}} + if msg.MessageID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Source, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Message, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Payload, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 35: + msg := &ResourceEvent{meta: &meta{TypeID: 35}} + if msg.MessageID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Duration, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.TTFB, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.HeaderSize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.EncodedBodySize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.DecodedBodySize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.URL, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Type, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Success, err = ReadBoolean(reader); err != nil { + return nil, err + } + if msg.Method, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Status, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 36: + msg := &CustomEvent{meta: &meta{TypeID: 36}} + if msg.MessageID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Payload, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 37: + msg := &CSSInsertRule{meta: &meta{TypeID: 37}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Rule, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Index, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 38: + msg := &CSSDeleteRule{meta: &meta{TypeID: 38}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Index, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 39: + msg := &Fetch{meta: &meta{TypeID: 39}} + if msg.Method, err = ReadString(reader); err != nil { + return nil, err + } + if msg.URL, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Request, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Response, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Status, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Duration, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 40: + msg := &Profiler{meta: &meta{TypeID: 40}} + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Duration, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Args, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Result, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 41: + msg := &OTable{meta: &meta{TypeID: 41}} + if msg.Key, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 42: + msg := &StateAction{meta: &meta{TypeID: 42}} + if msg.Type, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 43: + msg := &StateActionEvent{meta: &meta{TypeID: 43}} + if msg.MessageID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Type, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 44: + msg := &Redux{meta: &meta{TypeID: 44}} + if msg.Action, err = ReadString(reader); err != nil { + return nil, err + } + if msg.State, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Duration, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 45: + msg := &Vuex{meta: &meta{TypeID: 45}} + if msg.Mutation, err = ReadString(reader); err != nil { + return nil, err + } + if msg.State, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 46: + msg := &MobX{meta: &meta{TypeID: 46}} + if msg.Type, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Payload, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 47: + msg := &NgRx{meta: &meta{TypeID: 47}} + if msg.Action, err = ReadString(reader); err != nil { + return nil, err + } + if msg.State, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Duration, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 48: + msg := &GraphQL{meta: &meta{TypeID: 48}} + if msg.OperationKind, err = ReadString(reader); err != nil { + return nil, err + } + if msg.OperationName, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Variables, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Response, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 49: + msg := &PerformanceTrack{meta: &meta{TypeID: 49}} + if msg.Frames, err = ReadInt(reader); err != nil { + return nil, err + } + if msg.Ticks, err = ReadInt(reader); err != nil { + return nil, err + } + if msg.TotalJSHeapSize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.UsedJSHeapSize, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 50: + msg := &GraphQLEvent{meta: &meta{TypeID: 50}} + if msg.MessageID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.OperationKind, err = ReadString(reader); err != nil { + return nil, err + } + if msg.OperationName, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Variables, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Response, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 51: + msg := &FetchEvent{meta: &meta{TypeID: 51}} + if msg.MessageID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Method, err = ReadString(reader); err != nil { + return nil, err + } + if msg.URL, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Request, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Response, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Status, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Duration, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 52: + msg := &DOMDrop{meta: &meta{TypeID: 52}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 53: + msg := &ResourceTiming{meta: &meta{TypeID: 53}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Duration, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.TTFB, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.HeaderSize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.EncodedBodySize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.DecodedBodySize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.URL, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Initiator, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 54: + msg := &ConnectionInformation{meta: &meta{TypeID: 54}} + if msg.Downlink, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Type, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 55: + msg := &SetPageVisibility{meta: &meta{TypeID: 55}} + if msg.hidden, err = ReadBoolean(reader); err != nil { + return nil, err + } + return msg, nil + + case 56: + msg := &PerformanceTrackAggr{meta: &meta{TypeID: 56}} + if msg.TimestampStart, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.TimestampEnd, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MinFPS, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.AvgFPS, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MaxFPS, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MinCPU, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.AvgCPU, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MaxCPU, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MinTotalJSHeapSize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.AvgTotalJSHeapSize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MaxTotalJSHeapSize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MinUsedJSHeapSize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.AvgUsedJSHeapSize, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MaxUsedJSHeapSize, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 59: + msg := &LongTask{meta: &meta{TypeID: 59}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Duration, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Context, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ContainerType, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ContainerSrc, err = ReadString(reader); err != nil { + return nil, err + } + if msg.ContainerId, err = ReadString(reader); err != nil { + return nil, err + } + if msg.ContainerName, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 60: + msg := &SetNodeAttributeURLBased{meta: &meta{TypeID: 60}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + if msg.BaseURL, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 61: + msg := &SetCSSDataURLBased{meta: &meta{TypeID: 61}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Data, err = ReadString(reader); err != nil { + return nil, err + } + if msg.BaseURL, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 62: + msg := &IssueEvent{meta: &meta{TypeID: 62}} + if msg.MessageID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Type, err = ReadString(reader); err != nil { + return nil, err + } + if msg.ContextString, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Context, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Payload, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 63: + msg := &TechnicalInfo{meta: &meta{TypeID: 63}} + if msg.Type, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 64: + msg := &CustomIssue{meta: &meta{TypeID: 64}} + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Payload, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 65: + msg := &PageClose{meta: &meta{TypeID: 65}} + + return msg, nil + + case 66: + msg := &AssetCache{meta: &meta{TypeID: 66}} + if msg.URL, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 67: + msg := &CSSInsertRuleURLBased{meta: &meta{TypeID: 67}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Rule, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Index, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.BaseURL, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 69: + msg := &MouseClick{meta: &meta{TypeID: 69}} + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.HesitationTime, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Label, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Selector, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 70: + msg := &CreateIFrameDocument{meta: &meta{TypeID: 70}} + if msg.FrameID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ID, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 107: + msg := &IOSBatchMeta{meta: &meta{TypeID: 107}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.FirstIndex, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 90: + msg := &IOSSessionStart{meta: &meta{TypeID: 90}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.ProjectID, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.TrackerVersion, err = ReadString(reader); err != nil { + return nil, err + } + if msg.RevID, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserUUID, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserOS, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserOSVersion, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserDevice, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserDeviceType, err = ReadString(reader); err != nil { + return nil, err + } + if msg.UserCountry, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 91: + msg := &IOSSessionEnd{meta: &meta{TypeID: 91}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 92: + msg := &IOSMetadata{meta: &meta{TypeID: 92}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Key, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 93: + msg := &IOSCustomEvent{meta: &meta{TypeID: 93}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Payload, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 94: + msg := &IOSUserID{meta: &meta{TypeID: 94}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 95: + msg := &IOSUserAnonymousID{meta: &meta{TypeID: 95}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 96: + msg := &IOSScreenChanges{meta: &meta{TypeID: 96}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.X, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Y, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Width, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Height, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 97: + msg := &IOSCrash{meta: &meta{TypeID: 97}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Reason, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Stacktrace, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 98: + msg := &IOSScreenEnter{meta: &meta{TypeID: 98}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Title, err = ReadString(reader); err != nil { + return nil, err + } + if msg.ViewName, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 99: + msg := &IOSScreenLeave{meta: &meta{TypeID: 99}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Title, err = ReadString(reader); err != nil { + return nil, err + } + if msg.ViewName, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 100: + msg := &IOSClickEvent{meta: &meta{TypeID: 100}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Label, err = ReadString(reader); err != nil { + return nil, err + } + if msg.X, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Y, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 101: + msg := &IOSInputEvent{meta: &meta{TypeID: 101}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadString(reader); err != nil { + return nil, err + } + if msg.ValueMasked, err = ReadBoolean(reader); err != nil { + return nil, err + } + if msg.Label, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 102: + msg := &IOSPerformanceEvent{meta: &meta{TypeID: 102}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Name, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Value, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 103: + msg := &IOSLog{meta: &meta{TypeID: 103}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Severity, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Content, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 104: + msg := &IOSInternalError{meta: &meta{TypeID: 104}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Content, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + + case 105: + msg := &IOSNetworkCall{meta: &meta{TypeID: 105}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Length, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Duration, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Headers, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Body, err = ReadString(reader); err != nil { + return nil, err + } + if msg.URL, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Success, err = ReadBoolean(reader); err != nil { + return nil, err + } + if msg.Method, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Status, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 110: + msg := &IOSPerformanceAggregated{meta: &meta{TypeID: 110}} + if msg.TimestampStart, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.TimestampEnd, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MinFPS, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.AvgFPS, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MaxFPS, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MinCPU, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.AvgCPU, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MaxCPU, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MinMemory, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.AvgMemory, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MaxMemory, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MinBattery, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.AvgBattery, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.MaxBattery, err = ReadUint(reader); err != nil { + return nil, err + } + return msg, nil + + case 111: + msg := &IOSIssueEvent{meta: &meta{TypeID: 111}} + if msg.Timestamp, err = ReadUint(reader); err != nil { + return nil, err + } + if msg.Type, err = ReadString(reader); err != nil { + return nil, err + } + if msg.ContextString, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Context, err = ReadString(reader); err != nil { + return nil, err + } + if msg.Payload, err = ReadString(reader); err != nil { + return nil, err + } + return msg, nil + } return nil, fmt.Errorf("Unknown message code: %v", t) } diff --git a/backend/services/db/messages.go b/backend/services/db/messages.go index 6aa4ac076..d3e4ae1ed 100644 --- a/backend/services/db/messages.go +++ b/backend/services/db/messages.go @@ -11,7 +11,7 @@ func insertMessage(sessionID uint64, msg Message) error { return pg.InsertMetadata(sessionID, m) case *IssueEvent: return pg.InsertIssueEvent(sessionID, m) - //TODO: message adapter (transformer) (at the level of pkg/message) for types: + //TODO: message adapter (transformer) (at the level of pkg/message) for types: // case *IOSMetadata, *IOSIssueEvent and others // Web @@ -30,14 +30,18 @@ func insertMessage(sessionID uint64, msg Message) error { case *InputEvent: return pg.InsertWebInputEvent(sessionID, m) // Unique Web messages - case *ResourceEvent: - return pg.InsertWebResourceEvent(sessionID, m) + // case *ResourceEvent: + // return pg.InsertWebResourceEvent(sessionID, m) case *PageEvent: return pg.InsertWebPageEvent(sessionID, m) - case *ErrorEvent: + case *ErrorEvent: return pg.InsertWebErrorEvent(sessionID, m) + case *FetchEvent: + return pg.InsertWebFetchEvent(sessionID, m) + case *GraphQLEvent: + return pg.InsertWebGraphQLEvent(sessionID, m) - // IOS + // IOS case *IOSSessionStart: return pg.InsertIOSSessionStart(sessionID, m) case *IOSSessionEnd: @@ -57,8 +61,8 @@ func insertMessage(sessionID uint64, msg Message) error { return pg.InsertIOSNetworkCall(sessionID, m) case *IOSScreenEnter: return pg.InsertIOSScreenEnter(sessionID, m) - case *IOSCrash: + case *IOSCrash: return pg.InsertIOSCrash(sessionID, m) } - return nil // "Not implemented" -} \ No newline at end of file + return nil // "Not implemented" +} diff --git a/backend/services/ender/builder/builder.go b/backend/services/ender/builder/builder.go index c0690a3ad..e36bdcbe3 100644 --- a/backend/services/ender/builder/builder.go +++ b/backend/services/ender/builder/builder.go @@ -41,33 +41,32 @@ func getResourceType(initiator string, URL string) string { } type builder struct { - readyMsgs []Message - timestamp uint64 - lastProcessedTimestamp int64 - peBuilder *pageEventBuilder - ptaBuilder *performanceTrackAggrBuilder - ieBuilder *inputEventBuilder - ciFinder *cpuIssueFinder - miFinder *memoryIssueFinder - ddDetector *domDropDetector - crDetector *clickRageDetector - dcDetector *deadClickDetector - integrationsWaiting bool - + readyMsgs []Message + timestamp uint64 + lastProcessedTimestamp int64 + peBuilder *pageEventBuilder + ptaBuilder *performanceTrackAggrBuilder + ieBuilder *inputEventBuilder + ciFinder *cpuIssueFinder + miFinder *memoryIssueFinder + ddDetector *domDropDetector + crDetector *clickRageDetector + dcDetector *deadClickDetector + integrationsWaiting bool sid uint64 } func NewBuilder() *builder { return &builder{ - peBuilder: &pageEventBuilder{}, - ptaBuilder: &performanceTrackAggrBuilder{}, - ieBuilder: NewInputEventBuilder(), - ciFinder: &cpuIssueFinder{}, - miFinder: &memoryIssueFinder{}, - ddDetector: &domDropDetector{}, - crDetector: &clickRageDetector{}, - dcDetector: &deadClickDetector{}, + peBuilder: &pageEventBuilder{}, + ptaBuilder: &performanceTrackAggrBuilder{}, + ieBuilder: NewInputEventBuilder(), + ciFinder: &cpuIssueFinder{}, + miFinder: &memoryIssueFinder{}, + ddDetector: &domDropDetector{}, + crDetector: &clickRageDetector{}, + dcDetector: &deadClickDetector{}, integrationsWaiting: true, } } @@ -115,15 +114,14 @@ func (b *builder) handleMessage(message Message, messageID uint64) { b.timestamp = timestamp } - b.lastProcessedTimestamp = time.Now().UnixNano()/1e6 - + b.lastProcessedTimestamp = time.Now().UnixNano() / 1e6 // Might happen before the first timestamp. switch msg := message.(type) { case *SessionStart, - *Metadata, - *UserID, - *UserAnonymousID: + *Metadata, + *UserID, + *UserAnonymousID: b.appendReadyMessage(msg) case *RawErrorEvent: b.appendReadyMessage(&ErrorEvent{ @@ -220,14 +218,14 @@ func (b *builder) handleMessage(message Message, messageID uint64) { Type: tp, Success: success, }) - if !success && tp == "fetch" { - b.appendReadyMessage(&IssueEvent{ - Type: "bad_request", - MessageID: messageID, - Timestamp: msg.Timestamp, + if !success && tp == "fetch" { + b.appendReadyMessage(&IssueEvent{ + Type: "bad_request", + MessageID: messageID, + Timestamp: msg.Timestamp, ContextString: msg.URL, - Context: "", - Payload: "", + Context: "", + Payload: "", }) } case *RawCustomEvent: @@ -239,22 +237,31 @@ func (b *builder) handleMessage(message Message, messageID uint64) { }) case *CustomIssue: b.appendReadyMessage(&IssueEvent{ - Type: "custom", - Timestamp: b.timestamp, - MessageID: messageID, + Type: "custom", + Timestamp: b.timestamp, + MessageID: messageID, ContextString: msg.Name, - Payload: msg.Payload, + Payload: msg.Payload, }) case *Fetch: - b.appendReadyMessage(&ResourceEvent{ + b.appendReadyMessage(&FetchEvent{ MessageID: messageID, Timestamp: msg.Timestamp, - Duration: msg.Duration, - URL: msg.URL, - Type: "fetch", - Success: msg.Status < 300, Method: msg.Method, + URL: msg.URL, + Request: msg.Request, + Response: msg.Response, Status: msg.Status, + Duration: msg.Duration, + }) + case *GraphQL: + b.appendReadyMessage(&GraphQLEvent{ + MessageID: messageID, + Timestamp: b.timestamp, + OperationKind: msg.OperationKind, + OperationName: msg.OperationName, + Variables: msg.Variables, + Response: msg.Response, }) case *StateAction: b.appendReadyMessage(&StateActionEvent{ @@ -262,12 +269,6 @@ func (b *builder) handleMessage(message Message, messageID uint64) { Timestamp: b.timestamp, Type: msg.Type, }) - case *GraphQL: - b.appendReadyMessage(&GraphQLEvent{ - MessageID: messageID, - Timestamp: b.timestamp, - Name: msg.OperationName, - }) case *CreateElementNode, *CreateTextNode: b.ddDetector.HandleNodeCreation() @@ -283,11 +284,10 @@ func (b *builder) handleMessage(message Message, messageID uint64) { } } - func (b *builder) checkTimeouts(ts int64) bool { - if b.timestamp == 0 { + if b.timestamp == 0 { return false // There was no timestamp events yet - } + } if b.peBuilder.HasInstance() && int64(b.peBuilder.GetTimestamp())+intervals.EVENTS_PAGE_EVENT_TIMEOUT < ts { b.buildPageEvent() diff --git a/ee/api/chalicelib/core/projects.py b/ee/api/chalicelib/core/projects.py index 2728e5077..75a3a31d0 100644 --- a/ee/api/chalicelib/core/projects.py +++ b/ee/api/chalicelib/core/projects.py @@ -81,20 +81,25 @@ def get_projects(tenant_id, recording_state=False, gdpr=None, recorded=False, st ) rows = cur.fetchall() if recording_state: + project_ids = [f'({r["project_id"]})' for r in rows] + query = f"""SELECT projects.project_id, COALESCE(MAX(start_ts), 0) AS last + FROM (VALUES {",".join(project_ids)}) AS projects(project_id) + LEFT JOIN sessions USING (project_id) + GROUP BY project_id;""" + cur.execute( + query=query + ) + status = cur.fetchall() for r in rows: - query = cur.mogrify( - "select COALESCE(MAX(start_ts),0) AS last from public.sessions where project_id=%(project_id)s;", - {"project_id": r["project_id"]}) - cur.execute( - query=query - ) - status = cur.fetchone() - if status["last"] < TimeUTC.now(-2): - r["status"] = "red" - elif status["last"] < TimeUTC.now(-1): - r["status"] = "yellow" - else: - r["status"] = "green" + for s in status: + if s["project_id"] == r["project_id"]: + if s["last"] < TimeUTC.now(-2): + r["status"] = "red" + elif s["last"] < TimeUTC.now(-1): + r["status"] = "yellow" + else: + r["status"] = "green" + break return helper.list_to_camel_case(rows) diff --git a/ee/api/chalicelib/core/signup.py b/ee/api/chalicelib/core/signup.py index aa4ba2af9..4014f5e92 100644 --- a/ee/api/chalicelib/core/signup.py +++ b/ee/api/chalicelib/core/signup.py @@ -1,7 +1,5 @@ import json -from decouple import config - import schemas from chalicelib.core import users, telemetry, tenants from chalicelib.utils import captcha @@ -63,12 +61,11 @@ def create_step1(data: schemas.UserSignupSchema): params = {"email": email, "password": password, "fullname": fullname, "companyName": company_name, "projectName": project_name, - "versionNumber": config("version_number"), "data": json.dumps({"lastAnnouncementView": TimeUTC.now()})} query = """\ WITH t AS ( INSERT INTO public.tenants (name, version_number, edition) - VALUES (%(companyName)s, %(versionNumber)s, 'ee') + VALUES (%(companyName)s, (SELECT openreplay_version()), 'ee') RETURNING tenant_id, api_key ), r AS ( diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.5.3/1.5.3.sql b/ee/scripts/helm/db/init_dbs/postgresql/1.5.3/1.5.3.sql new file mode 100644 index 000000000..1e08dfeae --- /dev/null +++ b/ee/scripts/helm/db/init_dbs/postgresql/1.5.3/1.5.3.sql @@ -0,0 +1,100 @@ +BEGIN; +CREATE OR REPLACE FUNCTION openreplay_version() + RETURNS text AS +$$ +SELECT 'v1.5.3-ee' +$$ LANGUAGE sql IMMUTABLE; + +UPDATE metrics +SET is_public= TRUE; + + +DO +$$ + BEGIN + IF NOT EXISTS(SELECT * + FROM pg_type typ + INNER JOIN pg_namespace nsp + ON nsp.oid = typ.typnamespace + WHERE nsp.nspname = current_schema() + AND typ.typname = 'metric_type') THEN + CREATE TYPE metric_type AS ENUM ('timeseries','table'); + END IF; + END; +$$ +LANGUAGE plpgsql; + +DO +$$ + BEGIN + IF NOT EXISTS(SELECT * + FROM pg_type typ + INNER JOIN pg_namespace nsp + ON nsp.oid = typ.typnamespace + WHERE nsp.nspname = current_schema() + AND typ.typname = 'metric_view_type') THEN + CREATE TYPE metric_view_type AS ENUM ('lineChart','progress','table','pieChart'); + END IF; + END; +$$ +LANGUAGE plpgsql; + +ALTER TABLE metrics + ADD COLUMN IF NOT EXISTS + metric_type metric_type NOT NULL DEFAULT 'timeseries', + ADD COLUMN IF NOT EXISTS + view_type metric_view_type NOT NULL DEFAULT 'lineChart', + ADD COLUMN IF NOT EXISTS + metric_of text NOT NULL DEFAULT 'sessionCount', + ADD COLUMN IF NOT EXISTS + metric_value text[] NOT NULL DEFAULT '{}'::text[], + ADD COLUMN IF NOT EXISTS + metric_format text; + + +DO +$$ + BEGIN + IF NOT EXISTS(SELECT * + FROM pg_type typ + INNER JOIN pg_namespace nsp + ON nsp.oid = typ.typnamespace + WHERE typ.typname = 'http_method') THEN + CREATE TYPE http_method AS ENUM ('GET','HEAD','POST','PUT','DELETE','CONNECT','OPTIONS','TRACE','PATCH'); + END IF; + END; +$$ +LANGUAGE plpgsql; + + +ALTER TABLE events.graphql + ADD COLUMN IF NOT EXISTS request_body text NULL, + ADD COLUMN IF NOT EXISTS response_body text NULL, + ADD COLUMN IF NOT EXISTS status_code smallint NULL, + ADD COLUMN IF NOT EXISTS method http_method NULL, + ADD COLUMN IF NOT EXISTS duration integer NULL; + +ALTER TABLE events_common.requests + ADD COLUMN IF NOT EXISTS request_body text NULL, + ADD COLUMN IF NOT EXISTS response_body text NULL, + ADD COLUMN IF NOT EXISTS status_code smallint NULL, + ADD COLUMN IF NOT EXISTS method http_method NULL; + +UPDATE tenants +SET version_number= openreplay_version(); + +COMMIT; + +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_request_body_nn_idx ON events_common.requests (request_body) WHERE request_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_request_body_nn_gin_idx ON events_common.requests USING GIN (request_body gin_trgm_ops) WHERE request_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_response_body_nn_idx ON events_common.requests (response_body) WHERE response_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_response_body_nn_gin_idx ON events_common.requests USING GIN (response_body gin_trgm_ops) WHERE response_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_status_code_nn_idx ON events_common.requests (status_code) WHERE status_code IS NOT NULL; + +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_request_body_nn_idx ON events.graphql (request_body) WHERE request_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_request_body_nn_gin_idx ON events.graphql USING GIN (request_body gin_trgm_ops) WHERE request_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_response_body_nn_idx ON events.graphql (response_body) WHERE response_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_response_body_nn_gin_idx ON events.graphql USING GIN (response_body gin_trgm_ops) WHERE response_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_status_code_nn_idx ON events.graphql (status_code) WHERE status_code IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_duration_nn_gt0_idx ON events.graphql (duration) WHERE duration IS NOT NULL AND duration > 0; + diff --git a/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql b/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql index b64376d10..ae724f60b 100644 --- a/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql @@ -7,7 +7,7 @@ CREATE EXTENSION IF NOT EXISTS pgcrypto; CREATE OR REPLACE FUNCTION openreplay_version() RETURNS text AS $$ -SELECT 'v1.5.2-ee' +SELECT 'v1.5.3-ee' $$ LANGUAGE sql IMMUTABLE; @@ -770,16 +770,23 @@ $$ CREATE INDEX IF NOT EXISTS traces_user_id_idx ON traces (user_id); CREATE INDEX IF NOT EXISTS traces_tenant_id_idx ON traces (tenant_id); + CREATE TYPE metric_type AS ENUM ('timeseries','table'); + CREATE TYPE metric_view_type AS ENUM ('lineChart','progress','table','pieChart'); CREATE TABLE IF NOT EXISTS metrics ( - metric_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY, - project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE, - user_id integer REFERENCES users (user_id) ON DELETE SET NULL, - name text NOT NULL, - is_public boolean NOT NULL DEFAULT FALSE, - active boolean NOT NULL DEFAULT TRUE, - created_at timestamp default timezone('utc'::text, now()) not null, - deleted_at timestamp + metric_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY, + project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE, + user_id integer REFERENCES users (user_id) ON DELETE SET NULL, + name text NOT NULL, + is_public boolean NOT NULL DEFAULT FALSE, + active boolean NOT NULL DEFAULT TRUE, + created_at timestamp DEFAULT timezone('utc'::text, now()) not null, + deleted_at timestamp, + metric_type metric_type NOT NULL DEFAULT 'timeseries', + view_type metric_view_type NOT NULL DEFAULT 'lineChart', + metric_of text NOT NULL DEFAULT 'sessionCount', + metric_value text[] NOT NULL DEFAULT '{}'::text[], + metric_format text ); CREATE INDEX IF NOT EXISTS metrics_user_id_is_public_idx ON public.metrics (user_id, is_public); CREATE TABLE IF NOT EXISTS metric_series @@ -987,7 +994,11 @@ $$ CREATE INDEX IF NOT EXISTS errors_error_id_timestamp_session_id_idx ON events.errors (error_id, timestamp, session_id); CREATE INDEX IF NOT EXISTS errors_error_id_idx ON events.errors (error_id); - + IF NOT EXISTS(SELECT * + FROM pg_type typ + WHERE typ.typname = 'http_method') THEN + CREATE TYPE http_method AS ENUM ('GET','HEAD','POST','PUT','DELETE','CONNECT','OPTIONS','TRACE','PATCH'); + END IF; CREATE TABLE IF NOT EXISTS events.graphql ( session_id bigint NOT NULL REFERENCES sessions (session_id) ON DELETE CASCADE, @@ -999,6 +1010,12 @@ $$ CREATE INDEX IF NOT EXISTS graphql_name_idx ON events.graphql (name); CREATE INDEX IF NOT EXISTS graphql_name_gin_idx ON events.graphql USING GIN (name gin_trgm_ops); CREATE INDEX IF NOT EXISTS graphql_timestamp_idx ON events.graphql (timestamp); + CREATE INDEX IF NOT EXISTS graphql_request_body_nn_idx ON events.graphql (request_body) WHERE request_body IS NOT NULL; + CREATE INDEX IF NOT EXISTS graphql_request_body_nn_gin_idx ON events.graphql USING GIN (request_body gin_trgm_ops) WHERE request_body IS NOT NULL; + CREATE INDEX IF NOT EXISTS graphql_response_body_nn_idx ON events.graphql (response_body) WHERE response_body IS NOT NULL; + CREATE INDEX IF NOT EXISTS graphql_response_body_nn_gin_idx ON events.graphql USING GIN (response_body gin_trgm_ops) WHERE response_body IS NOT NULL; + CREATE INDEX IF NOT EXISTS graphql_status_code_nn_idx ON events.graphql (status_code) WHERE status_code IS NOT NULL; + CREATE INDEX IF NOT EXISTS graphql_duration_nn_gt0_idx ON events.graphql (duration) WHERE duration IS NOT NULL AND duration > 0; CREATE TABLE IF NOT EXISTS events.state_actions ( @@ -1140,15 +1157,23 @@ $$ CREATE INDEX IF NOT EXISTS issues_issue_id_timestamp_idx ON events_common.issues (issue_id, timestamp); CREATE INDEX IF NOT EXISTS issues_timestamp_idx ON events_common.issues (timestamp); - + IF NOT EXISTS(SELECT * + FROM pg_type typ + WHERE typ.typname = 'http_method') THEN + CREATE TYPE http_method AS ENUM ('GET','HEAD','POST','PUT','DELETE','CONNECT','OPTIONS','TRACE','PATCH'); + END IF; CREATE TABLE IF NOT EXISTS events_common.requests ( - session_id bigint NOT NULL REFERENCES sessions (session_id) ON DELETE CASCADE, - timestamp bigint NOT NULL, - seq_index integer NOT NULL, - url text NOT NULL, - duration integer NOT NULL, - success boolean NOT NULL, + session_id bigint NOT NULL REFERENCES sessions (session_id) ON DELETE CASCADE, + timestamp bigint NOT NULL, + seq_index integer NOT NULL, + url text NOT NULL, + duration integer NOT NULL, + success boolean NOT NULL, + request_body text NULL, + response_body text NULL, + status_code smallint NULL, + method http_method NULL, PRIMARY KEY (session_id, timestamp, seq_index) ); CREATE INDEX IF NOT EXISTS requests_url_idx ON events_common.requests (url); @@ -1165,6 +1190,13 @@ $$ ELSE 0 END)) gin_trgm_ops); CREATE INDEX IF NOT EXISTS requests_timestamp_session_id_failed_idx ON events_common.requests (timestamp, session_id) WHERE success = FALSE; + CREATE INDEX IF NOT EXISTS requests_request_body_nn_idx ON events_common.requests (request_body) WHERE request_body IS NOT NULL; + CREATE INDEX IF NOT EXISTS requests_request_body_nn_gin_idx ON events_common.requests USING GIN (request_body gin_trgm_ops) WHERE request_body IS NOT NULL; + CREATE INDEX IF NOT EXISTS requests_response_body_nn_idx ON events_common.requests (response_body) WHERE response_body IS NOT NULL; + CREATE INDEX IF NOT EXISTS requests_response_body_nn_gin_idx ON events_common.requests USING GIN (response_body gin_trgm_ops) WHERE response_body IS NOT NULL; + CREATE INDEX IF NOT EXISTS requests_status_code_nn_idx ON events_common.requests (status_code) WHERE status_code IS NOT NULL; + + END IF; END; $$ diff --git a/ee/utilities/.gitignore b/ee/utilities/.gitignore new file mode 100644 index 000000000..fc05191e0 --- /dev/null +++ b/ee/utilities/.gitignore @@ -0,0 +1,13 @@ +.idea +node_modules +npm-debug.log +.cache +test.html +build.sh + + + +servers/peerjs-server.js +servers/sourcemaps-handler.js +servers/sourcemaps-server.js +#servers/websocket.js \ No newline at end of file diff --git a/ee/utilities/package-lock.json b/ee/utilities/package-lock.json new file mode 100644 index 000000000..e7974f3f2 --- /dev/null +++ b/ee/utilities/package-lock.json @@ -0,0 +1,2699 @@ +{ + "name": "utilities_server", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "utilities_server", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@maxmind/geoip2-node": "^3.4.0", + "@socket.io/redis-adapter": "^7.1.0", + "aws-sdk": "^2.992.0", + "express": "^4.17.1", + "peer": "^0.6.1", + "redis": "^4.0.3", + "socket.io": "^4.4.1", + "source-map": "^0.7.3", + "ua-parser-js": "^1.0.2", + "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.6.0" + } + }, + "node_modules/@maxmind/geoip2-node": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@maxmind/geoip2-node/-/geoip2-node-3.4.0.tgz", + "integrity": "sha512-XBB+IJSXQRXXHBvwULZu2nOYAPuC0pc77xw/xkDo0cWkBO/L2rUMr+xKGZwj47mFBEiG6tnTMBzxJajEJTrKAg==", + "dependencies": { + "camelcase-keys": "^7.0.0", + "ip6addr": "^0.2.5", + "lodash.set": "^4.3.2", + "maxmind": "^4.2.0" + } + }, + "node_modules/@node-redis/bloom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@node-redis/bloom/-/bloom-1.0.1.tgz", + "integrity": "sha512-mXEBvEIgF4tUzdIN89LiYsbi6//EdpFA7L8M+DHCvePXg+bfHWi+ct5VI6nHUFQE5+ohm/9wmgihCH3HSkeKsw==", + "peerDependencies": { + "@node-redis/client": "^1.0.0" + } + }, + "node_modules/@node-redis/client": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@node-redis/client/-/client-1.0.4.tgz", + "integrity": "sha512-IM/NRAqg7MvNC3bIRQipXGrEarunrdgvrbAzsd3ty93LSHi/M+ybQulOERQi8a3M+P5BL8HenwXjiIoKm6ml2g==", + "dependencies": { + "cluster-key-slot": "1.1.0", + "generic-pool": "3.8.2", + "redis-parser": "3.0.0", + "yallist": "4.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@node-redis/graph": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@node-redis/graph/-/graph-1.0.0.tgz", + "integrity": "sha512-mRSo8jEGC0cf+Rm7q8mWMKKKqkn6EAnA9IA2S3JvUv/gaWW/73vil7GLNwion2ihTptAm05I9LkepzfIXUKX5g==", + "peerDependencies": { + "@node-redis/client": "^1.0.0" + } + }, + "node_modules/@node-redis/json": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@node-redis/json/-/json-1.0.2.tgz", + "integrity": "sha512-qVRgn8WfG46QQ08CghSbY4VhHFgaTY71WjpwRBGEuqGPfWwfRcIf3OqSpR7Q/45X+v3xd8mvYjywqh0wqJ8T+g==", + "peerDependencies": { + "@node-redis/client": "^1.0.0" + } + }, + "node_modules/@node-redis/search": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@node-redis/search/-/search-1.0.3.tgz", + "integrity": "sha512-rsrzkGWI84di/uYtEctS/4qLusWt0DESx/psjfB0TFpORDhe7JfC0h8ary+eHulTksumor244bXLRSqQXbFJmw==", + "peerDependencies": { + "@node-redis/client": "^1.0.0" + } + }, + "node_modules/@node-redis/time-series": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@node-redis/time-series/-/time-series-1.0.2.tgz", + "integrity": "sha512-HGQ8YooJ8Mx7l28tD7XjtB3ImLEjlUxG1wC1PAjxu6hPJqjPshUZxAICzDqDjtIbhDTf48WXXUcx8TQJB1XTKA==", + "peerDependencies": { + "@node-redis/client": "^1.0.0" + } + }, + "node_modules/@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/@socket.io/redis-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/redis-adapter/-/redis-adapter-7.1.0.tgz", + "integrity": "sha512-vbsNJKUQgtVHcOqNL2ac8kSemTVNKHRzYPldqQJt0eFKvlAtAviuAMzBP0WmOp5OoRLQMjhVsVvgMzzMsVsK5g==", + "dependencies": { + "debug": "~4.3.1", + "notepack.io": "~2.2.0", + "socket.io-adapter": "~2.3.0", + "uid2": "0.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "node_modules/@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/aws-sdk": { + "version": "2.1087.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1087.0.tgz", + "integrity": "sha512-m5EERT29Fwh2cv3SaSdygeAjJBXnjSaXRRERy70bf6PQ7KgmASJouBxY11g5G7LTEPK/yfB0TGshujKh3hEtPA==", + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "dependencies": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/cluster-key-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", + "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", + "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "dependencies": { + "@socket.io/base64-arraybuffer": "~1.0.2" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/express": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", + "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.19.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.9.7", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/generic-pool": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", + "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ip6addr": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/ip6addr/-/ip6addr-0.2.5.tgz", + "integrity": "sha512-9RGGSB6Zc9Ox5DpDGFnJdIeF0AsqXzdH+FspCfPPaU/L/4tI6P+5lIoFUFm9JXs9IrJv1boqAaNCQmoDADTSKQ==", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/maxmind": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/maxmind/-/maxmind-4.3.5.tgz", + "integrity": "sha512-ak0TABuO664C5zXyQH5u13WmtdTwxxXLGOy1e51ZRrp/cEH9xfOcG20F51TcNhVyDos13Ys94kxN8/elg9Ri4Q==", + "dependencies": { + "mmdb-lib": "2.0.2", + "tiny-lru": "7.0.6" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mmdb-lib": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mmdb-lib/-/mmdb-lib-2.0.2.tgz", + "integrity": "sha512-shi1I+fCPQonhTi7qyb6hr7hi87R7YS69FlfJiMFuJ12+grx0JyL56gLNzGTYXPU7EhAPkMLliGeyHer0K+AVA==", + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/notepack.io": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/notepack.io/-/notepack.io-2.2.0.tgz", + "integrity": "sha512-9b5w3t5VSH6ZPosoYnyDONnUTF8o0UkBw7JLA6eBlYJWyGT1Q3vQa8Hmuj1/X6RYvHjjygBDgw6fJhe0JEojfw==" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/peer": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/peer/-/peer-0.6.1.tgz", + "integrity": "sha512-zPJSPoZvo+83sPJNrW8o93QTktx7dKk67965RRDDNAIelWw1ZwE6ZmmhsvRrdNRlK0knQb3rR8GBdZlbWzCYJw==", + "dependencies": { + "@types/cors": "^2.8.6", + "@types/express": "^4.17.3", + "@types/ws": "^7.2.3", + "body-parser": "^1.19.0", + "cors": "^2.8.5", + "express": "^4.17.1", + "uuid": "^3.4.0", + "ws": "^7.2.3", + "yargs": "^15.3.1" + }, + "bin": { + "peerjs": "bin/peerjs" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/peer/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/redis": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.0.4.tgz", + "integrity": "sha512-KaM1OAj/nGrSeybmmOWSMY0LXTGT6FVWgUZZrd2MYzXKJ+VGtqVaciGQeNMfZiQX+kDM8Ke4uttb54m2rm6V0A==", + "dependencies": { + "@node-redis/bloom": "1.0.1", + "@node-redis/client": "1.0.4", + "@node-redis/graph": "1.0.0", + "@node-redis/json": "1.0.2", + "@node-redis/search": "1.0.3", + "@node-redis/time-series": "1.0.2" + } + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "node_modules/send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "dependencies": { + "debug": "2.6.9", + "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": "1.8.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/socket.io": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" + }, + "node_modules/socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "dependencies": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tiny-lru": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-7.0.6.tgz", + "integrity": "sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==", + "engines": { + "node": ">=6" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ua-parser-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.2.tgz", + "integrity": "sha512-00y/AXhx0/SsnI51fTc0rLRmafiGOM4/O+ny10Ps7f+j/b8p/ZY11ytMgznXkOVo4GQ+KwQG5UQLkLGirsACRg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/uid2": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", + "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/uWebSockets.js": { + "version": "20.6.0", + "resolved": "git+ssh://git@github.com/uNetworking/uWebSockets.js.git#a58e810e47a23696410f6073c8c905dc38f75da5" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ws": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "node_modules/xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-parser/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + } + }, + "dependencies": { + "@maxmind/geoip2-node": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@maxmind/geoip2-node/-/geoip2-node-3.4.0.tgz", + "integrity": "sha512-XBB+IJSXQRXXHBvwULZu2nOYAPuC0pc77xw/xkDo0cWkBO/L2rUMr+xKGZwj47mFBEiG6tnTMBzxJajEJTrKAg==", + "requires": { + "camelcase-keys": "^7.0.0", + "ip6addr": "^0.2.5", + "lodash.set": "^4.3.2", + "maxmind": "^4.2.0" + } + }, + "@node-redis/bloom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@node-redis/bloom/-/bloom-1.0.1.tgz", + "integrity": "sha512-mXEBvEIgF4tUzdIN89LiYsbi6//EdpFA7L8M+DHCvePXg+bfHWi+ct5VI6nHUFQE5+ohm/9wmgihCH3HSkeKsw==", + "requires": {} + }, + "@node-redis/client": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@node-redis/client/-/client-1.0.4.tgz", + "integrity": "sha512-IM/NRAqg7MvNC3bIRQipXGrEarunrdgvrbAzsd3ty93LSHi/M+ybQulOERQi8a3M+P5BL8HenwXjiIoKm6ml2g==", + "requires": { + "cluster-key-slot": "1.1.0", + "generic-pool": "3.8.2", + "redis-parser": "3.0.0", + "yallist": "4.0.0" + } + }, + "@node-redis/graph": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@node-redis/graph/-/graph-1.0.0.tgz", + "integrity": "sha512-mRSo8jEGC0cf+Rm7q8mWMKKKqkn6EAnA9IA2S3JvUv/gaWW/73vil7GLNwion2ihTptAm05I9LkepzfIXUKX5g==", + "requires": {} + }, + "@node-redis/json": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@node-redis/json/-/json-1.0.2.tgz", + "integrity": "sha512-qVRgn8WfG46QQ08CghSbY4VhHFgaTY71WjpwRBGEuqGPfWwfRcIf3OqSpR7Q/45X+v3xd8mvYjywqh0wqJ8T+g==", + "requires": {} + }, + "@node-redis/search": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@node-redis/search/-/search-1.0.3.tgz", + "integrity": "sha512-rsrzkGWI84di/uYtEctS/4qLusWt0DESx/psjfB0TFpORDhe7JfC0h8ary+eHulTksumor244bXLRSqQXbFJmw==", + "requires": {} + }, + "@node-redis/time-series": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@node-redis/time-series/-/time-series-1.0.2.tgz", + "integrity": "sha512-HGQ8YooJ8Mx7l28tD7XjtB3ImLEjlUxG1wC1PAjxu6hPJqjPshUZxAICzDqDjtIbhDTf48WXXUcx8TQJB1XTKA==", + "requires": {} + }, + "@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==" + }, + "@socket.io/redis-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/redis-adapter/-/redis-adapter-7.1.0.tgz", + "integrity": "sha512-vbsNJKUQgtVHcOqNL2ac8kSemTVNKHRzYPldqQJt0eFKvlAtAviuAMzBP0WmOp5OoRLQMjhVsVvgMzzMsVsK5g==", + "requires": { + "debug": "~4.3.1", + "notepack.io": "~2.2.0", + "socket.io-adapter": "~2.3.0", + "uid2": "0.0.3" + } + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "@types/node": { + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "requires": { + "@types/node": "*" + } + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "aws-sdk": { + "version": "2.1087.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1087.0.tgz", + "integrity": "sha512-m5EERT29Fwh2cv3SaSdygeAjJBXnjSaXRRERy70bf6PQ7KgmASJouBxY11g5G7LTEPK/yfB0TGshujKh3hEtPA==", + "requires": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" + }, + "body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "requires": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "cluster-key-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", + "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "engine.io": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", + "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" + }, + "dependencies": { + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "requires": {} + } + } + }, + "engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "requires": { + "@socket.io/base64-arraybuffer": "~1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "express": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", + "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.19.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.9.7", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "generic-pool": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", + "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ip6addr": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/ip6addr/-/ip6addr-0.2.5.tgz", + "integrity": "sha512-9RGGSB6Zc9Ox5DpDGFnJdIeF0AsqXzdH+FspCfPPaU/L/4tI6P+5lIoFUFm9JXs9IrJv1boqAaNCQmoDADTSKQ==", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2" + } + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==" + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" + }, + "map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==" + }, + "maxmind": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/maxmind/-/maxmind-4.3.5.tgz", + "integrity": "sha512-ak0TABuO664C5zXyQH5u13WmtdTwxxXLGOy1e51ZRrp/cEH9xfOcG20F51TcNhVyDos13Ys94kxN8/elg9Ri4Q==", + "requires": { + "mmdb-lib": "2.0.2", + "tiny-lru": "7.0.6" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + }, + "mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "requires": { + "mime-db": "1.51.0" + } + }, + "mmdb-lib": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mmdb-lib/-/mmdb-lib-2.0.2.tgz", + "integrity": "sha512-shi1I+fCPQonhTi7qyb6hr7hi87R7YS69FlfJiMFuJ12+grx0JyL56gLNzGTYXPU7EhAPkMLliGeyHer0K+AVA==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "notepack.io": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/notepack.io/-/notepack.io-2.2.0.tgz", + "integrity": "sha512-9b5w3t5VSH6ZPosoYnyDONnUTF8o0UkBw7JLA6eBlYJWyGT1Q3vQa8Hmuj1/X6RYvHjjygBDgw6fJhe0JEojfw==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "peer": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/peer/-/peer-0.6.1.tgz", + "integrity": "sha512-zPJSPoZvo+83sPJNrW8o93QTktx7dKk67965RRDDNAIelWw1ZwE6ZmmhsvRrdNRlK0knQb3rR8GBdZlbWzCYJw==", + "requires": { + "@types/cors": "^2.8.6", + "@types/express": "^4.17.3", + "@types/ws": "^7.2.3", + "body-parser": "^1.19.0", + "cors": "^2.8.5", + "express": "^4.17.1", + "uuid": "^3.4.0", + "ws": "^7.2.3", + "yargs": "^15.3.1" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "requires": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "redis": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.0.4.tgz", + "integrity": "sha512-KaM1OAj/nGrSeybmmOWSMY0LXTGT6FVWgUZZrd2MYzXKJ+VGtqVaciGQeNMfZiQX+kDM8Ke4uttb54m2rm6V0A==", + "requires": { + "@node-redis/bloom": "1.0.1", + "@node-redis/client": "1.0.4", + "@node-redis/graph": "1.0.0", + "@node-redis/json": "1.0.2", + "@node-redis/search": "1.0.3", + "@node-redis/time-series": "1.0.2" + } + }, + "redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" + }, + "redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", + "requires": { + "redis-errors": "^1.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "requires": { + "debug": "2.6.9", + "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": "1.8.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serve-static": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "socket.io": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" + } + }, + "socket.io-adapter": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" + }, + "socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "requires": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "tiny-lru": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-7.0.6.tgz", + "integrity": "sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==" + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "ua-parser-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.2.tgz", + "integrity": "sha512-00y/AXhx0/SsnI51fTc0rLRmafiGOM4/O+ny10Ps7f+j/b8p/ZY11ytMgznXkOVo4GQ+KwQG5UQLkLGirsACRg==" + }, + "uid2": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", + "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "uWebSockets.js": { + "version": "git+ssh://git@github.com/uNetworking/uWebSockets.js.git#a58e810e47a23696410f6073c8c905dc38f75da5", + "from": "uWebSockets.js@github:uNetworking/uWebSockets.js#v20.6.0" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "ws": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "requires": {} + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + } + } + } + } +} diff --git a/ee/utilities/package.json b/ee/utilities/package.json new file mode 100644 index 000000000..87e1d1596 --- /dev/null +++ b/ee/utilities/package.json @@ -0,0 +1,32 @@ +{ + "name": "utilities_server", + "version": "1.0.0", + "description": "assist server to get live sessions & sourcemaps reader to get stack trace", + "main": "peerjs-server.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/openreplay/openreplay.git" + }, + "author": "KRAIEM Taha Yassine ", + "license": "MIT", + "bugs": { + "url": "https://github.com/openreplay/openreplay/issues" + }, + "homepage": "https://github.com/openreplay/openreplay#readme", + "dependencies": { + "@maxmind/geoip2-node": "^3.4.0", + "@socket.io/redis-adapter": "^7.1.0", + "aws-sdk": "^2.992.0", + "express": "^4.17.1", + "peer": "^0.6.1", + "redis": "^4.0.3", + "socket.io": "^4.4.1", + "source-map": "^0.7.3", + "ua-parser-js": "^1.0.2", + "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.6.0" + } +} diff --git a/ee/utilities/server.js b/ee/utilities/server.js new file mode 100644 index 000000000..f1209c9ff --- /dev/null +++ b/ee/utilities/server.js @@ -0,0 +1,128 @@ +var sourcemapsReaderServer = require('./servers/sourcemaps-server'); +var {peerRouter, peerConnection, peerDisconnect, peerError} = require('./servers/peerjs-server'); +var express = require('express'); +const {ExpressPeerServer} = require('peer'); +var socket; +if (process.env.cluster === "true") { + console.log("Using Redis"); + socket = require("./servers/websocket-cluster"); +} else { + socket = require("./servers/websocket"); +} + +const HOST = '0.0.0.0'; +const PORT = 9000; + +var app = express(); + +let debug = process.env.debug === "1" || false; +const request_logger = (identity) => { + return (req, res, next) => { + debug && console.log(identity, new Date().toTimeString(), 'REQUEST', req.method, req.originalUrl); + res.on('finish', function () { + if (this.statusCode !== 200 || debug) { + console.log(new Date().toTimeString(), 'RESPONSE', req.method, req.originalUrl, this.statusCode); + } + }) + + next(); + } +}; +app.use(request_logger("[app]")); + + +app.use('/sourcemaps', sourcemapsReaderServer); +app.use('/assist', peerRouter); + +const server = app.listen(PORT, HOST, () => { + console.log(`App listening on http://${HOST}:${PORT}`); + console.log('Press Ctrl+C to quit.'); +}); + +const peerServer = ExpressPeerServer(server, { + debug: true, + path: '/', + proxied: true, + allow_discovery: false +}); +peerServer.on('connection', peerConnection); +peerServer.on('disconnect', peerDisconnect); +peerServer.on('error', peerError); +app.use('/', peerServer); +app.enable('trust proxy'); + +if (process.env.uws !== "true") { + var wsapp = express(); + wsapp.use(request_logger("[wsapp]")); + wsapp.use('/assist', socket.wsRouter); + + const wsserver = wsapp.listen(PORT + 1, HOST, () => { + console.log(`WS App listening on http://${HOST}:${PORT + 1}`); + console.log('Press Ctrl+C to quit.'); + }); + wsapp.enable('trust proxy'); + socket.start(wsserver); + module.exports = {wsserver, server}; +} else { + console.log("Using uWebSocket"); + const {App} = require("uWebSockets.js"); + const PREFIX = process.env.prefix || '/assist' + + const uapp = new App(); + + const healthFn = (res, req) => { + res.writeStatus('200 OK').end('ok!'); + } + uapp.get(PREFIX, healthFn); + uapp.get(`${PREFIX}/`, healthFn); + + + /* Either onAborted or simply finished request */ + const onAbortedOrFinishedResponse = function (res, readStream) { + + if (res.id === -1) { + debug && console.log("ERROR! onAbortedOrFinishedResponse called twice for the same res!"); + } else { + debug && console.log('Stream was closed'); + console.timeEnd(res.id); + readStream.destroy(); + } + + /* Mark this response already accounted for */ + res.id = -1; + } + + const uWrapper = function (fn) { + return (res, req) => { + res.id = 1; + res.onAborted(() => { + onAbortedOrFinishedResponse(res, readStream); + }); + return fn(req, res); + } + } + uapp.get(`${PREFIX}/${process.env.S3_KEY}/sockets-list`, uWrapper(socket.handlers.socketsList)); + uapp.get(`${PREFIX}/${process.env.S3_KEY}/sockets-list/:projectKey`, uWrapper(socket.handlers.socketsListByProject)); + + uapp.get(`${PREFIX}/${process.env.S3_KEY}/sockets-live`, uWrapper(socket.handlers.socketsLive)); + uapp.get(`${PREFIX}/${process.env.S3_KEY}/sockets-live/:projectKey`, uWrapper(socket.handlers.socketsLiveByProject)); + + + socket.start(uapp); + + uapp.listen(HOST, PORT + 1, (token) => { + if (!token) { + console.warn("port already in use"); + } + console.log(`WS App listening on http://${HOST}:${PORT + 1}`); + console.log('Press Ctrl+C to quit.'); + }); + + + process.on('uncaughtException', err => { + console.log(`Uncaught Exception: ${err.message}`); + debug && console.log(err.stack); + // process.exit(1); + }); + module.exports = {uapp, server}; +} \ No newline at end of file diff --git a/ee/utilities/servers/websocket-cluster.js b/ee/utilities/servers/websocket-cluster.js new file mode 100644 index 000000000..940f83879 --- /dev/null +++ b/ee/utilities/servers/websocket-cluster.js @@ -0,0 +1,371 @@ +const _io = require('socket.io'); +const express = require('express'); +const uaParser = require('ua-parser-js'); +const geoip2Reader = require('@maxmind/geoip2-node').Reader; +const {extractPeerId} = require('./peerjs-server'); +const {createAdapter} = require("@socket.io/redis-adapter"); +const {createClient} = require("redis"); + +var wsRouter = express.Router(); +const UPDATE_EVENT = "UPDATE_SESSION"; +const IDENTITIES = {agent: 'agent', session: 'session'}; +const NEW_AGENT = "NEW_AGENT"; +const NO_AGENTS = "NO_AGENT"; +const AGENT_DISCONNECT = "AGENT_DISCONNECTED"; +const AGENTS_CONNECTED = "AGENTS_CONNECTED"; +const NO_SESSIONS = "SESSION_DISCONNECTED"; +const SESSION_ALREADY_CONNECTED = "SESSION_ALREADY_CONNECTED"; +// const wsReconnectionTimeout = process.env.wsReconnectionTimeout | 10 * 1000; + +let io; +const debug = process.env.debug === "1" || false; +const REDIS_URL = process.env.REDIS_URL || "redis://localhost:6379"; + +const pubClient = createClient({url: REDIS_URL}); +const subClient = pubClient.duplicate(); + +const uniqueSessions = function (data) { + let resArr = []; + let resArrIDS = []; + for (let item of data) { + if (resArrIDS.indexOf(item.sessionID) < 0) { + resArr.push(item); + resArrIDS.push(item.sessionID); + } + } + return resArr; +} + +const socketsList = async function (req, res) { + debug && console.log("[WS]looking for all available sessions"); + let liveSessions = {}; + let rooms = await io.of('/').adapter.allRooms(); + for (let peerId of rooms) { + let {projectKey, sessionId} = extractPeerId(peerId); + if (projectKey !== undefined) { + liveSessions[projectKey] = liveSessions[projectKey] || []; + liveSessions[projectKey].push(sessionId); + } + } + let result = {"data": liveSessions}; + if (process.env.uws !== "true") { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify(result)); + } else { + res.writeStatus('200 OK').writeHeader('Content-Type', 'application/json').end(JSON.stringify(result)); + } +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-list`, socketsList); + +const socketsListByProject = async function (req, res) { + if (process.env.uws === "true") { + req.params = {projectKey: req.getParameter(0)}; + } + debug && console.log(`[WS]looking for available sessions for ${req.params.projectKey}`); + let liveSessions = {}; + let rooms = await io.of('/').adapter.allRooms(); + for (let peerId of rooms) { + let {projectKey, sessionId} = extractPeerId(peerId); + if (projectKey === req.params.projectKey) { + liveSessions[projectKey] = liveSessions[projectKey] || []; + liveSessions[projectKey].push(sessionId); + } + } + let result = {"data": liveSessions[req.params.projectKey] || []}; + if (process.env.uws !== "true") { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify(result)); + } else { + res.writeStatus('200 OK').writeHeader('Content-Type', 'application/json').end(JSON.stringify(result)); + } +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-list/:projectKey`, socketsListByProject); + +const socketsLive = async function (req, res) { + debug && console.log("[WS]looking for all available LIVE sessions"); + let liveSessions = {}; + let rooms = await io.of('/').adapter.allRooms(); + for (let peerId of rooms) { + let {projectKey, sessionId} = extractPeerId(peerId); + if (projectKey !== undefined) { + let connected_sockets = await io.in(peerId).fetchSockets(); + for (let item of connected_sockets) { + if (item.handshake.query.identity === IDENTITIES.session) { + liveSessions[projectKey] = liveSessions[projectKey] || []; + liveSessions[projectKey].push(item.handshake.query.sessionInfo); + } + } + liveSessions[projectKey] = uniqueSessions(liveSessions[projectKey]); + } + } + let result = {"data": liveSessions}; + if (process.env.uws !== "true") { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify(result)); + } else { + res.writeStatus('200 OK').writeHeader('Content-Type', 'application/json').end(JSON.stringify(result)); + } +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-live`, socketsLive); + +const socketsLiveByProject = async function (req, res) { + if (process.env.uws === "true") { + req.params = {projectKey: req.getParameter(0)}; + } + debug && console.log(`[WS]looking for available LIVE sessions for ${req.params.projectKey}`); + let liveSessions = {}; + let rooms = await io.of('/').adapter.allRooms(); + for (let peerId of rooms) { + let {projectKey, sessionId} = extractPeerId(peerId); + if (projectKey === req.params.projectKey) { + let connected_sockets = await io.in(peerId).fetchSockets(); + for (let item of connected_sockets) { + if (item.handshake.query.identity === IDENTITIES.session) { + liveSessions[projectKey] = liveSessions[projectKey] || []; + liveSessions[projectKey].push(item.handshake.query.sessionInfo); + } + } + liveSessions[projectKey] = uniqueSessions(liveSessions[projectKey]); + } + } + let result = {"data": liveSessions[req.params.projectKey] || []}; + if (process.env.uws !== "true") { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify(result)); + } else { + res.writeStatus('200 OK').writeHeader('Content-Type', 'application/json').end(JSON.stringify(result)); + } +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-live/:projectKey`, socketsLiveByProject); + +const findSessionSocketId = async (io, peerId) => { + const connected_sockets = await io.in(peerId).fetchSockets(); + for (let item of connected_sockets) { + if (item.handshake.query.identity === IDENTITIES.session) { + return item.id; + } + } + return null; +}; + +async function sessions_agents_count(io, socket) { + let c_sessions = 0, c_agents = 0; + let rooms = await io.of('/').adapter.allRooms(); + if (rooms.has(socket.peerId)) { + const connected_sockets = await io.in(socket.peerId).fetchSockets(); + + for (let item of connected_sockets) { + if (item.handshake.query.identity === IDENTITIES.session) { + c_sessions++; + } else { + c_agents++; + } + } + } else { + c_agents = -1; + c_sessions = -1; + } + return {c_sessions, c_agents}; +} + +async function get_all_agents_ids(io, socket) { + let agents = []; + let rooms = await io.of('/').adapter.allRooms(); + if (rooms.has(socket.peerId)) { + const connected_sockets = await io.in(socket.peerId).fetchSockets(); + for (let item of connected_sockets) { + if (item.handshake.query.identity === IDENTITIES.agent) { + agents.push(item.id); + } + } + } + return agents; +} + +function extractSessionInfo(socket) { + if (socket.handshake.query.sessionInfo !== undefined) { + debug && console.log("received headers"); + debug && console.log(socket.handshake.headers); + socket.handshake.query.sessionInfo = JSON.parse(socket.handshake.query.sessionInfo); + + let ua = uaParser(socket.handshake.headers['user-agent']); + socket.handshake.query.sessionInfo.userOs = ua.os.name || null; + socket.handshake.query.sessionInfo.userBrowser = ua.browser.name || null; + socket.handshake.query.sessionInfo.userBrowserVersion = ua.browser.version || null; + socket.handshake.query.sessionInfo.userDevice = ua.device.model || null; + socket.handshake.query.sessionInfo.userDeviceType = ua.device.type || 'desktop'; + socket.handshake.query.sessionInfo.userCountry = null; + + const options = { + // you can use options like `cache` or `watchForUpdates` + }; + // console.log("Looking for MMDB file in " + process.env.MAXMINDDB_FILE); + geoip2Reader.open(process.env.MAXMINDDB_FILE, options) + .then(reader => { + debug && console.log("looking for location of "); + debug && console.log(socket.handshake.headers['x-forwarded-for'] || socket.handshake.address); + let country = reader.country(socket.handshake.headers['x-forwarded-for'] || socket.handshake.address); + socket.handshake.query.sessionInfo.userCountry = country.country.isoCode; + }) + .catch(error => { + console.error(error); + }); + } +} + +module.exports = { + wsRouter, + start: (server) => { + if (process.env.uws !== "true") { + io = _io(server, { + maxHttpBufferSize: (parseInt(process.env.maxHttpBufferSize) || 5) * 1e6, + cors: { + origin: "*", + methods: ["GET", "POST", "PUT"] + }, + path: '/socket' + }); + } else { + io = new _io.Server({ + maxHttpBufferSize: (parseInt(process.env.maxHttpBufferSize) || 5) * 1e6, + cors: { + origin: "*", + methods: ["GET", "POST", "PUT"] + }, + path: '/socket', + // transports: ['websocket'], + // upgrade: false + }); + io.attachApp(server); + } + + io.on('connection', async (socket) => { + debug && console.log(`WS started:${socket.id}, Query:${JSON.stringify(socket.handshake.query)}`); + socket.peerId = socket.handshake.query.peerId; + socket.identity = socket.handshake.query.identity; + let {projectKey, sessionId} = extractPeerId(socket.peerId); + socket.sessionId = sessionId; + socket.projectKey = projectKey; + socket.lastMessageReceivedAt = Date.now(); + let {c_sessions, c_agents} = await sessions_agents_count(io, socket); + if (socket.identity === IDENTITIES.session) { + if (c_sessions > 0) { + debug && console.log(`session already connected, refusing new connexion`); + io.to(socket.id).emit(SESSION_ALREADY_CONNECTED); + return socket.disconnect(); + } + extractSessionInfo(socket); + if (c_agents > 0) { + debug && console.log(`notifying new session about agent-existence`); + let agents_ids = await get_all_agents_ids(io, socket); + io.to(socket.id).emit(AGENTS_CONNECTED, agents_ids); + } + + } else if (c_sessions <= 0) { + debug && console.log(`notifying new agent about no SESSIONS`); + io.to(socket.id).emit(NO_SESSIONS); + } + await io.of('/').adapter.remoteJoin(socket.id, socket.peerId); + let rooms = await io.of('/').adapter.allRooms(); + if (rooms.has(socket.peerId)) { + let connectedSockets = await io.in(socket.peerId).fetchSockets(); + debug && console.log(`${socket.id} joined room:${socket.peerId}, as:${socket.identity}, members:${connectedSockets.length}`); + } + if (socket.identity === IDENTITIES.agent) { + if (socket.handshake.query.agentInfo !== undefined) { + socket.handshake.query.agentInfo = JSON.parse(socket.handshake.query.agentInfo); + } + socket.to(socket.peerId).emit(NEW_AGENT, socket.id, socket.handshake.query.agentInfo); + } + + socket.on('disconnect', async () => { + debug && console.log(`${socket.id} disconnected from ${socket.peerId}`); + if (socket.identity === IDENTITIES.agent) { + socket.to(socket.peerId).emit(AGENT_DISCONNECT, socket.id); + } + debug && console.log("checking for number of connected agents and sessions"); + let {c_sessions, c_agents} = await sessions_agents_count(io, socket); + if (c_sessions === -1 && c_agents === -1) { + debug && console.log(`room not found: ${socket.peerId}`); + } + if (c_sessions === 0) { + debug && console.log(`notifying everyone in ${socket.peerId} about no SESSIONS`); + socket.to(socket.peerId).emit(NO_SESSIONS); + } + if (c_agents === 0) { + debug && console.log(`notifying everyone in ${socket.peerId} about no AGENTS`); + socket.to(socket.peerId).emit(NO_AGENTS); + } + }); + + socket.on(UPDATE_EVENT, async (...args) => { + debug && console.log(`${socket.id} sent update event.`); + if (socket.identity !== IDENTITIES.session) { + debug && console.log('Ignoring update event.'); + return + } + socket.handshake.query.sessionInfo = {...socket.handshake.query.sessionInfo, ...args[0]}; + socket.to(socket.peerId).emit(UPDATE_EVENT, args[0]); + }); + + socket.onAny(async (eventName, ...args) => { + socket.lastMessageReceivedAt = Date.now(); + if (socket.identity === IDENTITIES.session) { + debug && console.log(`received event:${eventName}, from:${socket.identity}, sending message to room:${socket.peerId}`); + socket.to(socket.peerId).emit(eventName, args[0]); + } else { + debug && console.log(`received event:${eventName}, from:${socket.identity}, sending message to session of room:${socket.peerId}`); + let socketId = await findSessionSocketId(io, socket.peerId); + if (socketId === null) { + debug && console.log(`session not found for:${socket.peerId}`); + io.to(socket.id).emit(NO_SESSIONS); + } else { + debug && console.log("message sent"); + io.to(socketId).emit(eventName, socket.id, args[0]); + } + } + }); + + }); + console.log("WS server started") + setInterval(async (io) => { + try { + let rooms = await io.of('/').adapter.allRooms(); + let validRooms = []; + console.log(` ====== Rooms: ${rooms.size} ====== `); + const arr = Array.from(rooms) + // const filtered = arr.filter(room => !room[1].has(room[0])) + for (let i of rooms) { + let {projectKey, sessionId} = extractPeerId(i); + if (projectKey !== undefined && sessionId !== undefined) { + validRooms.push(i); + } + } + console.log(` ====== Valid Rooms: ${validRooms.length} ====== `); + if (debug) { + for (let item of validRooms) { + let connectedSockets = await io.in(item).fetchSockets(); + console.log(`Room: ${item} connected: ${connectedSockets.length}`) + } + } + } catch (e) { + console.error(e); + } + }, 20000, io); + Promise.all([pubClient.connect(), subClient.connect()]).then(() => { + io.adapter(createAdapter(pubClient, subClient)); + console.log("> redis connected."); + // io.listen(3000); + }); + }, + handlers: { + socketsList, + socketsListByProject, + socketsLive, + socketsLiveByProject + } +}; \ No newline at end of file diff --git a/ee/utilities/servers/websocket.js b/ee/utilities/servers/websocket.js new file mode 100644 index 000000000..34f045a51 --- /dev/null +++ b/ee/utilities/servers/websocket.js @@ -0,0 +1,334 @@ +const _io = require('socket.io'); +const express = require('express'); +const uaParser = require('ua-parser-js'); +const geoip2Reader = require('@maxmind/geoip2-node').Reader; +var {extractPeerId} = require('./peerjs-server'); +var wsRouter = express.Router(); +const UPDATE_EVENT = "UPDATE_SESSION"; +const IDENTITIES = {agent: 'agent', session: 'session'}; +const NEW_AGENT = "NEW_AGENT"; +const NO_AGENTS = "NO_AGENT"; +const AGENT_DISCONNECT = "AGENT_DISCONNECTED"; +const AGENTS_CONNECTED = "AGENTS_CONNECTED"; +const NO_SESSIONS = "SESSION_DISCONNECTED"; +const SESSION_ALREADY_CONNECTED = "SESSION_ALREADY_CONNECTED"; +// const wsReconnectionTimeout = process.env.wsReconnectionTimeout | 10 * 1000; + +let io; +let debug = process.env.debug === "1" || false; + +const socketsList = function (req, res) { + debug && console.log("[WS]looking for all available sessions"); + let liveSessions = {}; + for (let peerId of io.sockets.adapter.rooms.keys()) { + let {projectKey, sessionId} = extractPeerId(peerId); + if (projectKey !== undefined) { + liveSessions[projectKey] = liveSessions[projectKey] || []; + liveSessions[projectKey].push(sessionId); + } + } + let result = {"data": liveSessions}; + if (process.env.uws !== "true") { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify(result)); + } else { + res.writeStatus('200 OK').writeHeader('Content-Type', 'application/json').end(JSON.stringify(result)); + } +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-list`, socketsList); + +const socketsListByProject = function (req, res) { + if (process.env.uws === "true") { + req.params = {projectKey: req.getParameter(0)}; + } + debug && console.log(`[WS]looking for available sessions for ${req.params.projectKey}`); + let liveSessions = {}; + for (let peerId of io.sockets.adapter.rooms.keys()) { + let {projectKey, sessionId} = extractPeerId(peerId); + if (projectKey === req.params.projectKey) { + liveSessions[projectKey] = liveSessions[projectKey] || []; + liveSessions[projectKey].push(sessionId); + } + } + let result = {"data": liveSessions[req.params.projectKey] || []}; + if (process.env.uws !== "true") { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify()); + } else { + res.writeStatus('200 OK').writeHeader('Content-Type', 'application/json').end(JSON.stringify(result)); + } +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-list/:projectKey`, socketsListByProject); + +const socketsLive = async function (req, res) { + debug && console.log("[WS]looking for all available LIVE sessions"); + let liveSessions = {}; + for (let peerId of io.sockets.adapter.rooms.keys()) { + let {projectKey, sessionId} = extractPeerId(peerId); + if (projectKey !== undefined) { + let connected_sockets = await io.in(peerId).fetchSockets(); + for (let item of connected_sockets) { + if (item.handshake.query.identity === IDENTITIES.session) { + liveSessions[projectKey] = liveSessions[projectKey] || []; + liveSessions[projectKey].push(item.handshake.query.sessionInfo); + } + } + } + } + let result = {"data": liveSessions}; + if (process.env.uws !== "true") { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify(result)); + } else { + res.writeStatus('200 OK').writeHeader('Content-Type', 'application/json').end(JSON.stringify(result)); + } +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-live`, socketsLive); + +const socketsLiveByProject = async function (req, res) { + if (process.env.uws === "true") { + req.params = {projectKey: req.getParameter(0)}; + } + debug && console.log(`[WS]looking for available LIVE sessions for ${req.params.projectKey}`); + let liveSessions = {}; + for (let peerId of io.sockets.adapter.rooms.keys()) { + let {projectKey, sessionId} = extractPeerId(peerId); + if (projectKey === req.params.projectKey) { + let connected_sockets = await io.in(peerId).fetchSockets(); + for (let item of connected_sockets) { + if (item.handshake.query.identity === IDENTITIES.session) { + liveSessions[projectKey] = liveSessions[projectKey] || []; + liveSessions[projectKey].push(item.handshake.query.sessionInfo); + } + } + } + } + let result = {"data": liveSessions[req.params.projectKey] || []}; + if (process.env.uws !== "true") { + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify(result)); + } else { + res.writeStatus('200 OK').writeHeader('Content-Type', 'application/json').end(JSON.stringify(result)); + } +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-live/:projectKey`, socketsLiveByProject); + +const findSessionSocketId = async (io, peerId) => { + const connected_sockets = await io.in(peerId).fetchSockets(); + for (let item of connected_sockets) { + if (item.handshake.query.identity === IDENTITIES.session) { + return item.id; + } + } + return null; +}; + +async function sessions_agents_count(io, socket) { + let c_sessions = 0, c_agents = 0; + if (io.sockets.adapter.rooms.get(socket.peerId)) { + const connected_sockets = await io.in(socket.peerId).fetchSockets(); + + for (let item of connected_sockets) { + if (item.handshake.query.identity === IDENTITIES.session) { + c_sessions++; + } else { + c_agents++; + } + } + } else { + c_agents = -1; + c_sessions = -1; + } + return {c_sessions, c_agents}; +} + +async function get_all_agents_ids(io, socket) { + let agents = []; + if (io.sockets.adapter.rooms.get(socket.peerId)) { + const connected_sockets = await io.in(socket.peerId).fetchSockets(); + for (let item of connected_sockets) { + if (item.handshake.query.identity === IDENTITIES.agent) { + agents.push(item.id); + } + } + } + return agents; +} + +function extractSessionInfo(socket) { + if (socket.handshake.query.sessionInfo !== undefined) { + debug && console.log("received headers"); + debug && console.log(socket.handshake.headers); + socket.handshake.query.sessionInfo = JSON.parse(socket.handshake.query.sessionInfo); + + let ua = uaParser(socket.handshake.headers['user-agent']); + socket.handshake.query.sessionInfo.userOs = ua.os.name || null; + socket.handshake.query.sessionInfo.userBrowser = ua.browser.name || null; + socket.handshake.query.sessionInfo.userBrowserVersion = ua.browser.version || null; + socket.handshake.query.sessionInfo.userDevice = ua.device.model || null; + socket.handshake.query.sessionInfo.userDeviceType = ua.device.type || 'desktop'; + socket.handshake.query.sessionInfo.userCountry = null; + + const options = { + // you can use options like `cache` or `watchForUpdates` + }; + // console.log("Looking for MMDB file in " + process.env.MAXMINDDB_FILE); + geoip2Reader.open(process.env.MAXMINDDB_FILE, options) + .then(reader => { + debug && console.log("looking for location of "); + debug && console.log(socket.handshake.headers['x-forwarded-for'] || socket.handshake.address); + let country = reader.country(socket.handshake.headers['x-forwarded-for'] || socket.handshake.address); + socket.handshake.query.sessionInfo.userCountry = country.country.isoCode; + }) + .catch(error => { + console.error(error); + }); + } +} + +module.exports = { + wsRouter, + start: (server) => { + if (process.env.uws !== "true") { + io = _io(server, { + maxHttpBufferSize: (parseInt(process.env.maxHttpBufferSize) || 5) * 1e6, + cors: { + origin: "*", + methods: ["GET", "POST", "PUT"] + }, + path: '/socket' + }); + } else { + io = new _io.Server({ + maxHttpBufferSize: (parseInt(process.env.maxHttpBufferSize) || 5) * 1e6, + cors: { + origin: "*", + methods: ["GET", "POST", "PUT"] + }, + path: '/socket', + // transports: ['websocket'], + // upgrade: false + }); + io.attachApp(server); + } + io.on('connection', async (socket) => { + debug && console.log(`WS started:${socket.id}, Query:${JSON.stringify(socket.handshake.query)}`); + socket.peerId = socket.handshake.query.peerId; + socket.identity = socket.handshake.query.identity; + const {projectKey, sessionId} = extractPeerId(socket.peerId); + socket.sessionId = sessionId; + socket.projectKey = projectKey; + socket.lastMessageReceivedAt = Date.now(); + let {c_sessions, c_agents} = await sessions_agents_count(io, socket); + if (socket.identity === IDENTITIES.session) { + if (c_sessions > 0) { + debug && console.log(`session already connected, refusing new connexion`); + io.to(socket.id).emit(SESSION_ALREADY_CONNECTED); + return socket.disconnect(); + } + extractSessionInfo(socket); + if (c_agents > 0) { + debug && console.log(`notifying new session about agent-existence`); + let agents_ids = await get_all_agents_ids(io, socket); + io.to(socket.id).emit(AGENTS_CONNECTED, agents_ids); + } + + } else if (c_sessions <= 0) { + debug && console.log(`notifying new agent about no SESSIONS`); + io.to(socket.id).emit(NO_SESSIONS); + } + socket.join(socket.peerId); + if (io.sockets.adapter.rooms.get(socket.peerId)) { + debug && console.log(`${socket.id} joined room:${socket.peerId}, as:${socket.identity}, members:${io.sockets.adapter.rooms.get(socket.peerId).size}`); + } + if (socket.identity === IDENTITIES.agent) { + if (socket.handshake.query.agentInfo !== undefined) { + socket.handshake.query.agentInfo = JSON.parse(socket.handshake.query.agentInfo); + } + socket.to(socket.peerId).emit(NEW_AGENT, socket.id, socket.handshake.query.agentInfo); + } + + socket.on('disconnect', async () => { + debug && console.log(`${socket.id} disconnected from ${socket.peerId}`); + if (socket.identity === IDENTITIES.agent) { + socket.to(socket.peerId).emit(AGENT_DISCONNECT, socket.id); + } + debug && console.log("checking for number of connected agents and sessions"); + let {c_sessions, c_agents} = await sessions_agents_count(io, socket); + if (c_sessions === -1 && c_agents === -1) { + debug && console.log(`room not found: ${socket.peerId}`); + } + if (c_sessions === 0) { + debug && console.log(`notifying everyone in ${socket.peerId} about no SESSIONS`); + socket.to(socket.peerId).emit(NO_SESSIONS); + } + if (c_agents === 0) { + debug && console.log(`notifying everyone in ${socket.peerId} about no AGENTS`); + socket.to(socket.peerId).emit(NO_AGENTS); + } + }); + + socket.on(UPDATE_EVENT, async (...args) => { + debug && console.log(`${socket.id} sent update event.`); + if (socket.identity !== IDENTITIES.session) { + debug && console.log('Ignoring update event.'); + return + } + socket.handshake.query.sessionInfo = {...socket.handshake.query.sessionInfo, ...args[0]}; + socket.to(socket.peerId).emit(UPDATE_EVENT, args[0]); + }); + + socket.onAny(async (eventName, ...args) => { + socket.lastMessageReceivedAt = Date.now(); + if (socket.identity === IDENTITIES.session) { + debug && console.log(`received event:${eventName}, from:${socket.identity}, sending message to room:${socket.peerId}, members: ${io.sockets.adapter.rooms.get(socket.peerId).size}`); + socket.to(socket.peerId).emit(eventName, args[0]); + } else { + debug && console.log(`received event:${eventName}, from:${socket.identity}, sending message to session of room:${socket.peerId}, members:${io.sockets.adapter.rooms.get(socket.peerId).size}`); + let socketId = await findSessionSocketId(io, socket.peerId); + if (socketId === null) { + debug && console.log(`session not found for:${socket.peerId}`); + io.to(socket.id).emit(NO_SESSIONS); + } else { + debug && console.log("message sent"); + io.to(socketId).emit(eventName, socket.id, args[0]); + } + } + }); + + }); + console.log("WS server started") + setInterval((io) => { + try { + let count = 0; + console.log(` ====== Rooms: ${io.sockets.adapter.rooms.size} ====== `); + const arr = Array.from(io.sockets.adapter.rooms) + const filtered = arr.filter(room => !room[1].has(room[0])) + for (let i of filtered) { + let {projectKey, sessionId} = extractPeerId(i[0]); + if (projectKey !== null && sessionId !== null) { + count++; + } + } + console.log(` ====== Valid Rooms: ${count} ====== `); + if (debug) { + for (let item of filtered) { + console.log(`Room: ${item[0]} connected: ${item[1].size}`) + } + } + } catch (e) { + console.error(e); + } + }, 20000, io); + }, + handlers: { + socketsList, + socketsListByProject, + socketsLive, + socketsLiveByProject + } +}; \ No newline at end of file diff --git a/frontend/app/components/Assist/components/AssistTabs/AssistTabs.tsx b/frontend/app/components/Assist/components/AssistTabs/AssistTabs.tsx index 539c2d8d1..6bacc38fc 100644 --- a/frontend/app/components/Assist/components/AssistTabs/AssistTabs.tsx +++ b/frontend/app/components/Assist/components/AssistTabs/AssistTabs.tsx @@ -21,7 +21,7 @@ const AssistTabs = (props: Props) => {
- {props.userId}'s asdasd asdasdasdasd + {props.userId}'s
@@ -35,7 +35,7 @@ const AssistTabs = (props: Props) => { )} Live Sessions by {props.userId} } + title={
{props.userId}'s Live Sessions
} isDisplayed={ showMenu } content={ showMenu && } onClose={ () => setShowMenu(false) } diff --git a/frontend/app/components/Assist/components/SessionList/SessionList.tsx b/frontend/app/components/Assist/components/SessionList/SessionList.tsx index f556a8f1d..73c7a3a7f 100644 --- a/frontend/app/components/Assist/components/SessionList/SessionList.tsx +++ b/frontend/app/components/Assist/components/SessionList/SessionList.tsx @@ -1,7 +1,7 @@ import React, { useEffect } from 'react'; import { connect } from 'react-redux'; import { fetchLiveList } from 'Duck/sessions'; -import { Loader, NoContent } from 'UI'; +import { Loader, NoContent, Label } from 'UI'; import SessionItem from 'Shared/SessionItem'; interface Props { @@ -22,7 +22,17 @@ function SessionList(props: Props) { title="No live sessions." >
- { props.list.map(session => ) } + { props.list.map(session => ( +
+ {session.pageTitle && session.pageTitle !== '' && ( +
+ + {session.pageTitle} +
+ )} + +
+ )) }
diff --git a/frontend/app/components/Dashboard/Dashboard.js b/frontend/app/components/Dashboard/Dashboard.js index aacda8b07..2b71ef253 100644 --- a/frontend/app/components/Dashboard/Dashboard.js +++ b/frontend/app/components/Dashboard/Dashboard.js @@ -240,11 +240,10 @@ export default class Dashboard extends React.PureComponent { Custom Metrics are not supported for comparison. )} - {/* */} } > -
+
null}/>
diff --git a/frontend/app/components/Dashboard/SideMenu/SideMenuSection.js b/frontend/app/components/Dashboard/SideMenu/SideMenuSection.js index 77d72f013..e26e24da2 100644 --- a/frontend/app/components/Dashboard/SideMenu/SideMenuSection.js +++ b/frontend/app/components/Dashboard/SideMenu/SideMenuSection.js @@ -33,9 +33,6 @@ function SideMenuSection({ title, items, onItemClick, setShowAlerts, siteId }) {
-
- Be proactive by monitoring the metrics you care about the most. -
); diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetriLineChart/CustomMetriLineChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetriLineChart/CustomMetriLineChart.tsx new file mode 100644 index 000000000..ffbbc6b88 --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetriLineChart/CustomMetriLineChart.tsx @@ -0,0 +1,59 @@ +import React from 'react' +import { Styles } from '../../common'; +import { ResponsiveContainer, XAxis, YAxis, CartesianGrid, Area, Tooltip } from 'recharts'; +import { LineChart, Line, Legend } from 'recharts'; + +interface Props { + data: any; + params: any; + seriesMap: any; + colors: any; + onClick?: (event, index) => void; +} +function CustomMetriLineChart(props: Props) { + const { data, params, seriesMap, colors, onClick = () => null } = props; + return ( + + + + + + + + { seriesMap.map((key, index) => ( + + ))} + + + ) +} + +export default CustomMetriLineChart diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetriLineChart/index.ts b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetriLineChart/index.ts new file mode 100644 index 000000000..f05a16274 --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetriLineChart/index.ts @@ -0,0 +1 @@ +export { default } from './CustomMetriLineChart'; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPercentage/CustomMetricPercentage.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPercentage/CustomMetricPercentage.tsx new file mode 100644 index 000000000..ed4f3cc85 --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPercentage/CustomMetricPercentage.tsx @@ -0,0 +1,20 @@ +import React from 'react' + +interface Props { + data: any; + params: any; + colors: any; + onClick?: (event, index) => void; +} +function CustomMetriPercentage(props: Props) { + const { data = {} } = props; + return ( +
+
{data.count}
+
{`${data.previousCount} ( ${data.countProgress}% )`}
+
from previous period.
+
+ ) +} + +export default CustomMetriPercentage; diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPercentage/index.ts b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPercentage/index.ts new file mode 100644 index 000000000..0e1f80170 --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPercentage/index.ts @@ -0,0 +1 @@ +export { default } from './CustomMetricPercentage'; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.css b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.css new file mode 100644 index 000000000..1d1ef3ee4 --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.css @@ -0,0 +1,6 @@ +.wrapper { + background-color: white; + /* border: solid thin $gray-medium; */ + border-radius: 3px; + padding: 10px; +} \ No newline at end of file diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx new file mode 100644 index 000000000..219f4cc98 --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx @@ -0,0 +1,156 @@ +import React from 'react' +import { ResponsiveContainer, Tooltip } from 'recharts'; +import { PieChart, Pie, Cell } from 'recharts'; +import { Styles } from '../../common'; +import { NoContent } from 'UI'; +import { filtersMap } from 'Types/filter/newFilter'; +interface Props { + metric: any, + data: any; + params: any; + // seriesMap: any; + colors: any; + onClick?: (filters) => void; +} + +function CustomMetricPieChart(props: Props) { + const { metric, data = { values: [] }, onClick = () => null } = props; + + const onClickHandler = (event) => { + if (event && !event.payload.group) { + const filters = Array(); + let filter = { ...filtersMap[metric.metricOf] } + filter.value = [event.payload.name] + filter.type = filter.key + delete filter.key + delete filter.operatorOptions + delete filter.category + delete filter.icon + delete filter.label + delete filter.options + + filters.push(filter); + onClick(filters); + } + } + return ( +
+ + + + { + const RADIAN = Math.PI / 180; + let radius1 = 15 + innerRadius + (outerRadius - innerRadius); + let radius2 = innerRadius + (outerRadius - innerRadius); + let x2 = cx + radius1 * Math.cos(-midAngle * RADIAN); + let y2 = cy + radius1 * Math.sin(-midAngle * RADIAN); + let x1 = cx + radius2 * Math.cos(-midAngle * RADIAN); + let y1 = cy + radius2 * Math.sin(-midAngle * RADIAN); + + const percentage = value * 100 / data.values.reduce((a, b) => a + b.sessionCount, 0); + + if (percentage<3){ + return null; + } + + return( + + ) + }} + label={({ + cx, + cy, + midAngle, + innerRadius, + outerRadius, + value, + index + }) => { + const RADIAN = Math.PI / 180; + let radius = 20 + innerRadius + (outerRadius - innerRadius); + let x = cx + radius * Math.cos(-midAngle * RADIAN); + let y = cy + radius * Math.sin(-midAngle * RADIAN); + const percentage = (value / data.values.reduce((a, b) => a + b.sessionCount, 0)) * 100; + let name = data.values[index].name || 'Unidentified'; + name = name.length > 20 ? name.substring(0, 20) + '...' : name; + if (percentage<3){ + return null; + } + return ( + cx ? "start" : "end"} + dominantBaseline="central" + fill='#666' + > + {name || 'Unidentified'} {value} + + ); + }} + // label={({ + // cx, + // cy, + // midAngle, + // innerRadius, + // outerRadius, + // value, + // index + // }) => { + // const RADIAN = Math.PI / 180; + // const radius = 30 + innerRadius + (outerRadius - innerRadius); + // const x = cx + radius * Math.cos(-midAngle * RADIAN); + // const y = cy + radius * Math.sin(-midAngle * RADIAN); + + // return ( + // cx ? "start" : "end"} + // dominantBaseline="top" + // fontSize={10} + // > + // {data.values[index].name} ({value}) + // + // ); + // }} + > + {data.values.map((entry, index) => ( + + ))} + + + + + +
Top 5
+
+
+ ) +} + +export default CustomMetricPieChart; diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/index.ts b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/index.ts new file mode 100644 index 000000000..6bdaf2270 --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/index.ts @@ -0,0 +1 @@ +export { default } from './CustomMetricPieChart'; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/CustomMetricTable.css b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/CustomMetricTable.css new file mode 100644 index 000000000..1d1ef3ee4 --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/CustomMetricTable.css @@ -0,0 +1,6 @@ +.wrapper { + background-color: white; + /* border: solid thin $gray-medium; */ + border-radius: 3px; + padding: 10px; +} \ No newline at end of file diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/CustomMetricTable.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/CustomMetricTable.tsx new file mode 100644 index 000000000..6a9481077 --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/CustomMetricTable.tsx @@ -0,0 +1,64 @@ +import React from 'react' +import { Table } from '../../common'; +import { List } from 'immutable'; +import { filtersMap } from 'Types/filter/newFilter'; +import { NoContent } from 'UI'; +import { tableColumnName } from 'App/constants/filterOptions'; + +const getColumns = (metric) => { + return [ + { + key: 'name', + title: tableColumnName[metric.metricOf], + toText: name => name || 'Unidentified', + width: '70%', + }, + { + key: 'sessionCount', + title: 'Sessions', + toText: sessions => sessions, + width: '30%', + }, + ] +} + +interface Props { + metric?: any, + data: any; + onClick?: (filters) => void; +} +function CustomMetriTable(props: Props) { + const { metric = {}, data = { values: [] }, onClick = () => null } = props; + const rows = List(data.values); + + const onClickHandler = (event, data) => { + const filters = Array(); + let filter = { ...filtersMap[metric.metricOf] } + filter.value = [data.name] + filter.type = filter.key + delete filter.key + delete filter.operatorOptions + delete filter.category + delete filter.icon + delete filter.label + delete filter.options + + filters.push(filter); + onClick(filters); + } + return ( +
+ + + + + ) +} + +export default CustomMetriTable; diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/index.ts b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/index.ts new file mode 100644 index 000000000..dc43c93b4 --- /dev/null +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTable/index.ts @@ -0,0 +1 @@ +export { default } from './CustomMetricTable'; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidget/CustomMetricWidget.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidget/CustomMetricWidget.tsx index bbf37408a..c5fd2ad3f 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidget/CustomMetricWidget.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidget/CustomMetricWidget.tsx @@ -2,22 +2,25 @@ import React, { useEffect, useState } from 'react'; import { connect } from 'react-redux'; import { Loader, NoContent, Icon, Popup } from 'UI'; import { Styles } from '../../common'; -import { ResponsiveContainer, AreaChart, XAxis, YAxis, CartesianGrid, Area, Tooltip } from 'recharts'; -import { LineChart, Line, Legend } from 'recharts'; +import { ResponsiveContainer } from 'recharts'; import { LAST_24_HOURS, LAST_30_MINUTES, YESTERDAY, LAST_7_DAYS } from 'Types/app/period'; import stl from './CustomMetricWidget.css'; import { getChartFormatter, getStartAndEndTimestampsByDensity } from 'Types/dashboard/helper'; import { init, edit, remove, setAlertMetricId, setActiveWidget, updateActiveState } from 'Duck/customMetrics'; import APIClient from 'App/api_client'; import { setShowAlerts } from 'Duck/dashboard'; +import CustomMetriLineChart from '../CustomMetriLineChart'; +import CustomMetricPieChart from '../CustomMetricPieChart'; +import CustomMetricPercentage from '../CustomMetricPercentage'; +import CustomMetricTable from '../CustomMetricTable'; const customParams = rangeName => { const params = { density: 70 } - if (rangeName === LAST_24_HOURS) params.density = 70 - if (rangeName === LAST_30_MINUTES) params.density = 70 - if (rangeName === YESTERDAY) params.density = 70 - if (rangeName === LAST_7_DAYS) params.density = 70 + // if (rangeName === LAST_24_HOURS) params.density = 70 + // if (rangeName === LAST_30_MINUTES) params.density = 70 + // if (rangeName === YESTERDAY) params.density = 70 + // if (rangeName === LAST_7_DAYS) params.density = 70 return params } @@ -47,11 +50,14 @@ function CustomMetricWidget(props: Props) { const colors = Styles.customMetricColors; const params = customParams(period.rangeName) - const gradientDef = Styles.gradientDef(); const metricParams = { ...params, metricId: metric.metricId, viewType: 'lineChart', startDate: period.start, endDate: period.end } + const isLineChart = metric.viewType === 'lineChart'; + const isProgress = metric.viewType === 'progress'; + const isTable = metric.viewType === 'table'; + const isPieChart = metric.viewType === 'pieChart'; useEffect(() => { - new APIClient()['post']('/custom_metrics/chart', { ...metricParams, q: metric.name }) + new APIClient()['post'](`/custom_metrics/${metricParams.metricId}/chart`, { ...metricParams, q: metric.name }) .then(response => response.json()) .then(({ errors, data }) => { if (errors) { @@ -74,12 +80,33 @@ function CustomMetricWidget(props: Props) { }).finally(() => setLoading(false)); }, [period]) + const clickHandlerTable = (filters) => { + const activeWidget = { + widget: metric, + period: period, + ...period.toTimestamps(), + filters, + } + props.setActiveWidget(activeWidget); + } + const clickHandler = (event, index) => { if (event) { const payload = event.activePayload[0].payload; const timestamp = payload.timestamp; - const { startTimestamp, endTimestamp } = getStartAndEndTimestampsByDensity(timestamp, period.start, period.end, params.density); - props.setActiveWidget({ widget: metric, startTimestamp, endTimestamp, timestamp: payload.timestamp, index }) + const periodTimestamps = metric.metricType === 'timeseries' ? + getStartAndEndTimestampsByDensity(timestamp, period.start, period.end, params.density) : + period.toTimestamps(); + + const activeWidget = { + widget: metric, + period: period, + ...periodTimestamps, + timestamp: payload.timestamp, + index, + } + + props.setActiveWidget(activeWidget); } } @@ -89,64 +116,59 @@ function CustomMetricWidget(props: Props) { return (
-
+
{metric.name}
- + {!isTable && !isPieChart && } props.init(metric)} /> updateActiveState(metric.metricId, false)} />
-
+
- - - - - - - - - - - - - { seriesMap.map((key, index) => ( - + {isLineChart && ( + - ))} - + )} + + {isPieChart && ( + + )} + + {isProgress && ( + + )} + + {isTable && ( + + )} + diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.css b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.css index 1d1ef3ee4..2088330ba 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.css +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.css @@ -1,6 +1,14 @@ .wrapper { - background-color: white; + background-color: $gray-light; /* border: solid thin $gray-medium; */ border-radius: 3px; - padding: 10px; + padding: 20px; +} + +.innerWapper { + border-radius: 3px; + width: 70%; + margin: 0 auto; + background-color: white; + min-height: 220px; } \ No newline at end of file diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.tsx index 8af9784d5..109243252 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.tsx @@ -1,16 +1,20 @@ import React, { useEffect, useState, useRef } from 'react'; import { connect } from 'react-redux'; -import { Loader, NoContent, Icon } from 'UI'; +import { Loader, NoContent, SegmentSelection, Icon } from 'UI'; import { Styles } from '../../common'; -import { ResponsiveContainer, XAxis, YAxis, CartesianGrid, Tooltip, LineChart, Line, Legend } from 'recharts'; +// import { ResponsiveContainer, XAxis, YAxis, CartesianGrid, Tooltip, LineChart, Line, Legend } from 'recharts'; import Period, { LAST_24_HOURS, LAST_30_MINUTES, YESTERDAY, LAST_7_DAYS } from 'Types/app/period'; import stl from './CustomMetricWidgetPreview.css'; import { getChartFormatter } from 'Types/dashboard/helper'; import { remove } from 'Duck/customMetrics'; import DateRange from 'Shared/DateRange'; import { edit } from 'Duck/customMetrics'; +import CustomMetriLineChart from '../CustomMetriLineChart'; +import CustomMetricPercentage from '../CustomMetricPercentage'; +import CustomMetricTable from '../CustomMetricTable'; import APIClient from 'App/api_client'; +import CustomMetricPieChart from '../CustomMetricPieChart'; const customParams = rangeName => { const params = { density: 70 } @@ -43,8 +47,9 @@ function CustomMetricWidget(props: Props) { const params = customParams(period.rangeName) const gradientDef = Styles.gradientDef(); const metricParams = { ...params, metricId: metric.metricId, viewType: 'lineChart' } - const prevMetricRef = useRef(); + const isTimeSeries = metric.metricType === 'timeseries'; + const isTable = metric.metricType === 'table'; useEffect(() => { // Check for title change @@ -83,11 +88,52 @@ function CustomMetricWidget(props: Props) { props.edit({ ...changedDates, rangeName: changedDates.rangeValue }); } + const chagneViewType = (e, { name, value }) => { + props.edit({ [ name ]: value }); + } + return (
-
+
Preview
-
+
+ {isTimeSeries && ( + <> + Visualization + + + )} + + {isTable && ( + <> + Visualization + + + )} +
+ Time Range
-
+
- - - - - - - - { seriesMap.map((key, index) => ( - - ))} - - +
+ {metric.name} +
+
+ { isTimeSeries && ( + <> + { metric.viewType === 'progress' && ( + + )} + { metric.viewType === 'lineChart' && ( + + )} + + )} + + { isTable && ( + <> + { metric.viewType === 'table' ? ( + + ) : ( + + )} + + )} +
diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricsWidgets.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricsWidgets.tsx index 6cf633518..4db7abfd4 100644 --- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricsWidgets.tsx +++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricsWidgets.tsx @@ -5,6 +5,7 @@ import CustomMetricWidget from './CustomMetricWidget'; import AlertFormModal from 'App/components/Alerts/AlertFormModal'; import { init as initAlert } from 'Duck/alerts'; import LazyLoad from 'react-lazyload'; +import CustomMetrics from 'App/components/shared/CustomMetrics'; interface Props { fetchList: Function; @@ -15,6 +16,7 @@ interface Props { function CustomMetricsWidgets(props: Props) { const { list } = props; const [activeMetricId, setActiveMetricId] = useState(null); + const activeList = list.filter(item => item.active); useEffect(() => { props.fetchList() @@ -22,19 +24,34 @@ function CustomMetricsWidgets(props: Props) { return ( <> - {list.filter(item => item.active).map((item: any) => ( - - { - setActiveMetricId(item.metricId) - props.initAlert({ query: { left: item.series.first().seriesId }}) - }} - /> - - ))} +
+ {activeList.map((item: any) => ( + + { + setActiveMetricId(item.metricId) + props.initAlert({ query: { left: item.series.first().seriesId }}) + }} + /> + + ))} +
+ + {list.size === 0 && ( +
+
Be proactive by monitoring the metrics you care about the most.
+ +
+ )} + + {list.size > 0 && activeList && activeList.size === 0 && ( +
+
It's blank here, add a metric to this section.
+
+ )} { const isMoreThanK = count >= 1000; @@ -14,6 +15,7 @@ const countView = count => { export default { customMetricColors, colors, + colorsPie, colorsx, compareColors, compareColorsx, diff --git a/frontend/app/components/Dashboard/Widgets/common/Table.js b/frontend/app/components/Dashboard/Widgets/common/Table.js index 0aecca5ea..e1b6a503c 100644 --- a/frontend/app/components/Dashboard/Widgets/common/Table.js +++ b/frontend/app/components/Dashboard/Widgets/common/Table.js @@ -16,7 +16,9 @@ export default class Table extends React.PureComponent { rowProps, rowClass = '', small = false, - compare = false + compare = false, + maxHeight = 200, + onRowClick = null, } = this.props; const { showAll } = this.state; @@ -30,9 +32,13 @@ export default class Table extends React.PureComponent {
{ title }
) }
-
+
{ rows.take(showAll ? 10 : (small ? 3 : 5)).map(row => ( -
+
onRowClick(e, row) : () => null} + > { cols.map(({ cellClass = '', className = '', Component, key, toText = t => t, width }) => (
{ Component ? @@ -41,21 +47,20 @@ export default class Table extends React.PureComponent {
)) }
- )) } - - { rows.size > (small ? 3 : 5) && !showAll && -
+ )) } +
+ { rows.size > (small ? 3 : 5) && !showAll && +
} -
); } diff --git a/frontend/app/components/Onboarding/components/OnboardingTabs/ProjectCodeSnippet/ProjectCodeSnippet.js b/frontend/app/components/Onboarding/components/OnboardingTabs/ProjectCodeSnippet/ProjectCodeSnippet.js index fb52d0e5f..bf0e83791 100644 --- a/frontend/app/components/Onboarding/components/OnboardingTabs/ProjectCodeSnippet/ProjectCodeSnippet.js +++ b/frontend/app/components/Onboarding/components/OnboardingTabs/ProjectCodeSnippet/ProjectCodeSnippet.js @@ -17,9 +17,11 @@ const inputModeOptions = [ const codeSnippet = ` `; diff --git a/frontend/app/components/shared/CustomMetrics/CustomMetricForm/CustomMetricForm.tsx b/frontend/app/components/shared/CustomMetrics/CustomMetricForm/CustomMetricForm.tsx index 7700a7a29..28a0cbc42 100644 --- a/frontend/app/components/shared/CustomMetrics/CustomMetricForm/CustomMetricForm.tsx +++ b/frontend/app/components/shared/CustomMetrics/CustomMetricForm/CustomMetricForm.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Form, SegmentSelection, Button, IconButton } from 'UI'; +import { Form, Button, IconButton, HelpText } from 'UI'; import FilterSeries from '../FilterSeries'; import { connect } from 'react-redux'; import { edit as editMetric, save, addSeries, removeSeries, remove } from 'Duck/customMetrics'; @@ -7,7 +7,9 @@ import CustomMetricWidgetPreview from 'App/components/Dashboard/Widgets/CustomMe import { confirm } from 'UI/Confirmation'; import { toast } from 'react-toastify'; import cn from 'classnames'; - +import DropdownPlain from '../../DropdownPlain'; +import { metricTypes, metricOf, issueOptions } from 'App/constants/filterOptions'; +import { FilterKey } from 'Types/filter/filterType'; interface Props { metric: any; editMetric: (metric, shouldFetch?) => void; @@ -21,6 +23,13 @@ interface Props { function CustomMetricForm(props: Props) { const { metric, loading } = props; + // const metricOfOptions = metricOf.filter(i => i.key === metric.metricType); + const timeseriesOptions = metricOf.filter(i => i.type === 'timeseries'); + const tableOptions = metricOf.filter(i => i.type === 'table'); + const isTable = metric.metricType === 'table'; + const isTimeSeries = metric.metricType === 'timeseries'; + const _issueOptions = [{ text: 'All', value: 'all' }].concat(issueOptions); + const addSeries = () => { props.addSeries(); @@ -30,12 +39,33 @@ function CustomMetricForm(props: Props) { props.removeSeries(index); } - const write = ({ target: { value, name } }) => props.editMetric({ ...metric, [ name ]: value }, false); + const write = ({ target: { value, name } }) => props.editMetric({ [ name ]: value }, false); + const writeOption = (e, { value, name }) => { + props.editMetric({ [ name ]: value }, false); - const changeConditionTab = (e, { name, value }) => { - props.editMetric({[ 'viewType' ]: value }); + if (name === 'metricValue') { + props.editMetric({ metricValue: [value] }, false); + } + + if (name === 'metricOf') { + if (value === FilterKey.ISSUE) { + props.editMetric({ metricValue: ['all'] }, false); + } + } + + if (name === 'metricType') { + if (value === 'timeseries') { + props.editMetric({ metricOf: timeseriesOptions[0].value, viewType: 'lineChart' }, false); + } else if (value === 'table') { + props.editMetric({ metricOf: tableOptions[0].value, viewType: 'table' }, false); + } + } }; + // const changeConditionTab = (e, { name, value }) => { + // props.editMetric({[ 'viewType' ]: value }); + // }; + const save = () => { props.save(metric).then(() => { toast.success(metric.exists() ? 'Updated succesfully.' : 'Created succesfully.'); @@ -79,42 +109,92 @@ function CustomMetricForm(props: Props) {
- Timeseries - of -
- -
+ + + {metric.metricType === 'timeseries' && ( + <> + of + + + )} + + {metric.metricType === 'table' && ( + <> + of + + + )} + + {metric.metricOf === FilterKey.ISSUE && ( + <> + issue type + + + )} + + {metric.metricType === 'table' && ( + <> + showing + + + )}
- - {metric.series && metric.series.size > 0 && metric.series.map((series: any, index: number) => ( + + {metric.series && metric.series.size > 0 && metric.series.take(isTable ? 1 : metric.series.size).map((series: any, index: number) => (
removeSeries(index)} canDelete={metric.series.size > 1} + emptyMessage={isTable ? + 'Filter data using any event or attribute. Use Add Step button below to do so.' : + 'Add user event or filter to define the series by clicking Add Step.' + } />
))}
-
2})}> - -
+ { isTimeSeries && ( +
2})}> + +
+ )}
diff --git a/frontend/app/components/shared/CustomMetrics/CustomMetrics.tsx b/frontend/app/components/shared/CustomMetrics/CustomMetrics.tsx index aedd4a097..77a49a7e1 100644 --- a/frontend/app/components/shared/CustomMetrics/CustomMetrics.tsx +++ b/frontend/app/components/shared/CustomMetrics/CustomMetrics.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { IconButton } from 'UI'; import { connect } from 'react-redux'; import { edit, init } from 'Duck/customMetrics'; diff --git a/frontend/app/components/shared/CustomMetrics/FilterSeries/FilterSeries.tsx b/frontend/app/components/shared/CustomMetrics/FilterSeries/FilterSeries.tsx index 0f5df220b..5327308dd 100644 --- a/frontend/app/components/shared/CustomMetrics/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/shared/CustomMetrics/FilterSeries/FilterSeries.tsx @@ -25,15 +25,20 @@ interface Props { editSeriesFilterFilter: typeof editSeriesFilterFilter; editSeriesFilter: typeof editSeriesFilter; removeSeriesFilterFilter: typeof removeSeriesFilterFilter; + hideHeader?: boolean; + emptyMessage?: any; } function FilterSeries(props: Props) { - const { canDelete } = props; + const { canDelete, hideHeader = false, emptyMessage = 'Add user event or filter to define the series by clicking Add Step.' } = props; const [expanded, setExpanded] = useState(true) const { series, seriesIndex } = props; const onAddFilter = (filter) => { filter.value = [""] + if (filter.hasOwnProperty('filters')) { + filter.filters = filter.filters.map(i => ({ ...i, value: [""] })) + } props.addSeriesFilterFilter(seriesIndex, filter); } @@ -51,9 +56,9 @@ function FilterSeries(props: Props) { return (
-
+
- props.updateSeries(seriesIndex, { name }) } /> + props.updateSeries(seriesIndex, { name }) } />
@@ -78,10 +83,10 @@ function FilterSeries(props: Props) { onChangeEventsOrder={onChangeEventsOrder} /> ): ( -
Add user event or filter to define the series by clicking Add Step.
+
{emptyMessage}
)}
-
+
void; + seriesIndex?: number; } function SeriesName(props: Props) { + const { seriesIndex = 1 } = props; const [editing, setEditing] = useState(false) const [name, setName] = useState(props.name) const ref = useRef(null) @@ -36,7 +38,7 @@ function SeriesName(props: Props) { setEditing(true)} /> ) : ( -
{name}
+
{name.trim() === '' ? 'Seriess ' + (seriesIndex + 1) : name }
)}
setEditing(true)}>
diff --git a/frontend/app/components/shared/CustomMetrics/SessionListModal/SessionListModal.tsx b/frontend/app/components/shared/CustomMetrics/SessionListModal/SessionListModal.tsx index 9bc3e56a0..d6434fadb 100644 --- a/frontend/app/components/shared/CustomMetrics/SessionListModal/SessionListModal.tsx +++ b/frontend/app/components/shared/CustomMetrics/SessionListModal/SessionListModal.tsx @@ -5,7 +5,6 @@ import stl from './SessionListModal.css'; import { connect } from 'react-redux'; import { fetchSessionList, setActiveWidget } from 'Duck/customMetrics'; import { DateTime } from 'luxon'; - interface Props { loading: boolean; list: any; @@ -24,7 +23,8 @@ function SessionListModal(props: Props) { props.fetchSessionList({ metricId: activeWidget.widget.metricId, startDate: activeWidget.startTimestamp, - endDate: activeWidget.endTimestamp + endDate: activeWidget.endTimestamp, + filters: activeWidget.filters || [], }); }, [activeWidget]); @@ -57,9 +57,9 @@ function SessionListModal(props: Props) { const writeOption = (e, { name, value }) => setActiveSeries(value); const filteredSessions = getListSessionsBySeries(activeSeries); - const startTime = DateTime.fromMillis(activeWidget.startTimestamp).toFormat('LLL dd, yyyy HH:mm a'); const endTime = DateTime.fromMillis(activeWidget.endTimestamp).toFormat('LLL dd, yyyy HH:mm a'); + return ( void; icon?: string; direction?: string; value: any; + multiple?: boolean; } export default function DropdownPlain(props: Props) { - const { value, options, icon = "chevron-down", direction = "left" } = props; + const { name = "sort", value, options, icon = "chevron-down", direction = "right", multiple = false } = props; return (
: null } /> diff --git a/frontend/app/components/shared/FilterDropdown/FilterDropdown.js b/frontend/app/components/shared/FilterDropdown/FilterDropdown.js index 66da1f586..5b8a4ac76 100644 --- a/frontend/app/components/shared/FilterDropdown/FilterDropdown.js +++ b/frontend/app/components/shared/FilterDropdown/FilterDropdown.js @@ -100,18 +100,20 @@ const FilterDropdown = props => {
)} {showDropdown && ( -
-
SELECT FILTER
- {filterKeys.filter(f => !filterKeyMaps.includes(f.key)).map(f => ( -
onFilterKeySelect(f.key)} - className={cn(stl.filterItem, 'py-3 -mx-3 px-3 flex items-center cursor-pointer')} - > - - {f.name} -
- ))} +
+
SELECT FILTER
+
+ {filterKeys.filter(f => !filterKeyMaps.includes(f.key)).map(f => ( +
onFilterKeySelect(f.key)} + className={cn(stl.filterItem, 'py-3 -mx-3 px-3 flex items-center cursor-pointer')} + > + + {f.name} +
+ ))} +
)} {filterKey && ( diff --git a/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx b/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx index 333188b3e..92baa3d51 100644 --- a/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx +++ b/frontend/app/components/shared/Filters/FilterAutoComplete/FilterAutoComplete.tsx @@ -47,15 +47,17 @@ function FilterAutoComplete(props: Props) { const requestValues = (q) => { setLoading(true); - return new APIClient()[method?.toLowerCase()](endpoint, { ...params, q }) - .then(response => response.json()) - .then(({ errors, data }) => { - if (errors) { - // this.setError(); - } else { - setOptions(data); - } - }).finally(() => setLoading(false)); + return new APIClient()[method?.toLocaleLowerCase()](endpoint, { ...params, q }) + .then(response => { + if (response.ok) { + return response.json(); + } + throw new Error(response.statusText); + }) + .then(({ data }) => { + setOptions(data); + }) + .finally(() => setLoading(false)); } const debouncedRequestValues = React.useCallback(debounce(requestValues, 300), []); diff --git a/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx b/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx index 96156e6db..542dfce1c 100644 --- a/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx +++ b/frontend/app/components/shared/Filters/FilterAutoCompleteLocal/FilterAutoCompleteLocal.tsx @@ -13,6 +13,8 @@ interface Props { onSelect: (e, item) => void; value: any; icon?: string; + type?: string; + isMultilple?: boolean; } function FilterAutoCompleteLocal(props: Props) { @@ -24,6 +26,8 @@ function FilterAutoCompleteLocal(props: Props) { onAddValue = () => null, value = '', icon = null, + type = "text", + isMultilple = true, } = props; const [showModal, setShowModal] = useState(true) const [query, setQuery] = useState(value); @@ -59,7 +63,7 @@ function FilterAutoCompleteLocal(props: Props) { onFocus={ () => setShowModal(true)} value={ query } autoFocus={ true } - type="text" + type={ type } placeholder={ placeholder } onKeyDown={handleKeyDown} /> @@ -71,7 +75,7 @@ function FilterAutoCompleteLocal(props: Props) {
- { !showOrButton &&
or
} + { !showOrButton && isMultilple &&
or
}
); } diff --git a/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx b/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx index db0bedf32..6a3829699 100644 --- a/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx +++ b/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx @@ -4,6 +4,8 @@ import FilterSelection from '../FilterSelection'; import FilterValue from '../FilterValue'; import { Icon } from 'UI'; import FilterSource from '../FilterSource'; +import { FilterType } from 'App/types/filter/filterType'; +import SubFilterItem from '../SubFilterItem'; interface Props { filterIndex: number; @@ -15,9 +17,14 @@ interface Props { function FilterItem(props: Props) { const { isFilter = false, filterIndex, filter } = props; const canShowValues = !(filter.operator === "isAny" || filter.operator === "onAny" || filter.operator === "isUndefined"); + const isSubFilter = filter.type === FilterType.SUB_FILTERS; const replaceFilter = (filter) => { - props.onUpdate({ ...filter, value: [""]}); + props.onUpdate({ + ...filter, + value: [""], + filters: filter.filters ? filter.filters.map(i => ({ ...i, value: [""] })) : [] + }); }; const onOperatorChange = (e, { name, value }) => { @@ -28,6 +35,19 @@ function FilterItem(props: Props) { props.onUpdate({ ...filter, sourceOperator: value }) } + const onUpdateSubFilter = (subFilter, subFilterIndex) => { + props.onUpdate({ + ...filter, + filters: filter.filters.map((i, index) => { + if (index === subFilterIndex) { + return subFilter; + } + return i; + }) + }); + }; + + return (
@@ -48,14 +68,31 @@ function FilterItem(props: Props) { )} {/* Filter values */} - - { canShowValues && () } - + { !isSubFilter && ( + <> + + { canShowValues && () } + + )} + + {/* filters */} + {isSubFilter && ( +
+ {filter.filters.map((subFilter, subFilterIndex) => ( + onUpdateSubFilter(f, subFilterIndex)} + onRemoveFilter={props.onRemoveFilter} + /> + ))} +
+ )}
Events Order
} - content={ `Events Order` } + content={ `Select the operator to be applied between events in your search.` } size="tiny" inverted position="top center" diff --git a/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx b/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx index 10f10a428..ba7b8650e 100644 --- a/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx +++ b/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx @@ -63,7 +63,7 @@ function FilterValue(props: Props) { } const renderValueFiled = (value, valueIndex) => { - const showOrButton = valueIndex === lastIndex; + const showOrButton = valueIndex === lastIndex && filter.type !== FilterType.NUMBER; switch(filter.type) { case FilterType.STRING: return ( @@ -113,15 +113,40 @@ function FilterValue(props: Props) { maxDuration={ durationValues.maxDuration } /> ) + case FilterType.NUMBER_MULTIPLE: + return ( + onRemoveValue(valueIndex)} + onSelect={(e, item) => debounceOnSelect(e, item, valueIndex)} + icon={filter.icon} + type="number" + /> + ) case FilterType.NUMBER: return ( - onChange(e, { value: e.target.value }, valueIndex)} + showCloseButton={showCloseButton} + showOrButton={showOrButton} + onAddValue={onAddValue} + onRemoveValue={() => onRemoveValue(valueIndex)} + onSelect={(e, item) => debounceOnSelect(e, item, valueIndex)} + icon={filter.icon} + type="number" + isMultilple={false} /> + // onChange(e, { value: e.target.value }, valueIndex)} + // /> ) case FilterType.MULTIPLE: return ( diff --git a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.css b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.css index d93803884..010042bf3 100644 --- a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.css +++ b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.css @@ -5,6 +5,7 @@ display: flex; align-items: center; height: 26px; + width: 100%; & .right { height: 24px; diff --git a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx index 1381f509a..5787f774f 100644 --- a/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx +++ b/frontend/app/components/shared/Filters/FilterValueDropdown/FilterValueDropdown.tsx @@ -16,31 +16,36 @@ interface Props { showOrButton?: boolean; onRemoveValue?: () => void; onAddValue?: () => void; + isMultilple?: boolean; } function FilterValueDropdown(props: Props) { - const { filter, multiple = false, search = false, options, onChange, value, className = '', showCloseButton = true, showOrButton = true } = props; + const { filter, multiple = false, isMultilple = true, search = false, options, onChange, value, className = '', showCloseButton = true, showOrButton = true } = props; // const options = [] return ( -
- } - /> -
- { showCloseButton &&
} - { showOrButton &&
or
} +
+
+ } + /> +
+ { showCloseButton &&
} + { showOrButton &&
or
} +
+ + { !showOrButton && isMultilple &&
or
}
); } diff --git a/frontend/app/components/shared/Filters/SubFilterItem/SubFilterItem.tsx b/frontend/app/components/shared/Filters/SubFilterItem/SubFilterItem.tsx new file mode 100644 index 000000000..73c8663b9 --- /dev/null +++ b/frontend/app/components/shared/Filters/SubFilterItem/SubFilterItem.tsx @@ -0,0 +1,34 @@ +import { filter } from 'App/components/BugFinder/ManageFilters/savedFilterList.css' +import React from 'react' +import FilterOperator from '../FilterOperator'; +import FilterValue from '../FilterValue'; + +interface Props { + filterIndex: number; + filter: any; // event/filter + onUpdate: (filter) => void; + onRemoveFilter: () => void; + isFilter?: boolean; +} +export default function SubFilterItem(props: Props) { + const { isFilter = false, filterIndex, filter } = props; + const canShowValues = !(filter.operator === "isAny" || filter.operator === "onAny" || filter.operator === "isUndefined"); + + const onOperatorChange = (e, { name, value }) => { + props.onUpdate({ ...filter, operator: value }) + } + + return ( +
+
{filter.label}
+ + + { canShowValues && () } +
+ ) +} diff --git a/frontend/app/components/shared/Filters/SubFilterItem/index.ts b/frontend/app/components/shared/Filters/SubFilterItem/index.ts new file mode 100644 index 000000000..0877700cc --- /dev/null +++ b/frontend/app/components/shared/Filters/SubFilterItem/index.ts @@ -0,0 +1 @@ +export { default } from './SubFilterItem'; \ No newline at end of file diff --git a/frontend/app/components/shared/FunnelSearch/FunnelSearch.tsx b/frontend/app/components/shared/FunnelSearch/FunnelSearch.tsx index 809eb739f..19a3b7ceb 100644 --- a/frontend/app/components/shared/FunnelSearch/FunnelSearch.tsx +++ b/frontend/app/components/shared/FunnelSearch/FunnelSearch.tsx @@ -18,12 +18,6 @@ function FunnelSearch(props: Props) { const onAddFilter = (filter) => { props.addFilter(filter); - // filter.value = [""] - // const newFilters = appliedFilter.filters.concat(filter); - // props.edit({ - // ...appliedFilter.filter, - // filters: newFilters, - // }); } const onUpdateFilter = (filterIndex, filter) => { diff --git a/frontend/app/components/shared/SessionItem/SessionItem.js b/frontend/app/components/shared/SessionItem/SessionItem.js index 51599b3c7..0b7551760 100644 --- a/frontend/app/components/shared/SessionItem/SessionItem.js +++ b/frontend/app/components/shared/SessionItem/SessionItem.js @@ -7,7 +7,8 @@ import { BrowserIcon, CountryFlag, Avatar, - TextEllipsis + TextEllipsis, + Label, } from 'UI'; import { deviceTypeIcon } from 'App/iconNames'; import { toggleFavorite, setSessionPath } from 'Duck/sessions'; @@ -20,14 +21,15 @@ import Counter from './Counter' import { withRouter } from 'react-router-dom'; import SessionMetaList from './SessionMetaList'; import ErrorBars from './ErrorBars'; -import { assist as assistRoute, isRoute } from "App/routes"; +import { assist as assistRoute, liveSession, isRoute } from "App/routes"; import { capitalize } from 'App/utils'; const ASSIST_ROUTE = assistRoute(); +const ASSIST_LIVE_SESSION = liveSession() -const Label = ({ label = '', color = 'color-gray-medium'}) => ( -
{label}
-) +// const Label = ({ label = '', color = 'color-gray-medium'}) => ( +//
{label}
+// ) @connect(state => ({ timezone: state.getIn(['sessions', 'timezone']), siteId: state.getIn([ 'user', 'siteId' ]), @@ -59,16 +61,18 @@ export default class SessionItem extends React.PureComponent { metadata, userSessionsCount, issueTypes, + active, }, timezone, onUserClick = () => null, hasUserFilter = false, disableUser = false, metaList = [], + showActive = false, } = this.props; const formattedDuration = durationFormatted(duration); const hasUserId = userId || userAnonymousId; - const isAssist = isRoute(ASSIST_ROUTE, this.props.location.pathname); + const isAssist = isRoute(ASSIST_ROUTE, this.props.location.pathname) || isRoute(ASSIST_LIVE_SESSION, this.props.location.pathname); const _metaList = Object.keys(metadata).filter(i => metaList.includes(i)).map(key => { const value = metadata[key]; @@ -129,6 +133,11 @@ export default class SessionItem extends React.PureComponent {
+ { isAssist && showActive && ( + + )}
diff --git a/frontend/app/components/shared/SessionSearch/SessionSearch.tsx b/frontend/app/components/shared/SessionSearch/SessionSearch.tsx index 264786fff..17904c1ba 100644 --- a/frontend/app/components/shared/SessionSearch/SessionSearch.tsx +++ b/frontend/app/components/shared/SessionSearch/SessionSearch.tsx @@ -19,12 +19,6 @@ function SessionSearch(props: Props) { const onAddFilter = (filter) => { props.addFilter(filter); - // filter.value = [""] - // const newFilters = appliedFilter.filters.concat(filter); - // props.edit({ - // ...appliedFilter.filter, - // filters: newFilters, - // }); } const onUpdateFilter = (filterIndex, filter) => { diff --git a/frontend/app/components/shared/TrackingCodeModal/ProjectCodeSnippet/ProjectCodeSnippet.js b/frontend/app/components/shared/TrackingCodeModal/ProjectCodeSnippet/ProjectCodeSnippet.js index 1fc8eea7b..e269c2cc7 100644 --- a/frontend/app/components/shared/TrackingCodeModal/ProjectCodeSnippet/ProjectCodeSnippet.js +++ b/frontend/app/components/shared/TrackingCodeModal/ProjectCodeSnippet/ProjectCodeSnippet.js @@ -1,12 +1,12 @@ import React, { useState } from 'react' import { connect } from 'react-redux'; import { editGDPR, saveGDPR } from 'Duck/site'; -import { Controlled as CodeMirror } from 'react-codemirror2'; import copy from 'copy-to-clipboard'; import { Select, Checkbox } from 'UI'; import GDPR from 'Types/site/gdpr'; import cn from 'classnames' import styles from './projectCodeSnippet.css' +import Highlight from 'react-highlight' const inputModeOptions = [ { text: 'Record all inputs', value: 'plain' }, @@ -16,9 +16,11 @@ const inputModeOptions = [ const codeSnippet = ` `; @@ -132,17 +133,9 @@ const ProjectCodeSnippet = props => {
- + + {_snippet} +
You can also setup OpenReplay using Google Tag Manager (GTM).
diff --git a/frontend/app/components/ui/HelpText/HelpText.tsx b/frontend/app/components/ui/HelpText/HelpText.tsx new file mode 100644 index 000000000..92a06a5d0 --- /dev/null +++ b/frontend/app/components/ui/HelpText/HelpText.tsx @@ -0,0 +1,22 @@ + +import React from 'react' +import { Icon, Popup } from 'UI' + +interface Props { + text: string, + className?: string, + position?: string, +} +export default function HelpText(props: Props) { + const { text, className = '', position = 'top center' } = props + return ( +
+
} + content={text} + inverted + position={position} + /> +
+ ) +} diff --git a/frontend/app/components/ui/HelpText/index.ts b/frontend/app/components/ui/HelpText/index.ts new file mode 100644 index 000000000..0868cbffd --- /dev/null +++ b/frontend/app/components/ui/HelpText/index.ts @@ -0,0 +1 @@ +export { default } from './HelpText'; \ No newline at end of file diff --git a/frontend/app/components/ui/SegmentSelection/SegmentSelection.js b/frontend/app/components/ui/SegmentSelection/SegmentSelection.js index a862394ee..74335fddd 100644 --- a/frontend/app/components/ui/SegmentSelection/SegmentSelection.js +++ b/frontend/app/components/ui/SegmentSelection/SegmentSelection.js @@ -9,13 +9,14 @@ class SegmentSelection extends React.Component { } render() { - const { className, list, small = false, extraSmall = false, primary = false, size = "normal" } = this.props; + const { className, list, small = false, extraSmall = false, primary = false, size = "normal", icons = false } = this.props; return (
{ list.map(item => ( @@ -27,8 +28,8 @@ class SegmentSelection extends React.Component { data-active={ this.props.value && this.props.value.value === item.value } onClick={ () => !item.disabled && this.setActiveItem(item) } > - { item.icon && } -
{ item.name }
+ { item.icon && } +
{ item.name }
} disabled={!item.disabled} diff --git a/frontend/app/components/ui/SegmentSelection/segmentSelection.css b/frontend/app/components/ui/SegmentSelection/segmentSelection.css index 20007b010..907f81e37 100644 --- a/frontend/app/components/ui/SegmentSelection/segmentSelection.css +++ b/frontend/app/components/ui/SegmentSelection/segmentSelection.css @@ -12,13 +12,13 @@ padding: 10px; flex: 1; text-align: center; - border-right: solid thin $teal; cursor: pointer; background-color: $gray-lightest; display: flex; align-items: center; justify-content: center; white-space: nowrap; + border-right: solid thin $gray-light; & span svg { fill: $gray-medium; @@ -53,9 +53,16 @@ & .item { color: $teal; background-color: white; + border-right: solid thin $teal; + & svg { + fill: $teal !important; + } &[data-active=true] { background-color: $teal; color: white; + & svg { + fill: white !important; + } } } } @@ -65,6 +72,11 @@ } .extraSmall .item { - padding: 0 4px; + padding: 2px 4px !important; + font-size: 12px; +} + +.icons .item { + padding: 4px !important; font-size: 12px; } \ No newline at end of file diff --git a/frontend/app/components/ui/SlideModal/SlideModal.js b/frontend/app/components/ui/SlideModal/SlideModal.js index cc329463c..92f8ba710 100644 --- a/frontend/app/components/ui/SlideModal/SlideModal.js +++ b/frontend/app/components/ui/SlideModal/SlideModal.js @@ -1,12 +1,24 @@ import styles from './slideModal.css'; import cn from 'classnames'; export default class SlideModal extends React.PureComponent { - componentDidMount() { - document.addEventListener('keydown', this.keyPressHandler); - } + // componentDidMount() { + // document.addEventListener('keydown', this.keyPressHandler); + // } - componentWillUnmount() { - document.removeEventListener('keydown', this.keyPressHandler); + // componentWillUnmount() { + // document.removeEventListener('keydown', this.keyPressHandler); + // } + + componentDidUpdate(prevProps) { + if (prevProps.isDisplayed !== this.props.isDisplayed) { + if (this.props.isDisplayed) { + document.addEventListener('keydown', this.keyPressHandler); + document.body.classList.add('no-scroll'); + } else { + document.removeEventListener('keydown', this.keyPressHandler); + document.body.classList.remove('no-scroll'); + } + } } keyPressHandler = (e) => { diff --git a/frontend/app/components/ui/index.js b/frontend/app/components/ui/index.js index 016a818de..1e0088720 100644 --- a/frontend/app/components/ui/index.js +++ b/frontend/app/components/ui/index.js @@ -54,5 +54,6 @@ export { default as CopyButton } from './CopyButton'; export { default as HighlightCode } from './HighlightCode'; export { default as NoPermission } from './NoPermission'; export { default as NoSessionPermission } from './NoSessionPermission'; +export { default as HelpText } from './HelpText'; export { Input, Modal, Form, Message, Card } from 'semantic-ui-react'; diff --git a/frontend/app/constants/filterOptions.js b/frontend/app/constants/filterOptions.js index 868379e86..560ad7912 100644 --- a/frontend/app/constants/filterOptions.js +++ b/frontend/app/constants/filterOptions.js @@ -1,3 +1,5 @@ +import { FilterKey } from 'Types/filter/filterType'; + export const options = [ { key: 'on', text: 'on', value: 'on' }, { key: 'notOn', text: 'not on', value: 'notOn' }, @@ -54,6 +56,57 @@ export const customOperators = [ { key: '>=', text: '>=', value: '>=' }, ] +export const metricTypes = [ + { text: 'Timeseries', value: 'timeseries' }, + { text: 'Table', value: 'table' }, +]; + +export const tableColumnName = { + [FilterKey.USERID]: 'User', + [FilterKey.ISSUE]: 'Issue', + [FilterKey.USER_BROWSER]: 'Browser', + [FilterKey.USER_DEVICE]: 'Device', + [FilterKey.USER_COUNTRY]: 'Country', + [FilterKey.LOCATION]: 'URL', +} + +export const metricOf = [ + { text: 'Session Count', value: 'sessionCount', type: 'timeseries' }, + { text: 'Users', value: FilterKey.USERID, type: 'table' }, + { text: 'Issues', value: FilterKey.ISSUE, type: 'table' }, + { text: 'Browser', value: FilterKey.USER_BROWSER, type: 'table' }, + { text: 'Device', value: FilterKey.USER_DEVICE, type: 'table' }, + { text: 'Country', value: FilterKey.USER_COUNTRY, type: 'table' }, + { text: 'URL', value: FilterKey.LOCATION, type: 'table' }, +] + +export const methodOptions = [ + { text: 'GET', value: 'GET' }, + { text: 'POST', value: 'POST' }, + { text: 'PUT', value: 'PUT' }, + { text: 'DELETE', value: 'DELETE' }, + { text: 'PATCH', value: 'PATCH' }, + { text: 'HEAD', value: 'HEAD' }, + { text: 'OPTIONS', value: 'OPTIONS' }, + { text: 'TRACE', value: 'TRACE' }, + { text: 'CONNECT', value: 'CONNECT' }, +] + +export const issueOptions = [ + { text: 'Click Rage', value: 'click_rage' }, + { text: 'Dead Click', value: 'dead_click' }, + { text: 'Excessive Scrolling', value: 'excessive_scrolling' }, + { text: 'Bad Request', value: 'bad_request' }, + { text: 'Missing Resource', value: 'missing_resource' }, + { text: 'Memory', value: 'memory' }, + { text: 'CPU', value: 'cpu' }, + { text: 'Slow Resource', value: 'slow_resource' }, + { text: 'Slow Page Load', value: 'slow_page_load' }, + { text: 'Crash', value: 'crash' }, + { text: 'Custom', value: 'custom' }, + { text: 'JS Exception', value: 'js_exception' }, +] + export default { options, baseOperators, @@ -62,4 +115,8 @@ export default { booleanOperators, customOperators, getOperatorsByKeys, + metricTypes, + metricOf, + issueOptions, + methodOptions, } \ No newline at end of file diff --git a/frontend/app/duck/customMetrics.js b/frontend/app/duck/customMetrics.js index f27429130..e6713acb4 100644 --- a/frontend/app/duck/customMetrics.js +++ b/frontend/app/duck/customMetrics.js @@ -187,7 +187,7 @@ export const init = (instance = null, forceNull = false) => (dispatch, getState) export const fetchSessionList = (params) => (dispatch, getState) => { dispatch({ types: array(FETCH_SESSION_LIST), - call: client => client.post(`/custom_metrics/sessions`, { ...params }), + call: client => client.post(`/custom_metrics/${params.metricId}/sessions`, { ...params }), }); } diff --git a/frontend/app/duck/filters.js b/frontend/app/duck/filters.js index 132996797..16c16aa5e 100644 --- a/frontend/app/duck/filters.js +++ b/frontend/app/duck/filters.js @@ -1,4 +1,4 @@ -import { fromJS, List, Map, Set } from 'immutable'; +import { List, Map, Set } from 'immutable'; import { errors as errorsRoute, isRoute } from "App/routes"; import Filter from 'Types/filter'; import SavedFilter from 'Types/filter/savedFilter'; @@ -8,15 +8,6 @@ import withRequestState, { RequestTypes } from './requestStateCreator'; import { fetchList as fetchSessionList } from './sessions'; import { fetchList as fetchErrorsList } from './errors'; import { fetchListType, fetchType, saveType, editType, initType, removeType } from './funcTools/crud/types'; -import logger from 'App/logger'; - -import { newFiltersList } from 'Types/filter' -import NewFilter, { filtersMap } from 'Types/filter/newFilter'; - - -// for (var i = 0; i < newFiltersList.length; i++) { -// filterOptions[newFiltersList[i].category] = newFiltersList.filter(filter => filter.category === newFiltersList[i].category) -// } const ERRORS_ROUTE = errorsRoute(); @@ -44,11 +35,8 @@ const ADD_ATTRIBUTE = 'filters/ADD_ATTRIBUTE'; const EDIT_ATTRIBUTE = 'filters/EDIT_ATTRIBUTE'; const REMOVE_ATTRIBUTE = 'filters/REMOVE_ATTRIBUTE'; const SET_ACTIVE_FLOW = 'filters/SET_ACTIVE_FLOW'; - const UPDATE_VALUE = 'filters/UPDATE_VALUE'; -const REFRESH_FILTER_OPTIONS = 'filters/REFRESH_FILTER_OPTIONS'; - const initialState = Map({ instance: Filter(), activeFilter: null, diff --git a/frontend/app/duck/search.js b/frontend/app/duck/search.js index ad4ea944c..3d15ae950 100644 --- a/frontend/app/duck/search.js +++ b/frontend/app/duck/search.js @@ -107,14 +107,15 @@ export const checkFilterValue = (value) => { return Array.isArray(value) ? (value.length === 0 ? [""] : value) : [value]; } -export const filterMap = ({category, value, key, operator, sourceOperator, source, custom, isEvent }) => ({ +export const filterMap = ({category, value, key, operator, sourceOperator, source, custom, isEvent, filters }) => ({ value: checkValues(key, value), custom, type: category === FilterCategory.METADATA ? FilterKey.METADATA : key, operator, source: category === FilterCategory.METADATA ? key : source, sourceOperator, - isEvent + isEvent, + filters: filters ? filters.map(filterMap) : [], }); const reduceThenFetchResource = actionCreator => (...args) => (dispatch, getState) => { @@ -233,6 +234,10 @@ export const hasFilterApplied = (filters, filter) => { export const addFilter = (filter) => (dispatch, getState) => { filter.value = checkFilterValue(filter.value); + filter.filters = filter.filters ? filter.filters.map(subFilter => ({ + ...subFilter, + value: checkFilterValue(subFilter.value), + })) : null; const instance = getState().getIn([ 'search', 'instance']); if (hasFilterApplied(instance.filters, filter)) { diff --git a/frontend/app/styles/main.css b/frontend/app/styles/main.css index 81e5ab814..3b7f5fe4b 100644 --- a/frontend/app/styles/main.css +++ b/frontend/app/styles/main.css @@ -141,4 +141,10 @@ margin: 25px 0; background-color: $gray-light; +} + +.no-scroll { + height: 100vh; + overflow-y: hidden; + padding-right: 15px; } \ No newline at end of file diff --git a/frontend/app/svg/icons/filters/perfromance-network-request.svg b/frontend/app/svg/icons/filters/perfromance-network-request.svg new file mode 100644 index 000000000..7c4028c89 --- /dev/null +++ b/frontend/app/svg/icons/filters/perfromance-network-request.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/app/svg/icons/graph-up-arrow.svg b/frontend/app/svg/icons/graph-up-arrow.svg new file mode 100644 index 000000000..fd582e467 --- /dev/null +++ b/frontend/app/svg/icons/graph-up-arrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/hash.svg b/frontend/app/svg/icons/hash.svg new file mode 100644 index 000000000..4621b1dac --- /dev/null +++ b/frontend/app/svg/icons/hash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/pie-chart-fill.svg b/frontend/app/svg/icons/pie-chart-fill.svg new file mode 100644 index 000000000..6aa71eb89 --- /dev/null +++ b/frontend/app/svg/icons/pie-chart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/app/svg/icons/table.svg b/frontend/app/svg/icons/table.svg new file mode 100644 index 000000000..5e70d22c4 --- /dev/null +++ b/frontend/app/svg/icons/table.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/app/types/app/period.js b/frontend/app/types/app/period.js index 5e5e9aba8..deebf9cad 100644 --- a/frontend/app/types/app/period.js +++ b/frontend/app/types/app/period.js @@ -103,5 +103,11 @@ export default Record({ endTimestamp: this.end, }; }, + toTimestampstwo() { + return { + startTimestamp: this.start / 1000, + endTimestamp: this.end / 1000, + }; + }, } }); \ No newline at end of file diff --git a/frontend/app/types/customMetric.js b/frontend/app/types/customMetric.js index d5238a0aa..9db8e920e 100644 --- a/frontend/app/types/customMetric.js +++ b/frontend/app/types/customMetric.js @@ -3,6 +3,7 @@ import { List } from 'immutable'; import Filter from 'Types/filter'; import { validateName } from 'App/validate'; import { LAST_7_DAYS } from 'Types/app/period'; +import { FilterKey } from 'Types/filter/filterType'; import { filterMap } from 'Duck/search'; export const FilterSeries = Record({ @@ -27,6 +28,10 @@ export const FilterSeries = Record({ export default Record({ metricId: undefined, name: 'Series', + metricType: 'timeseries', + metricOf: 'sessionCount', + metricValue: ['sessionCount'], + metricFormat: 'sessionCount', viewType: 'lineChart', series: List(), isPublic: true, @@ -43,11 +48,13 @@ export default Record({ toSaveData() { const js = this.toJS(); + + js.metricValue = js.metricValue.map(value => value === 'all' ? '' : value); js.series = js.series.map(series => { series.filter.filters = series.filter.filters.map(filterMap); // delete series._key - // delete series.key + delete series.key return series; }); @@ -61,8 +68,10 @@ export default Record({ return js; }, }, - fromJS: ({ series, ...rest }) => ({ + fromJS: ({ metricOf, metricValue, series, ...rest }) => ({ ...rest, series: List(series).map(FilterSeries), + metricOf, + metricValue: metricOf === FilterKey.ISSUE && metricValue.length === 0 ? ['all'] : metricValue, }), }); diff --git a/frontend/app/types/filter/filter.js b/frontend/app/types/filter/filter.js index 25d62c7cc..9566c9d4b 100644 --- a/frontend/app/types/filter/filter.js +++ b/frontend/app/types/filter/filter.js @@ -96,8 +96,14 @@ export default Record({ startDate, endDate, events: List(events).map(Event), - filters: List(filters).map(i => NewFilter(i).toData()).concat(List(events).map(i => NewFilter(i).toData())), - custom: Map(custom), + filters: List(filters) + .map(i => { + const filter = NewFilter(i).toData(); + if (i.hasOwnProperty('filters')) { + filter.filters = i.filters.map(f => NewFilter({...f, subFilter: i.type}).toData()); + } + return filter; + }), } } }); diff --git a/frontend/app/types/filter/filterType.ts b/frontend/app/types/filter/filterType.ts index 16f128975..ccb5156cd 100644 --- a/frontend/app/types/filter/filterType.ts +++ b/frontend/app/types/filter/filterType.ts @@ -13,8 +13,10 @@ export enum FilterType { ISSUE = "ISSUE", BOOLEAN = "BOOLEAN", NUMBER = "NUMBER", + NUMBER_MULTIPLE = "NUMBER_MULTIPLE", DURATION = "DURATION", MULTIPLE = "MULTIPLE", + SUB_FILTERS = "SUB_FILTERS", COUNTRY = "COUNTRY", DROPDOWN = "DROPDOWN", MULTIPLE_DROPDOWN = "MULTIPLE_DROPDOWN", @@ -61,4 +63,11 @@ export enum FilterKey { AVG_CPU_LOAD = "AVG_CPU_LOAD", AVG_MEMORY_USAGE = "AVG_MEMORY_USAGE", FETCH_FAILED = "FETCH_FAILED", + FETCH = "FETCH", + FETCH_URL = "FETCH_URL", + FETCH_STATUS_CODE = "FETCH_STATUS_CODE", + FETCH_METHOD = "FETCH_METHOD", + FETCH_DURATION = "FETCH_DURATION", + FETCH_REQUEST_BODY = "FETCH_REQUEST_BODY", + FETCH_RESPONSE_BODY = "FETCH_RESPONSE_BODY", } \ No newline at end of file diff --git a/frontend/app/types/filter/index.js b/frontend/app/types/filter/index.js index 957e1dfb8..386ea96a0 100644 --- a/frontend/app/types/filter/index.js +++ b/frontend/app/types/filter/index.js @@ -236,22 +236,4 @@ export const operatorOptions = (filter) => { case KEYS.CLICK_RAGE: return [{ key: 'onAnything', text: 'on anything', value: 'true' }] } -} - -const NewFilterType = (key, category, label, icon, isEvent = false) => { - return { - key: key, - category: category, - label: label, - icon: icon, - isEvent: isEvent, - operators: operatorOptions({ key }), - value: [""] - } -} - -export const newFiltersList = [ - NewFilterType(TYPES.CLICK, 'Gear', 'Click', 'filters/click', true), - NewFilterType(TYPES.CLICK, 'Gear', 'Input', 'filters/click', true), - NewFilterType(TYPES.CONSOLE, 'Other', 'Console', 'filters/click', true), -]; \ No newline at end of file +} \ No newline at end of file diff --git a/frontend/app/types/filter/newFilter.js b/frontend/app/types/filter/newFilter.js index d4cb905a1..dedc4a7c5 100644 --- a/frontend/app/types/filter/newFilter.js +++ b/frontend/app/types/filter/newFilter.js @@ -6,21 +6,6 @@ import { capitalize } from 'App/utils'; const countryOptions = Object.keys(countries).map(i => ({ text: countries[i], value: i })); const containsFilters = [{ key: 'contains', text: 'contains', value: 'contains' }] -const ISSUE_OPTIONS = [ - { text: 'Click Rage', value: 'click_rage' }, - { text: 'Dead Click', value: 'dead_click' }, - { text: 'Excessive Scrolling', value: 'excessive_scrolling' }, - { text: 'Bad Request', value: 'bad_request' }, - { text: 'Missing Resource', value: 'missing_resource' }, - { text: 'Memory', value: 'memory' }, - { text: 'CPU', value: 'cpu' }, - { text: 'Slow Resource', value: 'slow_resource' }, - { text: 'Slow Page Load', value: 'slow_page_load' }, - { text: 'Crash', value: 'crash' }, - { text: 'Custom', value: 'custom' }, - { text: 'JS Exception', value: 'js_exception' }, -] - export const filtersMap = { // EVENTS [FilterKey.CLICK]: { key: FilterKey.CLICK, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Click', operator: 'on', operatorOptions: filterOptions.targetOperators, icon: 'filters/click', isEvent: true }, @@ -48,13 +33,21 @@ export const filtersMap = { [FilterKey.USERANONYMOUSID]: { key: FilterKey.USERANONYMOUSID, type: FilterType.MULTIPLE, category: FilterCategory.USER, label: 'User AnonymousId', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/userid' }, // PERFORMANCE + [FilterKey.FETCH]: { key: FilterKey.FETCH, type: FilterType.SUB_FILTERS, category: FilterCategory.PERFORMANCE, operator: 'is', label: 'Network Request', filters: [ + { key: FilterKey.FETCH_URL, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with URL', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, + { key: FilterKey.FETCH_STATUS_CODE, type: FilterType.NUMBER_MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with status code', operator: '=', operatorOptions: filterOptions.customOperators, icon: 'filters/fetch' }, + { key: FilterKey.FETCH_METHOD, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.PERFORMANCE, label: 'with method', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', options: filterOptions.methodOptions }, + { key: FilterKey.FETCH_DURATION, type: FilterType.NUMBER, category: FilterCategory.PERFORMANCE, label: 'with duration', operator: '=', operatorOptions: filterOptions.customOperators, icon: 'filters/fetch' }, + { key: FilterKey.FETCH_REQUEST_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with request body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, + { key: FilterKey.FETCH_RESPONSE_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with response body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, + ], icon: 'filters/perfromance-network-request', isEvent: true }, [FilterKey.DOM_COMPLETE]: { key: FilterKey.DOM_COMPLETE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'DOM Complete', operator: 'isAny', operatorOptions: filterOptions.stringOperators, source: [], icon: 'filters/dom-complete', isEvent: true, hasSource: true, sourceOperator: '=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, [FilterKey.LARGEST_CONTENTFUL_PAINT_TIME]: { key: FilterKey.LARGEST_CONTENTFUL_PAINT_TIME, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Largest Contentful Paint', operator: 'isAny', operatorOptions: filterOptions.stringOperators, source: [], icon: 'filters/lcpt', isEvent: true, hasSource: true, sourceOperator: '=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, [FilterKey.TTFB]: { key: FilterKey.TTFB, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Time to First Byte', operator: 'isAny', operatorOptions: filterOptions.stringOperators, source: [], icon: 'filters/ttfb', isEvent: true, hasSource: true, sourceOperator: '=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, [FilterKey.AVG_CPU_LOAD]: { key: FilterKey.AVG_CPU_LOAD, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg CPU Load', operator: 'isAny', operatorOptions: filterOptions.stringOperators, source: [], icon: 'filters/cpu-load', isEvent: true, hasSource: true, sourceOperator: '=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, [FilterKey.AVG_MEMORY_USAGE]: { key: FilterKey.AVG_MEMORY_USAGE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg Memory Usage', operator: 'isAny', operatorOptions: filterOptions.stringOperators, source: [], icon: 'filters/memory-load', isEvent: true, hasSource: true, sourceOperator: '=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, [FilterKey.FETCH_FAILED]: { key: FilterKey.FETCH_FAILED, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Failed Request', operator: 'isAny', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch-failed', isEvent: true }, - [FilterKey.ISSUE]: { key: FilterKey.ISSUE, type: FilterType.ISSUE, category: FilterCategory.JAVASCRIPT, label: 'Issue', operator: 'is', operatorOptions: filterOptions.baseOperators, icon: 'filters/click', options: ISSUE_OPTIONS }, + [FilterKey.ISSUE]: { key: FilterKey.ISSUE, type: FilterType.ISSUE, category: FilterCategory.JAVASCRIPT, label: 'Issue', operator: 'is', operatorOptions: filterOptions.getOperatorsByKeys(['is', 'isAny', 'isNot']), icon: 'filters/click', options: filterOptions.issueOptions }, } export const liveFiltersMap = { @@ -121,17 +114,28 @@ export default Record({ isEvent: false, index: 0, options: [], + + filters: [], }, { keyKey: "_key", - fromJS: ({ value, key, type, ...filter }) => { - // const _filter = filtersMap[key] || filtersMap[type] || {}; - const _filter = filtersMap[type]; + fromJS: ({ value, type, subFilter = false, ...filter }) => { + let _filter = {}; + if (subFilter) { + const mainFilter = filtersMap[subFilter]; + const subFilterMap = {} + mainFilter.filters.forEach(option => { + subFilterMap[option.key] = option + }) + _filter = subFilterMap[type] + } else { + _filter = filtersMap[type]; + } return { ...filter, ..._filter, key: _filter.key, type: _filter.type, // camelCased(filter.type.toLowerCase()), - value: value.length === 0 ? [""] : value, // make sure there an empty value + value: value.length === 0 || !value ? [""] : value, } }, }) @@ -142,33 +146,29 @@ export default Record({ * @returns */ export const generateFilterOptions = (map) => { - const _options = {}; + const filterSection = {}; Object.keys(map).forEach(key => { const filter = map[key]; - if (_options.hasOwnProperty(filter.category)) { - _options[filter.category].push(filter); + if (filterSection.hasOwnProperty(filter.category)) { + filterSection[filter.category].push(filter); } else { - _options[filter.category] = [filter]; + filterSection[filter.category] = [filter]; } }); - return _options; + return filterSection; } export const generateLiveFilterOptions = (map) => { - const _options = {}; + const filterSection = {}; Object.keys(map).filter(i => map[i].isLive).forEach(key => { const filter = map[key]; filter.operator = 'contains'; - // filter.type = FilterType.STRING; - // filter.type = FilterType.AUTOCOMPLETE_LOCAL; - // filter.options = countryOptions; - // filter.operatorOptions = [{ key: 'contains', text: 'contains', value: 'contains' }] - if (_options.hasOwnProperty(filter.category)) { - _options[filter.category].push(filter); + if (filterSection.hasOwnProperty(filter.category)) { + filterSection[filter.category].push(filter); } else { - _options[filter.category] = [filter]; + filterSection[filter.category] = [filter]; } }); - return _options; + return filterSection; } \ No newline at end of file diff --git a/frontend/app/types/session/session.js b/frontend/app/types/session/session.js index 5eda0c987..5401e3008 100644 --- a/frontend/app/types/session/session.js +++ b/frontend/app/types/session/session.js @@ -25,6 +25,8 @@ function hashString(s: string): number { export default Record({ sessionId: '', + pageTitle: '', + active: true, siteId: '', projectKey: '', peerId: '', diff --git a/frontend/env.js b/frontend/env.js index 7d3ab7e6e..a76295cf1 100644 --- a/frontend/env.js +++ b/frontend/env.js @@ -13,7 +13,7 @@ const oss = { ORIGIN: () => 'window.location.origin', API_EDP: () => 'window.location.origin + "/api"', ASSETS_HOST: () => 'window.location.origin + "/assets"', - VERSION: '1.5.2', + VERSION: '1.5.3', SOURCEMAP: true, MINIO_ENDPOINT: process.env.MINIO_ENDPOINT, MINIO_PORT: process.env.MINIO_PORT, @@ -21,7 +21,7 @@ const oss = { MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY, MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY, ICE_SERVERS: process.env.ICE_SERVERS, - TRACKER_VERSION: '3.5.2' // trackerInfo.version, + TRACKER_VERSION: '3.5.3' // trackerInfo.version, } module.exports = { diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index e15ec72e9..0da29c3d5 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -19,7 +19,7 @@ module.exports = { // 'backgroundSize', // 'borderCollapse', 'borderColor', - // 'borderOpacity', + 'borderOpacity', 'borderRadius', // 'borderStyle', 'borderWidth', diff --git a/scripts/helm/db/init_dbs/postgresql/1.5.3/1.5.3.sql b/scripts/helm/db/init_dbs/postgresql/1.5.3/1.5.3.sql new file mode 100644 index 000000000..1030ba55d --- /dev/null +++ b/scripts/helm/db/init_dbs/postgresql/1.5.3/1.5.3.sql @@ -0,0 +1,97 @@ +BEGIN; +CREATE OR REPLACE FUNCTION openreplay_version() + RETURNS text AS +$$ +SELECT 'v1.5.3' +$$ LANGUAGE sql IMMUTABLE; + +UPDATE metrics +SET is_public= TRUE; + +DO +$$ + BEGIN + IF NOT EXISTS(SELECT * + FROM pg_type typ + INNER JOIN pg_namespace nsp + ON nsp.oid = typ.typnamespace + WHERE nsp.nspname = current_schema() + AND typ.typname = 'metric_type') THEN + CREATE TYPE metric_type AS ENUM ('timeseries','table'); + END IF; + END; +$$ +LANGUAGE plpgsql; + +DO +$$ + BEGIN + IF NOT EXISTS(SELECT * + FROM pg_type typ + INNER JOIN pg_namespace nsp + ON nsp.oid = typ.typnamespace + WHERE nsp.nspname = current_schema() + AND typ.typname = 'metric_view_type') THEN + CREATE TYPE metric_view_type AS ENUM ('lineChart','progress','table','pieChart'); + END IF; + END; +$$ +LANGUAGE plpgsql; + +ALTER TABLE metrics + ADD COLUMN IF NOT EXISTS + metric_type metric_type NOT NULL DEFAULT 'timeseries', + ADD COLUMN IF NOT EXISTS + view_type metric_view_type NOT NULL DEFAULT 'lineChart', + ADD COLUMN IF NOT EXISTS + metric_of text NOT NULL DEFAULT 'sessionCount', + ADD COLUMN IF NOT EXISTS + metric_value text[] NOT NULL DEFAULT '{}'::text[], + ADD COLUMN IF NOT EXISTS + metric_format text; + +DO +$$ + BEGIN + IF NOT EXISTS(SELECT * + FROM pg_type typ + INNER JOIN pg_namespace nsp + ON nsp.oid = typ.typnamespace + WHERE typ.typname = 'http_method') THEN + CREATE TYPE http_method AS ENUM ('GET','HEAD','POST','PUT','DELETE','CONNECT','OPTIONS','TRACE','PATCH'); + END IF; + END; +$$ +LANGUAGE plpgsql; + + +ALTER TABLE events.graphql + ADD COLUMN IF NOT EXISTS request_body text NULL, + ADD COLUMN IF NOT EXISTS response_body text NULL, + ADD COLUMN IF NOT EXISTS status_code smallint NULL, + ADD COLUMN IF NOT EXISTS method http_method NULL, + ADD COLUMN IF NOT EXISTS duration integer NULL; + +ALTER TABLE events_common.requests + ADD COLUMN IF NOT EXISTS request_body text NULL, + ADD COLUMN IF NOT EXISTS response_body text NULL, + ADD COLUMN IF NOT EXISTS status_code smallint NULL, + ADD COLUMN IF NOT EXISTS method http_method NULL; + +UPDATE tenants +SET version_number= openreplay_version(); + +COMMIT; + +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_request_body_nn_idx ON events_common.requests (request_body) WHERE request_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_request_body_nn_gin_idx ON events_common.requests USING GIN (request_body gin_trgm_ops) WHERE request_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_response_body_nn_idx ON events_common.requests (response_body) WHERE response_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_response_body_nn_gin_idx ON events_common.requests USING GIN (response_body gin_trgm_ops) WHERE response_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS requests_status_code_nn_idx ON events_common.requests (status_code) WHERE status_code IS NOT NULL; + +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_request_body_nn_idx ON events.graphql (request_body) WHERE request_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_request_body_nn_gin_idx ON events.graphql USING GIN (request_body gin_trgm_ops) WHERE request_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_response_body_nn_idx ON events.graphql (response_body) WHERE response_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_response_body_nn_gin_idx ON events.graphql USING GIN (response_body gin_trgm_ops) WHERE response_body IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_status_code_nn_idx ON events.graphql (status_code) WHERE status_code IS NOT NULL; +CREATE INDEX CONCURRENTLY IF NOT EXISTS graphql_duration_nn_gt0_idx ON events.graphql (duration) WHERE duration IS NOT NULL AND duration > 0; diff --git a/scripts/helm/db/init_dbs/postgresql/init_schema.sql b/scripts/helm/db/init_dbs/postgresql/init_schema.sql index e053063c2..c7d1f2110 100644 --- a/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/scripts/helm/db/init_dbs/postgresql/init_schema.sql @@ -6,7 +6,7 @@ CREATE SCHEMA IF NOT EXISTS events; CREATE OR REPLACE FUNCTION openreplay_version() RETURNS text AS $$ -SELECT 'v1.5.2' +SELECT 'v1.5.3' $$ LANGUAGE sql IMMUTABLE; -- --- accounts.sql --- @@ -631,14 +631,19 @@ $$ CREATE INDEX issues_timestamp_idx ON events_common.issues (timestamp); CREATE INDEX issues_project_id_issue_id_idx ON public.issues (project_id, issue_id); + CREATE TYPE http_method AS ENUM ('GET','HEAD','POST','PUT','DELETE','CONNECT','OPTIONS','TRACE','PATCH'); CREATE TABLE events_common.requests ( - session_id bigint NOT NULL REFERENCES sessions (session_id) ON DELETE CASCADE, - timestamp bigint NOT NULL, - seq_index integer NOT NULL, - url text NOT NULL, - duration integer NOT NULL, - success boolean NOT NULL, + session_id bigint NOT NULL REFERENCES sessions (session_id) ON DELETE CASCADE, + timestamp bigint NOT NULL, + seq_index integer NOT NULL, + url text NOT NULL, + duration integer NOT NULL, + success boolean NOT NULL, + request_body text NULL, + response_body text NULL, + status_code smallint NULL, + method http_method NULL, PRIMARY KEY (session_id, timestamp, seq_index) ); CREATE INDEX requests_url_idx ON events_common.requests (url); @@ -653,6 +658,12 @@ $$ ELSE 0 END)) gin_trgm_ops); CREATE INDEX requests_timestamp_session_id_failed_idx ON events_common.requests (timestamp, session_id) WHERE success = FALSE; + CREATE INDEX requests_request_body_nn_idx ON events_common.requests (request_body) WHERE request_body IS NOT NULL; + CREATE INDEX requests_request_body_nn_gin_idx ON events_common.requests USING GIN (request_body gin_trgm_ops) WHERE request_body IS NOT NULL; + CREATE INDEX requests_response_body_nn_idx ON events_common.requests (response_body) WHERE response_body IS NOT NULL; + CREATE INDEX requests_response_body_nn_gin_idx ON events_common.requests USING GIN (response_body gin_trgm_ops) WHERE response_body IS NOT NULL; + CREATE INDEX requests_status_code_nn_idx ON events_common.requests (status_code) WHERE status_code IS NOT NULL; + -- --- events.sql --- CREATE SCHEMA IF NOT EXISTS events; @@ -881,7 +892,6 @@ $$ CREATE INDEX autocomplete_type_idx ON public.autocomplete (type); CREATE INDEX autocomplete_value_gin_idx ON public.autocomplete USING GIN (value gin_trgm_ops); --- --- jobs.sql --- CREATE TYPE job_status AS ENUM ('scheduled','running','cancelled','failed','completed'); CREATE TYPE job_action AS ENUM ('delete_user_data'); CREATE TABLE jobs @@ -901,16 +911,23 @@ $$ CREATE INDEX jobs_start_at_idx ON jobs (start_at); CREATE INDEX jobs_project_id_idx ON jobs (project_id); + CREATE TYPE metric_type AS ENUM ('timeseries','table'); + CREATE TYPE metric_view_type AS ENUM ('lineChart','progress','table','pieChart'); CREATE TABLE metrics ( - metric_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY, - project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE, - user_id integer REFERENCES users (user_id) ON DELETE SET NULL, - name text NOT NULL, - is_public boolean NOT NULL DEFAULT FALSE, - active boolean NOT NULL DEFAULT TRUE, - created_at timestamp default timezone('utc'::text, now()) not null, - deleted_at timestamp + metric_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY, + project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE, + user_id integer REFERENCES users (user_id) ON DELETE SET NULL, + name text NOT NULL, + is_public boolean NOT NULL DEFAULT FALSE, + active boolean NOT NULL DEFAULT TRUE, + created_at timestamp default timezone('utc'::text, now()) not null, + deleted_at timestamp, + metric_type metric_type NOT NULL DEFAULT 'timeseries', + view_type metric_view_type NOT NULL DEFAULT 'lineChart', + metric_of text NOT NULL DEFAULT 'sessionCount', + metric_value text[] NOT NULL DEFAULT '{}'::text[], + metric_format text ); CREATE INDEX metrics_user_id_is_public_idx ON public.metrics (user_id, is_public); CREATE TABLE metric_series diff --git a/scripts/helmcharts/init.sh b/scripts/helmcharts/init.sh index 2df3b8450..6e4f70613 100644 --- a/scripts/helmcharts/init.sh +++ b/scripts/helmcharts/init.sh @@ -15,7 +15,7 @@ fatal() exit 1 } -version="v1.5.2" +version="v1.5.3" usr=`whoami` # Installing k3s diff --git a/scripts/helmcharts/openreplay/Chart.yaml b/scripts/helmcharts/openreplay/Chart.yaml index e621e543d..f0b5ef469 100644 --- a/scripts/helmcharts/openreplay/Chart.yaml +++ b/scripts/helmcharts/openreplay/Chart.yaml @@ -22,4 +22,4 @@ version: 0.1.0 # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. # Ref: https://github.com/helm/helm/issues/7858#issuecomment-608114589 -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/alerts/Chart.yaml b/scripts/helmcharts/openreplay/charts/alerts/Chart.yaml index 0bfe8b4bc..b39fb2e99 100644 --- a/scripts/helmcharts/openreplay/charts/alerts/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/alerts/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/assets/Chart.yaml b/scripts/helmcharts/openreplay/charts/assets/Chart.yaml index 9b8c32623..b1be7b726 100644 --- a/scripts/helmcharts/openreplay/charts/assets/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/assets/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/chalice/Chart.yaml b/scripts/helmcharts/openreplay/charts/chalice/Chart.yaml index 1d0441f7e..755fb8648 100644 --- a/scripts/helmcharts/openreplay/charts/chalice/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/chalice/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/db/Chart.yaml b/scripts/helmcharts/openreplay/charts/db/Chart.yaml index 0aa5f39e3..796e1ef76 100644 --- a/scripts/helmcharts/openreplay/charts/db/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/db/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/ender/Chart.yaml b/scripts/helmcharts/openreplay/charts/ender/Chart.yaml index 8a7ce610e..571ef34c0 100644 --- a/scripts/helmcharts/openreplay/charts/ender/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/ender/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/http/Chart.yaml b/scripts/helmcharts/openreplay/charts/http/Chart.yaml index 5422d1f3d..166b3e22d 100644 --- a/scripts/helmcharts/openreplay/charts/http/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/http/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/integrations/Chart.yaml b/scripts/helmcharts/openreplay/charts/integrations/Chart.yaml index e8fc92887..710f7ffe5 100644 --- a/scripts/helmcharts/openreplay/charts/integrations/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/integrations/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/nginx-ingress/Chart.yaml b/scripts/helmcharts/openreplay/charts/nginx-ingress/Chart.yaml index 2c473b4b4..b0baf2637 100644 --- a/scripts/helmcharts/openreplay/charts/nginx-ingress/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/nginx-ingress/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/nginx-ingress/templates/configMap.yaml b/scripts/helmcharts/openreplay/charts/nginx-ingress/templates/configMap.yaml index b8340ad5d..6780c9ee6 100644 --- a/scripts/helmcharts/openreplay/charts/nginx-ingress/templates/configMap.yaml +++ b/scripts/helmcharts/openreplay/charts/nginx-ingress/templates/configMap.yaml @@ -82,7 +82,7 @@ data: proxy_set_header Host $host; proxy_set_header X-Forwarded-For $origin_forwarded_ip; proxy_set_header X-Real-IP $origin_forwarded_ip; - proxy_pass http://utilities-openreplay.app.svc.cluster.local:9001; + proxy_pass http://utilities-pool; } location /assets/ { rewrite ^/assets/(.*) /sessions-assets/$1 break; @@ -161,8 +161,11 @@ data: } upstream utilities-pool { + # comment this line if you have multiple pods server utilities-openreplay-headless.app:9001; - # enable sticky session with either "hash" (uses the complete IP address) + # uncomment and change these lines if you have multiple pods + # server POD1_IP:9001; + # server POD2_IP:9001; hash $origin_forwarded_ip consistent; } diff --git a/scripts/helmcharts/openreplay/charts/sink/Chart.yaml b/scripts/helmcharts/openreplay/charts/sink/Chart.yaml index 7ece0a5bf..fea7646a4 100644 --- a/scripts/helmcharts/openreplay/charts/sink/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/sink/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/storage/Chart.yaml b/scripts/helmcharts/openreplay/charts/storage/Chart.yaml index 9e1c06d8c..879a077c6 100644 --- a/scripts/helmcharts/openreplay/charts/storage/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/storage/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/utilities/Chart.yaml b/scripts/helmcharts/openreplay/charts/utilities/Chart.yaml index acc73d941..e432835d0 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/Chart.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -AppVersion: "v1.5.2" +AppVersion: "v1.5.3" diff --git a/scripts/helmcharts/openreplay/charts/utilities/values.yaml b/scripts/helmcharts/openreplay/charts/utilities/values.yaml index 8d58b5227..87b3d771d 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/values.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/values.yaml @@ -81,7 +81,8 @@ autoscaling: targetCPUUtilizationPercentage: 80 # targetMemoryUtilizationPercentage: 80 -env: {} +env: + REDIS_URL: "redis://redis-master.db.svc.cluster.local:6379" nodeSelector: {} diff --git a/scripts/helmcharts/vars.yaml b/scripts/helmcharts/vars.yaml index ed0ab4c05..25d6a67d6 100644 --- a/scripts/helmcharts/vars.yaml +++ b/scripts/helmcharts/vars.yaml @@ -1,4 +1,4 @@ -fromVersion: "v1.5.2" +fromVersion: "v1.5.3" # Databases specific variables postgresql: &postgres # For generating passwords @@ -95,6 +95,13 @@ chalice: # idp_name: '' # idp_tenantKey: '' +utilities: + replicaCount: 1 + env: + debug: 0 + uws: false + cluster: false + # If you want to override something # chartname: # filedFrom chart/Values.yaml: diff --git a/tracker/tracker-assist/package-lock.json b/tracker/tracker-assist/package-lock.json index 45f467ba7..b0c032a8b 100644 --- a/tracker/tracker-assist/package-lock.json +++ b/tracker/tracker-assist/package-lock.json @@ -1,8 +1,3899 @@ { "name": "@openreplay/tracker-assist", - "version": "3.5.0", - "lockfileVersion": 1, + "version": "3.5.3", + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "@openreplay/tracker-assist", + "version": "3.5.3", + "license": "MIT", + "dependencies": { + "csstype": "^3.0.10", + "npm-dragndrop": "^1.2.0", + "peerjs": "^1.3.2", + "socket.io-client": "^4.4.1" + }, + "devDependencies": { + "@openreplay/tracker": "file:../tracker", + "prettier": "^1.18.2", + "replace-in-files-cli": "^1.0.0", + "typescript": "^4.6.0-dev.20211126" + }, + "peerDependencies": { + "@openreplay/tracker": "^3.5.0" + } + }, + "../tracker": { + "name": "@openreplay/tracker", + "version": "3.5.2", + "dev": true, + "license": "MIT", + "dependencies": { + "error-stack-parser": "^2.0.6" + }, + "devDependencies": { + "@babel/core": "^7.10.2", + "@rollup/plugin-babel": "^5.0.3", + "@rollup/plugin-node-resolve": "^8.0.1", + "@typescript-eslint/eslint-plugin": "^2.34.0", + "@typescript-eslint/parser": "^2.34.0", + "eslint": "^6.8.0", + "eslint-plugin-prettier": "^3.1.4", + "prettier": "^2.0.0", + "replace-in-files": "^2.0.3", + "rollup": "^2.17.0", + "rollup-plugin-terser": "^6.1.0", + "semver": "^6.3.0", + "typescript": "^4.6.0-dev.20211126" + }, + "engines": { + "node": ">=12" + } + }, + "../tracker/node_modules/@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.8.3" + } + }, + "../tracker/node_modules/@babel/core": { + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz", + "integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.1", + "@babel/generator": "^7.10.2", + "@babel/helper-module-transforms": "^7.10.1", + "@babel/helpers": "^7.10.1", + "@babel/parser": "^7.10.2", + "@babel/template": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.2", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "../tracker/node_modules/@babel/core/node_modules/@babel/code-frame": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", + "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/core/node_modules/@babel/highlight": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", + "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.1", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "../tracker/node_modules/@babel/core/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "../tracker/node_modules/@babel/generator": { + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz", + "integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.2", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "../tracker/node_modules/@babel/helper-function-name": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz", + "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.10.1", + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/helper-get-function-arity": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz", + "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz", + "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/helper-module-imports": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz", + "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/helper-module-transforms": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz", + "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.10.1", + "@babel/helper-replace-supers": "^7.10.1", + "@babel/helper-simple-access": "^7.10.1", + "@babel/helper-split-export-declaration": "^7.10.1", + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1", + "lodash": "^4.17.13" + } + }, + "../tracker/node_modules/@babel/helper-optimise-call-expression": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz", + "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/helper-replace-supers": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz", + "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.10.1", + "@babel/helper-optimise-call-expression": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/helper-simple-access": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz", + "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/helper-split-export-declaration": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz", + "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/helper-validator-identifier": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", + "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", + "dev": true + }, + "../tracker/node_modules/@babel/helpers": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz", + "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "dependencies": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "../tracker/node_modules/@babel/parser": { + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz", + "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../tracker/node_modules/@babel/template": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz", + "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.1", + "@babel/parser": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/template/node_modules/@babel/code-frame": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", + "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/template/node_modules/@babel/highlight": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", + "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.1", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "../tracker/node_modules/@babel/traverse": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz", + "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.1", + "@babel/generator": "^7.10.1", + "@babel/helper-function-name": "^7.10.1", + "@babel/helper-split-export-declaration": "^7.10.1", + "@babel/parser": "^7.10.1", + "@babel/types": "^7.10.1", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "../tracker/node_modules/@babel/traverse/node_modules/@babel/code-frame": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", + "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.1" + } + }, + "../tracker/node_modules/@babel/traverse/node_modules/@babel/highlight": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", + "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.1", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "../tracker/node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/@babel/types": { + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz", + "integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.1", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "../tracker/node_modules/@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "../tracker/node_modules/@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "../tracker/node_modules/@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "../tracker/node_modules/@rollup/plugin-babel": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.0.3.tgz", + "integrity": "sha512-NlaPf4E6YFxeOCbqc+A2PTkB1BSy3rfKu6EJuQ1MGhMHpTVvMqKi6Rf0DlwtnEsTNK9LueUgsGEgp5Occ4KDVA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.7.4", + "@rollup/pluginutils": "^3.0.8" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "rollup": "^1.20.0||^2.0.0" + } + }, + "../tracker/node_modules/@rollup/plugin-node-resolve": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.0.1.tgz", + "integrity": "sha512-KIeAmueDDaYMqMBnUngLVVZhURwxA12nq/YB6nGm5/JpVyOMwI1fCVU3oL/dAnnLBG7oiPXntO5LHOiMrfNXCA==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.0.8", + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "deep-freeze": "^0.0.1", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.14.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "../tracker/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "../tracker/node_modules/@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, + "../tracker/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "../tracker/node_modules/@types/glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "../tracker/node_modules/@types/json-schema": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", + "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", + "dev": true + }, + "../tracker/node_modules/@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "../tracker/node_modules/@types/node": { + "version": "14.0.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", + "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==", + "dev": true + }, + "../tracker/node_modules/@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "../tracker/node_modules/@typescript-eslint/eslint-plugin": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz", + "integrity": "sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "2.34.0", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "tsutils": "^3.17.1" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^2.0.0", + "eslint": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "../tracker/node_modules/@typescript-eslint/experimental-utils": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz", + "integrity": "sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.34.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + } + }, + "../tracker/node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "../tracker/node_modules/@typescript-eslint/parser": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.34.0.tgz", + "integrity": "sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA==", + "dev": true, + "dependencies": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "2.34.0", + "@typescript-eslint/typescript-estree": "2.34.0", + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "../tracker/node_modules/@typescript-eslint/typescript-estree": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", + "integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "../tracker/node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "../tracker/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "../tracker/node_modules/acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0" + } + }, + "../tracker/node_modules/ajv": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "../tracker/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../tracker/node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../tracker/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "../tracker/node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "../tracker/node_modules/binaryextensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", + "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==", + "dev": true, + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "../tracker/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "../tracker/node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "../tracker/node_modules/builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "../tracker/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "../tracker/node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "../tracker/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "../tracker/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "../tracker/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "../tracker/node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "../tracker/node_modules/convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "../tracker/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "../tracker/node_modules/cross-spawn/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "../tracker/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "../tracker/node_modules/deep-freeze": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz", + "integrity": "sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ=", + "dev": true + }, + "../tracker/node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "../tracker/node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../tracker/node_modules/editions": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/editions/-/editions-2.3.1.tgz", + "integrity": "sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA==", + "dev": true, + "dependencies": { + "errlop": "^2.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "../tracker/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "../tracker/node_modules/errlop": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/errlop/-/errlop-2.2.0.tgz", + "integrity": "sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw==", + "dev": true, + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "../tracker/node_modules/error-stack-parser": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", + "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==", + "dev": true, + "dependencies": { + "stackframe": "^1.1.1" + } + }, + "../tracker/node_modules/es6-promisify": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.1.1.tgz", + "integrity": "sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==", + "dev": true + }, + "../tracker/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "../tracker/node_modules/eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "../tracker/node_modules/eslint-plugin-prettier": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", + "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=5.0.0", + "prettier": ">=1.13.0" + } + }, + "../tracker/node_modules/eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "../tracker/node_modules/eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/eslint/node_modules/regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true, + "engines": { + "node": ">=6.5.0" + } + }, + "../tracker/node_modules/espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "dev": true, + "dependencies": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../tracker/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/esquery": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz", + "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==", + "dev": true, + "dependencies": { + "estraverse": "^4.0.0" + }, + "engines": { + "node": ">=0.6" + } + }, + "../tracker/node_modules/esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "dependencies": { + "estraverse": "^4.1.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "../tracker/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "../tracker/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "../tracker/node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "../tracker/node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "../tracker/node_modules/fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/fast-glob/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/fast-glob/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/fast-glob/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "../tracker/node_modules/fast-glob/node_modules/micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/fast-glob/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "../tracker/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "../tracker/node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "../tracker/node_modules/fastq": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", + "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "../tracker/node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../tracker/node_modules/file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "dependencies": { + "flat-cache": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "dependencies": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, + "../tracker/node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "../tracker/node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "../tracker/node_modules/gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "../tracker/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "../tracker/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "../tracker/node_modules/globals": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", + "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", + "dev": true, + "dependencies": { + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/globby/node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "../tracker/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "../tracker/node_modules/import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "../tracker/node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "../tracker/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "../tracker/node_modules/inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "../tracker/node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "../tracker/node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "../tracker/node_modules/inquirer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "../tracker/node_modules/inquirer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "../tracker/node_modules/inquirer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/inquirer/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "../tracker/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "../tracker/node_modules/istextorbinary": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.6.0.tgz", + "integrity": "sha512-+XRlFseT8B3L9KyjxxLjfXSLMuErKDsd8DBNrsaxoViABMEZlOSCstwmw0qpoFX3+U6yWU1yhLudAe6/lETGGA==", + "dev": true, + "dependencies": { + "binaryextensions": "^2.1.2", + "editions": "^2.2.0", + "textextensions": "^2.5.0" + }, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "../tracker/node_modules/jest-worker": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.0.0.tgz", + "integrity": "sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw==", + "dev": true, + "dependencies": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "../tracker/node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/jest-worker/node_modules/supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "../tracker/node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "../tracker/node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "../tracker/node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "../tracker/node_modules/json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/json5/node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "../tracker/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "../tracker/node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "../tracker/node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "../tracker/node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "../tracker/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "../tracker/node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "../tracker/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "../tracker/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "../tracker/node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "../tracker/node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "../tracker/node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "../tracker/node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "../tracker/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "../tracker/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "../tracker/node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "../tracker/node_modules/picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "../tracker/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "../tracker/node_modules/prettier": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", + "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "../tracker/node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../tracker/node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "../tracker/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "../tracker/node_modules/regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "../tracker/node_modules/replace-in-files": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/replace-in-files/-/replace-in-files-2.0.3.tgz", + "integrity": "sha512-wm9kg+WhKQ10CFaCS9jvUtgw9JnaPilm4TqSRq57H06v5EgX7hTrr/qwgyvq3G+IeNhmr6VTW84LvfnpZfq5/g==", + "dev": true, + "dependencies": { + "co": "^4.6.0", + "es6-promisify": "^6.0.2", + "globby": "^10.0.1", + "istextorbinary": "^2.5.1", + "lodash": "^4.17.15" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../tracker/node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "../tracker/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "../tracker/node_modules/rollup": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.17.0.tgz", + "integrity": "sha512-4Um68vKyyTLzT+EWClgc+nyxSlunlmx8wgCO16RDicwxvccnyBHguoNqxPaJL/YPAdvuAJkqaFPf/BfDojzEZA==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.2" + } + }, + "../tracker/node_modules/rollup-plugin-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-6.1.0.tgz", + "integrity": "sha512-4fB3M9nuoWxrwm39habpd4hvrbrde2W2GG4zEGPQg1YITNkM3Tqur5jSuXlWNzbv/2aMLJ+dZJaySc3GCD8oDw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.8.3", + "jest-worker": "^26.0.0", + "serialize-javascript": "^3.0.0", + "terser": "^4.7.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "../tracker/node_modules/rollup/node_modules/fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "deprecated": "\"Please update to latest v2.3 or v2.2\"", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "../tracker/node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "../tracker/node_modules/run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, + "../tracker/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "../tracker/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "../tracker/node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "../tracker/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "../tracker/node_modules/serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "../tracker/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/signal-exit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", + "dev": true + }, + "../tracker/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "../tracker/node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "../tracker/node_modules/stackframe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", + "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==", + "dev": true + }, + "../tracker/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "dependencies": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../tracker/node_modules/table/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "../tracker/node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/table/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "../tracker/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "../tracker/node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "../tracker/node_modules/textextensions": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.6.0.tgz", + "integrity": "sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ==", + "dev": true, + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "../tracker/node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "../tracker/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "../tracker/node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "../tracker/node_modules/tslib": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz", + "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==", + "dev": true + }, + "../tracker/node_modules/tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "../tracker/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "../tracker/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "../tracker/node_modules/typescript": { + "version": "4.6.0-dev.20211126", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.0-dev.20211126.tgz", + "integrity": "sha512-m+LKstqVv6FYW363aIbO6bm8awsLbeSUCzU6FxPtzUF/WJkFieQfYmdVwEIzigeTpw4E2GETBXnk6P6AixcQJQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "../tracker/node_modules/uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "../tracker/node_modules/v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, + "../tracker/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "../tracker/node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "../tracker/node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "../tracker/node_modules/write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "dependencies": { + "mkdirp": "^0.5.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", + "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@openreplay/tracker": { + "resolved": "../tracker", + "link": true + }, + "node_modules/@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.0.0.tgz", + "integrity": "sha512-2pTGuibAXJswAPJjaKisthqS/NOK5ypG4LYT6tEAV0S/mxW0zOIvYvGK0V8w8+SHxAm6vRMSjqSalFXeBAqs+Q==" + }, + "node_modules/@types/minimist": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz", + "integrity": "sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==", + "dev": true + }, + "node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "dev": true + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" + }, + "node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/engine.io-client": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.1.1.tgz", + "integrity": "sha512-V05mmDo4gjimYW+FGujoGmmmxRaDsrVr7AXA3ZIfa04MWM1jOfZfUwou0oNqhNwy/votUDvGDt4JA4QF4e0b4g==", + "dependencies": { + "@socket.io/component-emitter": "~3.0.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.0", + "has-cors": "1.1.0", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "ws": "~8.2.3", + "xmlhttprequest-ssl": "~2.0.0", + "yeast": "0.1.2" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "dependencies": { + "@socket.io/base64-arraybuffer": "~1.0.2" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" + }, + "node_modules/fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/map-obj": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.1.tgz", + "integrity": "sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.1.tgz", + "integrity": "sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^2.5.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.13.1", + "yargs-parser": "^18.1.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minimist-options/node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-dragndrop": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/npm-dragndrop/-/npm-dragndrop-1.2.0.tgz", + "integrity": "sha1-bgUkAP7Yay8eP0csU4EPkjcRu7U=" + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseqs": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" + }, + "node_modules/parseuri": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/peerjs": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/peerjs/-/peerjs-1.3.2.tgz", + "integrity": "sha512-+PHfmsC7QGUU8Ye3OLi6tKQZGPCNy7QatUVNw4JtE8alkguF3+DdO5W0bzepqP2OtE9FqH/ltXt37qyvHw2CqA==", + "dependencies": { + "@types/node": "^10.14.33", + "eventemitter3": "^3.1.2", + "peerjs-js-binarypack": "1.0.1", + "webrtc-adapter": "^7.7.1" + } + }, + "node_modules/peerjs-js-binarypack": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/peerjs-js-binarypack/-/peerjs-js-binarypack-1.0.1.tgz", + "integrity": "sha512-N6aeia3NhdpV7kiGxJV5xQiZZCVEEVjRz2T2C6UZQiBkHWHzUv/oWA4myQLcwBwO8LUoR1KWW5oStvwVesmfCg==" + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/replace-in-files-cli": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-in-files-cli/-/replace-in-files-cli-1.0.0.tgz", + "integrity": "sha512-/HMPLZeCA24CBUQ59ymHji6LyMKM+gEgDZlYsiPvXW6+3PdfOw6SsMCVd9KC2B+KlAEe/8vkJA6gfnexVdF15A==", + "dev": true, + "dependencies": { + "arrify": "^2.0.1", + "escape-string-regexp": "^4.0.0", + "globby": "^11.0.1", + "meow": "^7.1.1", + "normalize-path": "^3.0.0", + "write-file-atomic": "^3.0.0" + }, + "bin": { + "replace-in-files": "cli.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rtcpeerconnection-shim": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz", + "integrity": "sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw==", + "dependencies": { + "sdp": "^2.6.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=3.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/sdp": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-2.12.0.tgz", + "integrity": "sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/socket.io-client": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.4.1.tgz", + "integrity": "sha512-N5C/L5fLNha5Ojd7Yeb/puKcPWWcoB/A09fEjjNsg91EDVr5twk/OEyO6VT9dlLSUNY85NpW6KBhVMvaLKQ3vQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.0.0", + "backo2": "~1.0.2", + "debug": "~4.3.2", + "engine.io-client": "~6.1.1", + "parseuri": "0.0.6", + "socket.io-parser": "~4.1.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.1.1.tgz", + "integrity": "sha512-USQVLSkDWE5nbcY760ExdKaJxCE65kcsG/8k5FDGZVVxpD1pA7hABYXYkCUvxUuYYh/+uQw0N/fvBzfT8o07KA==", + "dependencies": { + "@socket.io/component-emitter": "~3.0.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "dev": true + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.6.0-dev.20211126", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.0-dev.20211126.tgz", + "integrity": "sha512-m+LKstqVv6FYW363aIbO6bm8awsLbeSUCzU6FxPtzUF/WJkFieQfYmdVwEIzigeTpw4E2GETBXnk6P6AixcQJQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/webrtc-adapter": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-7.7.1.tgz", + "integrity": "sha512-TbrbBmiQBL9n0/5bvDdORc6ZfRY/Z7JnEj+EYOD1ghseZdpJ+nF2yx14k3LgQKc7JZnG7HAcL+zHnY25So9d7A==", + "dependencies": { + "rtcpeerconnection-shim": "^1.2.15", + "sdp": "^2.12.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=3.10.0" + } + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + } + }, "dependencies": { "@babel/code-frame": { "version": "7.14.5", @@ -58,15 +3949,28 @@ }, "@openreplay/tracker": { "version": "file:../tracker", - "dev": true, "requires": { - "error-stack-parser": "^2.0.6" + "@babel/core": "^7.10.2", + "@rollup/plugin-babel": "^5.0.3", + "@rollup/plugin-node-resolve": "^8.0.1", + "@typescript-eslint/eslint-plugin": "^2.34.0", + "@typescript-eslint/parser": "^2.34.0", + "error-stack-parser": "^2.0.6", + "eslint": "^6.8.0", + "eslint-plugin-prettier": "^3.1.4", + "prettier": "^2.0.0", + "replace-in-files": "^2.0.3", + "rollup": "^2.17.0", + "rollup-plugin-terser": "^6.1.0", + "semver": "^6.3.0", + "typescript": "^4.6.0-dev.20211126" }, "dependencies": { "@babel/code-frame": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, "requires": { "@babel/highlight": "^7.8.3" } @@ -75,6 +3979,7 @@ "version": "7.10.2", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz", "integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==", + "dev": true, "requires": { "@babel/code-frame": "^7.10.1", "@babel/generator": "^7.10.2", @@ -98,6 +4003,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "dev": true, "requires": { "@babel/highlight": "^7.10.1" } @@ -106,6 +4012,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.1", "chalk": "^2.0.0", @@ -115,7 +4022,8 @@ "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, @@ -123,6 +4031,7 @@ "version": "7.10.2", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz", "integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==", + "dev": true, "requires": { "@babel/types": "^7.10.2", "jsesc": "^2.5.1", @@ -134,6 +4043,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz", "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==", + "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.10.1", "@babel/template": "^7.10.1", @@ -144,6 +4054,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz", "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==", + "dev": true, "requires": { "@babel/types": "^7.10.1" } @@ -152,6 +4063,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz", "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==", + "dev": true, "requires": { "@babel/types": "^7.10.1" } @@ -160,6 +4072,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz", "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==", + "dev": true, "requires": { "@babel/types": "^7.10.1" } @@ -168,6 +4081,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz", "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==", + "dev": true, "requires": { "@babel/helper-module-imports": "^7.10.1", "@babel/helper-replace-supers": "^7.10.1", @@ -182,6 +4096,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz", "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==", + "dev": true, "requires": { "@babel/types": "^7.10.1" } @@ -190,6 +4105,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz", "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==", + "dev": true, "requires": { "@babel/helper-member-expression-to-functions": "^7.10.1", "@babel/helper-optimise-call-expression": "^7.10.1", @@ -201,6 +4117,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz", "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==", + "dev": true, "requires": { "@babel/template": "^7.10.1", "@babel/types": "^7.10.1" @@ -210,6 +4127,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz", "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==", + "dev": true, "requires": { "@babel/types": "^7.10.1" } @@ -217,12 +4135,14 @@ "@babel/helper-validator-identifier": { "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", - "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==" + "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", + "dev": true }, "@babel/helpers": { "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz", "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==", + "dev": true, "requires": { "@babel/template": "^7.10.1", "@babel/traverse": "^7.10.1", @@ -233,6 +4153,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, "requires": { "chalk": "^2.0.0", "esutils": "^2.0.2", @@ -242,12 +4163,14 @@ "@babel/parser": { "version": "7.10.2", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz", - "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==" + "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==", + "dev": true }, "@babel/template": { "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz", "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==", + "dev": true, "requires": { "@babel/code-frame": "^7.10.1", "@babel/parser": "^7.10.1", @@ -258,6 +4181,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "dev": true, "requires": { "@babel/highlight": "^7.10.1" } @@ -266,6 +4190,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.1", "chalk": "^2.0.0", @@ -278,6 +4203,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz", "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==", + "dev": true, "requires": { "@babel/code-frame": "^7.10.1", "@babel/generator": "^7.10.1", @@ -294,6 +4220,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "dev": true, "requires": { "@babel/highlight": "^7.10.1" } @@ -302,6 +4229,7 @@ "version": "7.10.1", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.1", "chalk": "^2.0.0", @@ -311,7 +4239,8 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true } } }, @@ -319,6 +4248,7 @@ "version": "7.10.2", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz", "integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==", + "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.1", "lodash": "^4.17.13", @@ -329,6 +4259,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, "requires": { "@nodelib/fs.stat": "2.0.3", "run-parallel": "^1.1.9" @@ -337,12 +4268,14 @@ "@nodelib/fs.stat": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==" + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "dev": true }, "@nodelib/fs.walk": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.3", "fastq": "^1.6.0" @@ -352,6 +4285,7 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.0.3.tgz", "integrity": "sha512-NlaPf4E6YFxeOCbqc+A2PTkB1BSy3rfKu6EJuQ1MGhMHpTVvMqKi6Rf0DlwtnEsTNK9LueUgsGEgp5Occ4KDVA==", + "dev": true, "requires": { "@babel/helper-module-imports": "^7.7.4", "@rollup/pluginutils": "^3.0.8" @@ -361,6 +4295,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.0.1.tgz", "integrity": "sha512-KIeAmueDDaYMqMBnUngLVVZhURwxA12nq/YB6nGm5/JpVyOMwI1fCVU3oL/dAnnLBG7oiPXntO5LHOiMrfNXCA==", + "dev": true, "requires": { "@rollup/pluginutils": "^3.0.8", "@types/resolve": "0.0.8", @@ -375,6 +4310,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, "requires": { "@types/estree": "0.0.39", "estree-walker": "^1.0.1", @@ -384,17 +4320,20 @@ "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==" + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true }, "@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true }, "@types/glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.2.tgz", "integrity": "sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA==", + "dev": true, "requires": { "@types/minimatch": "*", "@types/node": "*" @@ -403,22 +4342,26 @@ "@types/json-schema": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", - "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==" + "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", + "dev": true }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true }, "@types/node": { "version": "14.0.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", - "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==" + "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==", + "dev": true }, "@types/resolve": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, "requires": { "@types/node": "*" } @@ -427,6 +4370,7 @@ "version": "2.34.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz", "integrity": "sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ==", + "dev": true, "requires": { "@typescript-eslint/experimental-utils": "2.34.0", "functional-red-black-tree": "^1.0.1", @@ -438,6 +4382,7 @@ "version": "2.34.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz", "integrity": "sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==", + "dev": true, "requires": { "@types/json-schema": "^7.0.3", "@typescript-eslint/typescript-estree": "2.34.0", @@ -449,6 +4394,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" } @@ -459,6 +4405,7 @@ "version": "2.34.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.34.0.tgz", "integrity": "sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA==", + "dev": true, "requires": { "@types/eslint-visitor-keys": "^1.0.0", "@typescript-eslint/experimental-utils": "2.34.0", @@ -470,6 +4417,7 @@ "version": "2.34.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", "integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==", + "dev": true, "requires": { "debug": "^4.1.1", "eslint-visitor-keys": "^1.1.0", @@ -483,24 +4431,29 @@ "semver": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true } } }, "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true }, "acorn-jsx": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", - "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==" + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true, + "requires": {} }, "ajv": { "version": "6.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -512,6 +4465,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, "requires": { "type-fest": "^0.21.3" }, @@ -519,19 +4473,22 @@ "type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true } } }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -540,6 +4497,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -547,27 +4505,32 @@ "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "binaryextensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", - "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==" + "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==", + "dev": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -576,22 +4539,26 @@ "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true }, "builtin-modules": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", - "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -601,12 +4568,14 @@ "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, "requires": { "restore-cursor": "^3.1.0" } @@ -614,17 +4583,20 @@ "cli-width": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -632,22 +4604,26 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "convert-source-map": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, "requires": { "safe-buffer": "~5.1.1" } @@ -656,6 +4632,7 @@ "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -667,7 +4644,8 @@ "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, @@ -675,6 +4653,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, "requires": { "ms": "^2.1.1" } @@ -682,22 +4661,26 @@ "deep-freeze": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz", - "integrity": "sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ=" + "integrity": "sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ=", + "dev": true }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true }, "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, "requires": { "path-type": "^4.0.0" }, @@ -705,7 +4688,8 @@ "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true } } }, @@ -713,6 +4697,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, "requires": { "esutils": "^2.0.2" } @@ -721,6 +4706,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/editions/-/editions-2.3.1.tgz", "integrity": "sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA==", + "dev": true, "requires": { "errlop": "^2.0.0", "semver": "^6.3.0" @@ -729,12 +4715,14 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "errlop": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/errlop/-/errlop-2.2.0.tgz", - "integrity": "sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw==" + "integrity": "sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw==", + "dev": true }, "error-stack-parser": { "version": "2.0.6", @@ -748,17 +4736,20 @@ "es6-promisify": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.1.1.tgz", - "integrity": "sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==" + "integrity": "sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==", + "dev": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "eslint": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "ajv": "^6.10.0", @@ -802,7 +4793,8 @@ "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true } } }, @@ -810,6 +4802,7 @@ "version": "3.1.4", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", + "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" } @@ -818,6 +4811,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" @@ -827,6 +4821,7 @@ "version": "1.4.3", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" } @@ -834,12 +4829,14 @@ "eslint-visitor-keys": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==" + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true }, "espree": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "dev": true, "requires": { "acorn": "^7.1.0", "acorn-jsx": "^5.1.0", @@ -849,12 +4846,14 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true }, "esquery": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz", "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==", + "dev": true, "requires": { "estraverse": "^4.0.0" } @@ -863,6 +4862,7 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, "requires": { "estraverse": "^4.1.0" } @@ -870,22 +4870,26 @@ "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true }, "estree-walker": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, "requires": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", @@ -895,17 +4899,20 @@ "fast-deep-equal": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true }, "fast-diff": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true }, "fast-glob": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -919,6 +4926,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -927,6 +4935,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -934,12 +4943,14 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true }, "micromatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, "requires": { "braces": "^3.0.1", "picomatch": "^2.0.5" @@ -949,6 +4960,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "requires": { "is-number": "^7.0.0" } @@ -958,17 +4970,20 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true }, "fastq": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", + "dev": true, "requires": { "reusify": "^1.0.4" } @@ -977,6 +4992,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, "requires": { "escape-string-regexp": "^1.0.5" } @@ -985,6 +5001,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, "requires": { "flat-cache": "^2.0.1" } @@ -993,6 +5010,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, "requires": { "flatted": "^2.0.0", "rimraf": "2.6.3", @@ -1002,27 +5020,32 @@ "flatted": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==" + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true }, "gensync": { "version": "1.0.0-beta.1", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1036,6 +5059,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -1044,6 +5068,7 @@ "version": "12.3.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", + "dev": true, "requires": { "type-fest": "^0.8.1" } @@ -1052,6 +5077,7 @@ "version": "10.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, "requires": { "@types/glob": "^7.1.1", "array-union": "^2.1.0", @@ -1066,19 +5092,22 @@ "ignore": { "version": "5.1.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true } } }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -1086,12 +5115,14 @@ "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true }, "import-fresh": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -1100,12 +5131,14 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -1114,12 +5147,14 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "inquirer": { "version": "7.3.3", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, "requires": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.0", @@ -1140,6 +5175,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -1148,6 +5184,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1157,6 +5194,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { "color-name": "~1.1.4" } @@ -1164,17 +5202,20 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -1183,6 +5224,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -1192,17 +5234,20 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -1210,17 +5255,20 @@ "is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=" + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "istextorbinary": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.6.0.tgz", "integrity": "sha512-+XRlFseT8B3L9KyjxxLjfXSLMuErKDsd8DBNrsaxoViABMEZlOSCstwmw0qpoFX3+U6yWU1yhLudAe6/lETGGA==", + "dev": true, "requires": { "binaryextensions": "^2.1.2", "editions": "^2.2.0", @@ -1231,6 +5279,7 @@ "version": "26.0.0", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.0.0.tgz", "integrity": "sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw==", + "dev": true, "requires": { "merge-stream": "^2.0.0", "supports-color": "^7.0.0" @@ -1239,12 +5288,14 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "supports-color": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -1254,12 +5305,14 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -1268,22 +5321,26 @@ "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true }, "json5": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, "requires": { "minimist": "^1.2.5" }, @@ -1291,7 +5348,8 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true } } }, @@ -1299,6 +5357,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, "requires": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -1307,27 +5366,32 @@ "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true }, "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -1335,12 +5399,14 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, "requires": { "minimist": "^1.2.5" } @@ -1348,27 +5414,32 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -1377,6 +5448,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, "requires": { "mimic-fn": "^2.1.0" } @@ -1385,6 +5457,7 @@ "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, "requires": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -1397,12 +5470,14 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "requires": { "callsites": "^3.0.0" } @@ -1410,37 +5485,44 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true }, "prettier": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", - "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==" + "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==", + "dev": true }, "prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, "requires": { "fast-diff": "^1.1.2" } @@ -1448,17 +5530,20 @@ "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "requires": { "safe-buffer": "^5.1.0" } @@ -1466,12 +5551,14 @@ "regexpp": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==" + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true }, "replace-in-files": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/replace-in-files/-/replace-in-files-2.0.3.tgz", "integrity": "sha512-wm9kg+WhKQ10CFaCS9jvUtgw9JnaPilm4TqSRq57H06v5EgX7hTrr/qwgyvq3G+IeNhmr6VTW84LvfnpZfq5/g==", + "dev": true, "requires": { "co": "^4.6.0", "es6-promisify": "^6.0.2", @@ -1484,6 +5571,7 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, "requires": { "path-parse": "^1.0.6" } @@ -1491,12 +5579,14 @@ "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, "requires": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -1505,12 +5595,14 @@ "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, "requires": { "glob": "^7.1.3" } @@ -1519,6 +5611,7 @@ "version": "2.17.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.17.0.tgz", "integrity": "sha512-4Um68vKyyTLzT+EWClgc+nyxSlunlmx8wgCO16RDicwxvccnyBHguoNqxPaJL/YPAdvuAJkqaFPf/BfDojzEZA==", + "dev": true, "requires": { "fsevents": "~2.1.2" }, @@ -1527,6 +5620,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, "optional": true } } @@ -1535,6 +5629,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-6.1.0.tgz", "integrity": "sha512-4fB3M9nuoWxrwm39habpd4hvrbrde2W2GG4zEGPQg1YITNkM3Tqur5jSuXlWNzbv/2aMLJ+dZJaySc3GCD8oDw==", + "dev": true, "requires": { "@babel/code-frame": "^7.8.3", "jest-worker": "^26.0.0", @@ -1545,17 +5640,20 @@ "run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true }, "run-parallel": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true }, "rxjs": { "version": "6.6.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, "requires": { "tslib": "^1.9.0" } @@ -1563,22 +5661,26 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true }, "serialize-javascript": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "dev": true, "requires": { "randombytes": "^2.1.0" } @@ -1587,6 +5689,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, "requires": { "shebang-regex": "^1.0.0" } @@ -1594,22 +5697,26 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true }, "signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", + "dev": true }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true }, "slice-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.0", "astral-regex": "^1.0.0", @@ -1619,19 +5726,22 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true } } }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true }, "source-map-support": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -1640,14 +5750,16 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true }, "stackframe": { "version": "1.2.0", @@ -1659,6 +5771,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -1669,6 +5782,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -1679,6 +5793,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, "requires": { "ansi-regex": "^4.1.0" }, @@ -1686,19 +5801,22 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true } } }, "strip-json-comments": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==" + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -1707,6 +5825,7 @@ "version": "5.4.6", "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, "requires": { "ajv": "^6.10.2", "lodash": "^4.17.14", @@ -1717,17 +5836,20 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -1740,6 +5862,7 @@ "version": "4.8.0", "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, "requires": { "commander": "^2.20.0", "source-map": "~0.6.1", @@ -1749,29 +5872,34 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true }, "textextensions": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.6.0.tgz", - "integrity": "sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ==" + "integrity": "sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ==", + "dev": true }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, "requires": { "os-tmpdir": "~1.0.2" } @@ -1779,17 +5907,20 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true }, "tslib": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz", - "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==" + "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==", + "dev": true }, "tsutils": { "version": "3.17.1", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, "requires": { "tslib": "^1.8.1" } @@ -1798,6 +5929,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, "requires": { "prelude-ls": "~1.1.2" } @@ -1805,17 +5937,20 @@ "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true }, "typescript": { "version": "4.6.0-dev.20211126", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.0-dev.20211126.tgz", - "integrity": "sha512-m+LKstqVv6FYW363aIbO6bm8awsLbeSUCzU6FxPtzUF/WJkFieQfYmdVwEIzigeTpw4E2GETBXnk6P6AixcQJQ==" + "integrity": "sha512-m+LKstqVv6FYW363aIbO6bm8awsLbeSUCzU6FxPtzUF/WJkFieQfYmdVwEIzigeTpw4E2GETBXnk6P6AixcQJQ==", + "dev": true }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -1823,12 +5958,14 @@ "v8-compile-cache": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==" + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, "requires": { "isexe": "^2.0.0" } @@ -1836,17 +5973,20 @@ "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "write": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, "requires": { "mkdirp": "^0.5.1" } @@ -1966,6 +6106,11 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==" + }, "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -2712,7 +6857,8 @@ "ws": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "requires": {} }, "xmlhttprequest-ssl": { "version": "2.0.0", diff --git a/tracker/tracker-assist/package.json b/tracker/tracker-assist/package.json index bb2edd4ab..30f85875b 100644 --- a/tracker/tracker-assist/package.json +++ b/tracker/tracker-assist/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker-assist", "description": "Tracker plugin for screen assistance through the WebRTC", - "version": "3.5.0", + "version": "3.5.5", "keywords": [ "WebRTC", "assistance", @@ -20,10 +20,11 @@ "replace-paths": "replace-in-files cjs/* --string='@openreplay/tracker' --replacement='@openreplay/tracker/cjs' && replace-in-files cjs/* --string='/lib/' --replacement='/'", "replace-versions": "npm run replace-pkg-version && npm run replace-req-version", "replace-pkg-version": "replace-in-files lib/* cjs/* --string='PACKAGE_VERSION' --replacement=$npm_package_version", - "replace-req-version": "replace-in-files lib/* cjs/* --string='REQUIRED_TRACKER_VERSION' --replacement='3.5.0'", + "replace-req-version": "replace-in-files lib/* cjs/* --string='REQUIRED_TRACKER_VERSION' --replacement='3.5.3'", "prepublishOnly": "npm run build" }, "dependencies": { + "csstype": "^3.0.10", "npm-dragndrop": "^1.2.0", "peerjs": "^1.3.2", "socket.io-client": "^4.4.1" diff --git a/tracker/tracker-assist/src/Assist.ts b/tracker/tracker-assist/src/Assist.ts index f9e010559..b5272510b 100644 --- a/tracker/tracker-assist/src/Assist.ts +++ b/tracker/tracker-assist/src/Assist.ts @@ -14,10 +14,14 @@ import type { Options as ConfirmOptions } from './ConfirmWindow.js'; //@ts-ignore peerjs hack for webpack5 (?!) TODO: ES/node modules; Peer = Peer.default || Peer; +type BehinEndCallback = () => ((()=>{}) | void) + export interface Options { - onAgentConnect: () => ((()=>{}) | void), - onCallStart: () => ((()=>{}) | void), + onAgentConnect: BehinEndCallback, + onCallStart: BehinEndCallback, + onRemoteControlStart: BehinEndCallback, session_calling_peer_key: string, + session_control_peer_key: string, callConfirm: ConfirmOptions, controlConfirm: ConfirmOptions, @@ -58,29 +62,53 @@ export default class Assist { ) { this.options = Object.assign({ session_calling_peer_key: "__openreplay_calling_peer", + session_control_peer_key: "__openreplay_control_peer", config: null, onCallStart: ()=>{}, onAgentConnect: ()=>{}, + onRemoteControlStart: ()=>{}, callConfirm: {}, controlConfirm: {}, // TODO: clear options passing/merging/overriting }, options, ); - app.attachStartCallback(() => { - if (this.assistDemandedRestart) { return; } - this.onStart() + + if (document.hidden !== undefined) { + const sendActivityState = () => this.emit("UPDATE_SESSION", { active: !document.hidden }) + app.attachEventListener( + document, + 'visibilitychange', + sendActivityState, + false, + false, + ) + } + const titleNode = document.querySelector('title') + const observer = titleNode && new MutationObserver(() => { + this.emit("UPDATE_SESSION", { pageTitle: document.title }) }) - app.attachCommitCallback((messages) => { - if (this.socket && this.agentsConnected) { - // @ts-ignore No need in statistics messages. TODO proper filter - if (messages.length === 2 && messages[0]._id === 0 && messages[1]._id === 49) { return } - this.socket.emit("messages", messages) - } + app.attachStartCallback(() => { + if (this.assistDemandedRestart) { return; } + this.onStart() + observer && observer.observe(titleNode, { subtree: true, characterData: true, childList: true }) }) app.attachStopCallback(() => { if (this.assistDemandedRestart) { return; } this.clean() + observer && observer.disconnect() }) + app.attachCommitCallback((messages) => { + if (this.agentsConnected) { + // @ts-ignore No need in statistics messages. TODO proper filter + if (messages.length === 2 && messages[0]._id === 0 && messages[1]._id === 49) { return } + this.emit("messages", messages) + } + }) + app.session.attachUpdateCallback(sessInfo => this.emit("UPDATE_SESSION", sessInfo)) + } + + private emit(ev: string, ...args) { + this.socket && this.socket.emit(ev, ...args) } private get agentsConnected(): boolean { @@ -88,7 +116,7 @@ export default class Assist { } private notifyCallEnd() { - this.socket && this.socket.emit("call_end"); + this.emit("call_end"); } private onRemoteCallEnd = () => {} @@ -102,8 +130,12 @@ export default class Assist { query: { "peerId": peerID, "identity": "session", - "sessionInfo": JSON.stringify(this.app.getSessionInfo()), - } + "sessionInfo": JSON.stringify({ + pageTitle: document.title, + ...this.app.getSessionInfo() + }), + }, + transports: ["websocket"], }) socket.onAny((...args) => app.debug.log("Socket:", ...args)) @@ -125,37 +157,57 @@ export default class Assist { this.assistDemandedRestart = true this.app.stop(); this.app.start().then(() => { this.assistDemandedRestart = false }) + const storedControllingAgent = sessionStorage.getItem(this.options.session_control_peer_key) + if (storedControllingAgent !== null && ids.includes(storedControllingAgent)) { + grantControl(storedControllingAgent) + socket.emit("control_granted", storedControllingAgent) + } else { + sessionStorage.removeItem(this.options.session_control_peer_key) + } }) let confirmRC: ConfirmWindow | null = null const mouse = new Mouse() // TODO: lazy init let controllingAgent: string | null = null - function releaseControl() { - confirmRC?.remove() - mouse.remove() - controllingAgent = null - } - socket.on("request_control", (id: string) => { + const requestControl = (id: string) => { if (controllingAgent !== null) { socket.emit("control_rejected", id) return } - controllingAgent = id + controllingAgent = id // TODO: more explicit pending state confirmRC = new ConfirmWindow(controlConfirmDefault(this.options.controlConfirm)) confirmRC.mount().then(allowed => { - if (allowed) { // TODO: per agent id - mouse.mount() + if (allowed) { + grantControl(id) socket.emit("control_granted", id) } else { releaseControl() socket.emit("control_rejected", id) } }).catch() - }) + } + let onRemoteControlStop: (()=>void) | null = null + const grantControl = (id: string) => { + controllingAgent = id + mouse.mount() + onRemoteControlStop = this.options.onRemoteControlStart() || null + sessionStorage.setItem(this.options.session_control_peer_key, id) + } + const releaseControl = () => { + typeof onRemoteControlStop === 'function' && onRemoteControlStop() + onRemoteControlStop = null + confirmRC?.remove() + mouse.remove() + controllingAgent = null + sessionStorage.removeItem(this.options.session_control_peer_key) + } + socket.on("request_control", requestControl) socket.on("release_control", (id: string) => { if (controllingAgent !== id) { return } releaseControl() }) + + socket.on("scroll", (id, d) => { id === controllingAgent && mouse.scroll(d) }) socket.on("click", (id, xy) => { id === controllingAgent && mouse.click(xy) }) socket.on("move", (id, xy) => { id === controllingAgent && mouse.move(xy) }) diff --git a/tracker/tracker-assist/tsconfig.json b/tracker/tracker-assist/tsconfig.json index 95d4f9408..bb8f6a4c4 100644 --- a/tracker/tracker-assist/tsconfig.json +++ b/tracker/tracker-assist/tsconfig.json @@ -5,7 +5,7 @@ "alwaysStrict": true, "target": "es6", "module": "es6", - "moduleResolution": "nodenext", + "moduleResolution": "node", "allowSyntheticDefaultImports": true, "declaration": true, "outDir": "./lib" diff --git a/tracker/tracker-fetch/package.json b/tracker/tracker-fetch/package.json index 1d650bf6e..11e7bf6ff 100644 --- a/tracker/tracker-fetch/package.json +++ b/tracker/tracker-fetch/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker-fetch", "description": "Tracker plugin for fetch requests recording ", - "version": "3.4.1", + "version": "3.5.1", "keywords": [ "fetch", "logging", diff --git a/tracker/tracker-fetch/src/index.ts b/tracker/tracker-fetch/src/index.ts index fbce7ac31..910d20ec7 100644 --- a/tracker/tracker-fetch/src/index.ts +++ b/tracker/tracker-fetch/src/index.ts @@ -1,10 +1,25 @@ import { App, Messages } from '@openreplay/tracker'; +interface Request { + url: string, + body: string | Object, + headers: Record, +} + +interface Response { + url: string, + status: number, + body: string, + headers: Record, +} + export interface Options { sessionTokenHeader?: string; replaceDefault: boolean; // overrideDefault ? failuresOnly: boolean; ignoreHeaders: Array | boolean; + requestSanitizer: ((Request) => Request | null) | null; + responseSanitizer: ((Response) => Response | null) | null; } export default function(opts: Partial = {}) { @@ -13,10 +28,11 @@ export default function(opts: Partial = {}) { replaceDefault: false, failuresOnly: false, ignoreHeaders: [ 'Cookie', 'Set-Cookie', 'Authorization' ], + requestSanitizer: null, + responseSanitizer: null, }, opts, ); - return (app: App | null) => { if (app === null) { return window.fetch; @@ -55,6 +71,7 @@ export default function(opts: Partial = {}) { const r = response.clone(); r.text().then(text => { + // Headers prepearing const reqHs: Record = {} const resHs: Record = {} if (ihOpt !== true) { @@ -71,20 +88,57 @@ export default function(opts: Partial = {}) { r.headers.forEach((v, n) => { if (!isHIgnoring(n)) resHs[n] = v }) } - const req = JSON.stringify({ + + // Request forming + let reqBody = '' + if (typeof init.body === 'string') { + reqBody = init.body + } else if (typeof init.body === 'object') { + try { + reqBody = JSON.stringify(init.body) + } catch {} + } + let req: Request | null = { + url: input, headers: reqHs, - body: typeof init.body === 'string' ? init.body : '', - }) - const res = JSON.stringify({ + body: reqBody, + } + if (options.requestSanitizer !== null) { + req = options.requestSanitizer(req) + if (!req) { + return + } + } + + // Response forming + let res: Response | null = { + url: input, + status: r.status, headers: resHs, body: text, + } + if (options.responseSanitizer !== null) { + res = options.responseSanitizer(res) + if (!res) { + return + } + } + + const reqStr = JSON.stringify({ + headers: req.headers, + body: req.body, }) + const resStr = JSON.stringify({ + headers: res.headers, + body: res.body, + }) + app.send( Messages.Fetch( typeof init.method === 'string' ? init.method.toUpperCase() : 'GET', input, - req, - res, + reqStr, + resStr, r.status, startTime + performance.timing.navigationStart, duration, diff --git a/tracker/tracker/package.json b/tracker/tracker/package.json index 744a2a375..e485faf11 100644 --- a/tracker/tracker/package.json +++ b/tracker/tracker/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker", "description": "The OpenReplay tracker main package", - "version": "3.5.1", + "version": "3.5.3", "keywords": [ "logging", "replay" @@ -41,6 +41,6 @@ "error-stack-parser": "^2.0.6" }, "engines": { - "node": ">=14" + "node": ">=12" } } diff --git a/tracker/tracker/src/main/app/index.ts b/tracker/tracker/src/main/app/index.ts index ca747411c..59129cbec 100644 --- a/tracker/tracker/src/main/app/index.ts +++ b/tracker/tracker/src/main/app/index.ts @@ -6,6 +6,7 @@ import Observer from "./observer/top_observer.js"; import Sanitizer from "./sanitizer.js"; import Ticker from "./ticker.js"; import Logger, { LogLevel } from "./logger.js"; +import Session from "./session.js"; import { deviceMemory, jsHeapSizeLimit } from "../modules/performance.js"; @@ -69,6 +70,7 @@ export default class App { readonly sanitizer: Sanitizer; readonly debug: Logger; readonly notify: Logger; + readonly session: Session; private readonly messages: Array = []; private readonly observer: Observer; private readonly startCallbacks: Array = []; @@ -76,9 +78,6 @@ export default class App { private readonly commitCallbacks: Array = []; private readonly options: AppOptions; private readonly revID: string; - private _sessionID: string | null = null; - private _userID: string | null = null; - private _metadata: Record = {}; private activityState: ActivityState = ActivityState.NotActive; private version = 'TRACKER_VERSION'; // TODO: version compatability check inside each plugin. private readonly worker?: Worker; @@ -120,6 +119,7 @@ export default class App { this.ticker.attach(() => this.commit()); this.debug = new Logger(this.options.__debug__); this.notify = new Logger(this.options.verbose ? LogLevel.Warnings : LogLevel.Silent); + this.session = new Session(this); try { this.worker = new Worker( URL.createObjectURL( @@ -129,18 +129,12 @@ export default class App { this.worker.onerror = e => { this._debug("webworker_error", e) } - let lastTs = timestamp(); - let fileno = 0; this.worker.onmessage = ({ data }: MessageEvent) => { if (data === null) { this.stop(); } else if (data === "restart") { this.stop(); - this.start({ - forceNew: true, - userID: this._userID || undefined, - metadata: this._metadata || undefined, - }); + this.start({ forceNew: true }); } }; const alertWorker = () => { @@ -197,10 +191,6 @@ export default class App { } } - attachCommitCallback(cb: CommitCallback): void { - this.commitCallbacks.push(cb) - } - safe void>(fn: T): T { const app = this; return function (this: any, ...args: any) { @@ -216,6 +206,10 @@ export default class App { } as any // TODO: correct typing } + attachCommitCallback(cb: CommitCallback): void { + this.commitCallbacks.push(cb) + } + attachStartCallback(cb: Callback): void { this.startCallbacks.push(cb); } @@ -258,15 +252,12 @@ export default class App { revID: this.revID, timestamp: timestamp(), trackerVersion: this.version, - userID: this._userID, isSnippet: this.options.__is_snippet, } - } getSessionInfo() { return { - sessionID: this._sessionID, - metadata: this._metadata, + ...this.session.getInfo(), ...this.getStartInfo() } } @@ -277,7 +268,7 @@ export default class App { } } getSessionID(): string | undefined { - return this._sessionID || undefined; + return this.session.getInfo().sessionID || undefined; } getHost(): string { return new URL(this.options.ingestPoint).hostname @@ -338,10 +329,7 @@ export default class App { } sessionStorage.setItem(this.options.session_pageno_key, pageNo.toString()); - this._userID = startOpts.userID || null - this._metadata = startOpts.metadata || {} // TODO: update both dynamically on corresponding messages const startInfo = this.getStartInfo() - const messageData: WorkerMessageData = { ingestPoint: this.options.ingestPoint, pageNo, @@ -361,6 +349,7 @@ export default class App { }, body: JSON.stringify({ ...startInfo, + userID: startOpts.userID || this.session.getInfo().userID, token: sessionStorage.getItem(this.options.session_token_key), deviceMemory, jsHeapSizeLimit, @@ -389,9 +378,10 @@ export default class App { } sessionStorage.setItem(this.options.session_token_key, token); localStorage.setItem(this.options.local_uuid_key, userUUID); - if (typeof sessionID === 'string') { - this._sessionID = sessionID; - } + this.session.update({ + sessionID, // any. TODO check + ...startOpts + }); this.activityState = ActivityState.Active this.worker.postMessage({ token, beaconSizeLimit }); @@ -399,9 +389,6 @@ export default class App { this.observer.observe(); this.ticker.start(); - Object.entries(this._metadata).forEach(([key, value]) => - this.send(new Metadata(key, value))) - this.notify.log("OpenReplay tracking started."); // TODO: get rid of onStart const onStartInfo = { sessionToken: token, userUUID, sessionID }; diff --git a/tracker/tracker/src/main/app/logger.ts b/tracker/tracker/src/main/app/logger.ts index 42dfa5347..34d8c12c6 100644 --- a/tracker/tracker/src/main/app/logger.ts +++ b/tracker/tracker/src/main/app/logger.ts @@ -1,11 +1,9 @@ - - export const LogLevel = { - Verbose: 4, - Errors: 4, + Verbose: 5, + Log: 4, Warnings: 3, - Log: 2, + Errors: 2, Silent: 0, } as const; type LogLevel = typeof LogLevel[keyof typeof LogLevel] @@ -31,30 +29,30 @@ interface _Options { export type Options = true | _Options | LogLevel export default class Logger { - private readonly opts: _Options; - constructor(private readonly options: Options = LogLevel.Silent) { - this.opts = options === true + private readonly options: _Options; + constructor(options: Options = LogLevel.Silent) { + this.options = options === true ? { level: LogLevel.Verbose } : typeof options === "number" ? { level: options } : options; } log(...args: any) { - if (IsCustomLevel(this.opts.level) - ? this.opts.level.log - : this.opts.level >= LogLevel.Log) { + if (IsCustomLevel(this.options.level) + ? this.options.level.log + : this.options.level >= LogLevel.Log) { console.log(...args) } } warn(...args: any) { - if (IsCustomLevel(this.opts.level) - ? this.opts.level.warn - : this.opts.level >= LogLevel.Warnings) { + if (IsCustomLevel(this.options.level) + ? this.options.level.warn + : this.options.level >= LogLevel.Warnings) { console.warn(...args) } } error(...args: any) { - if (IsCustomLevel(this.opts.level) - ? this.opts.level.error - : this.opts.level >= LogLevel.Errors) { + if (IsCustomLevel(this.options.level) + ? this.options.level.error + : this.options.level >= LogLevel.Errors) { console.error(...args) } } diff --git a/tracker/tracker/src/main/app/session.ts b/tracker/tracker/src/main/app/session.ts new file mode 100644 index 000000000..ec5dadf51 --- /dev/null +++ b/tracker/tracker/src/main/app/session.ts @@ -0,0 +1,84 @@ +import App, { StartOptions } from "./index.js"; +import { UserID, UserAnonymousID, Metadata } from "../../messages/index.js"; + + +enum ActivityState { + NotActive, + Starting, + Active, +} + +interface SessionInfo { + sessionID: string | null, + metadata: Record, + userID: string | null, +} +type OnUpdateCallback = (i: Partial) => void + + +export default class Session { + private metadata: Record = {} + private userID: string | null = null + private sessionID: string | null = null + private activityState: ActivityState = ActivityState.NotActive + private callbacks: OnUpdateCallback[] = [] + + constructor(private app: App) {} + + + attachUpdateCallback(cb: OnUpdateCallback) { + this.callbacks.push(cb) + } + private handleUpdate() { + const sessInfo: Partial = this.getInfo() + if (sessInfo.userID == null) { + delete sessInfo.userID + } + if (sessInfo.sessionID == null) { + delete sessInfo.sessionID + } + this.callbacks.forEach(cb => cb(sessInfo)) + } + + update({ userID, metadata, sessionID }: Partial) { + if (userID != null) { // TODO clear nullable/undefinable types + this._setUserID(userID) + } + if (metadata !== undefined) { + Object.entries(metadata).forEach(kv => this._setMetadata(...kv)) + } + if (sessionID !== undefined) { + this.sessionID = sessionID + } + this.handleUpdate() + } + + private _setMetadata(key: string, value: string) { + this.app.send(new Metadata(key, value)) + this.metadata[key] = value + } + private _setUserID(userID: string) { + this.app.send(new UserID(userID)) + this.userID = userID + } + + + + setMetadata(key: string, value: string) { + this._setMetadata(key, value) + this.handleUpdate() + } + setUserID(userID: string) { + this._setUserID(userID) + this.handleUpdate() + } + + getInfo(): SessionInfo { + return { + sessionID: this.sessionID, + metadata: this.metadata, + userID: this.userID, + + } + } +} \ No newline at end of file diff --git a/tracker/tracker/src/main/index.ts b/tracker/tracker/src/main/index.ts index 3ef4d8c98..8961d6e54 100644 --- a/tracker/tracker/src/main/index.ts +++ b/tracker/tracker/src/main/index.ts @@ -15,7 +15,6 @@ import Timing from "./modules/timing.js"; import Performance from "./modules/performance.js"; import Scroll from "./modules/scroll.js"; import Viewport from "./modules/viewport.js"; -import Longtasks from "./modules/longtasks.js"; import CSSRules from "./modules/cssrules.js"; import { IN_BROWSER, deprecationWarn, DOCS_HOST } from "./utils.js"; @@ -109,7 +108,6 @@ export default class API { Timing(app, options); Performance(app, options); Scroll(app); - Longtasks(app); (window as any).__OPENREPLAY__ = this; if (options.autoResetOnWindowOpen) { @@ -190,7 +188,7 @@ export default class API { setUserID(id: string): void { if (typeof id === 'string' && this.app !== null) { - this.app.send(new UserID(id)); + this.app.session.setUserID(id); } } userID(id: string): void { @@ -214,7 +212,7 @@ export default class API { typeof value === 'string' && this.app !== null ) { - this.app.send(new Metadata(key, value)); + this.app.session.setMetadata(key, value); } } metadata(key: string, value: string): void { diff --git a/utilities/package-lock.json b/utilities/package-lock.json index 8fe161f1a..724f7341a 100644 --- a/utilities/package-lock.json +++ b/utilities/package-lock.json @@ -15,8 +15,7 @@ "peer": "^0.6.1", "socket.io": "^4.4.1", "source-map": "^0.7.3", - "ua-parser-js": "^1.0.2", - "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.6.0" + "ua-parser-js": "^1.0.2" } }, "node_modules/@maxmind/geoip2-node": { @@ -82,9 +81,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.26", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.26.tgz", - "integrity": "sha512-zeu3tpouA043RHxW0gzRxwCHchMgftE8GArRsvYT0ByDMbn19olQHx5jLue0LxWY6iYtXb7rXmuVtSkhy9YZvQ==", + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -97,9 +96,9 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "node_modules/@types/node": { - "version": "16.11.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", - "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==" + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" }, "node_modules/@types/qs": { "version": "6.9.7", @@ -129,12 +128,12 @@ } }, "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { "node": ">= 0.6" @@ -176,14 +175,14 @@ } }, "node_modules/aws-sdk": { - "version": "2.1043.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1043.0.tgz", - "integrity": "sha512-WysMTSLfi8ZCj6QAAitJkxObxOzGLhcu6FxoKHiEnrefvfQtSvwqUq7BbT/pIfijnF9dE/7e9XwjW8Dz/hqF4Q==", + "version": "2.1087.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1087.0.tgz", + "integrity": "sha512-m5EERT29Fwh2cv3SaSdygeAjJBXnjSaXRRERy70bf6PQ7KgmASJouBxY11g5G7LTEPK/yfB0TGshujKh3hEtPA==", "dependencies": { "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", - "jmespath": "0.15.0", + "jmespath": "0.16.0", "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", @@ -222,20 +221,20 @@ } }, "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", "dependencies": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "1.7.2", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" }, "engines": { "node": ">= 0.8" @@ -252,19 +251,22 @@ } }, "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } }, "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/camelcase-keys": { @@ -284,17 +286,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/camelcase-keys/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -327,11 +318,11 @@ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dependencies": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" }, "engines": { "node": ">= 0.6" @@ -346,9 +337,9 @@ } }, "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "engines": { "node": ">= 0.6" } @@ -423,9 +414,9 @@ } }, "node_modules/engine.io": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.2.tgz", - "integrity": "sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", + "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -435,7 +426,7 @@ "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.0.0", + "engine.io-parser": "~5.0.3", "ws": "~8.2.3" }, "engines": { @@ -453,14 +444,6 @@ "node": ">=10.0.0" } }, - "node_modules/engine.io/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/engine.io/node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -524,16 +507,16 @@ } }, "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", + "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", "dependencies": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.19.2", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.4.2", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", @@ -547,13 +530,13 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.9.7", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", "statuses": "~1.5.0", "type-is": "~1.6.18", "utils-merge": "1.0.1", @@ -625,15 +608,15 @@ } }, "node_modules/http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dependencies": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "toidentifier": "1.0.1" }, "engines": { "node": ">= 0.6" @@ -656,9 +639,9 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ip6addr": { "version": "0.2.5", @@ -691,9 +674,9 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "node_modules/jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", "engines": { "node": ">= 0.6.0" } @@ -823,9 +806,9 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { "node": ">= 0.6" } @@ -952,11 +935,14 @@ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" }, "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", "engines": { "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/querystring": { @@ -988,12 +974,12 @@ } }, "node_modules/raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -1015,9 +1001,23 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safer-buffer": { "version": "2.1.2", @@ -1030,9 +1030,9 @@ "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" }, "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", "dependencies": { "debug": "2.6.9", "depd": "~1.1.2", @@ -1041,9 +1041,9 @@ "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "1.8.1", "mime": "1.6.0", - "ms": "2.1.1", + "ms": "2.1.3", "on-finished": "~2.3.0", "range-parser": "~1.2.1", "statuses": "~1.5.0" @@ -1053,19 +1053,19 @@ } }, "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.17.2" }, "engines": { "node": ">= 0.8.0" @@ -1077,9 +1077,9 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/socket.io": { "version": "4.4.1", @@ -1206,9 +1206,9 @@ } }, "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "engines": { "node": ">=0.6" } @@ -1288,10 +1288,6 @@ "uuid": "bin/uuid" } }, - "node_modules/uWebSockets.js": { - "version": "20.6.0", - "resolved": "git+ssh://git@github.com/uNetworking/uWebSockets.js.git#a58e810e47a23696410f6073c8c905dc38f75da5" - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -1332,9 +1328,9 @@ } }, "node_modules/ws": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", - "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", "engines": { "node": ">=8.3.0" }, @@ -1405,6 +1401,14 @@ "engines": { "node": ">=6" } + }, + "node_modules/yargs-parser/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } } }, "dependencies": { @@ -1468,9 +1472,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.26", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.26.tgz", - "integrity": "sha512-zeu3tpouA043RHxW0gzRxwCHchMgftE8GArRsvYT0ByDMbn19olQHx5jLue0LxWY6iYtXb7rXmuVtSkhy9YZvQ==", + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", "requires": { "@types/node": "*", "@types/qs": "*", @@ -1483,9 +1487,9 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "@types/node": { - "version": "16.11.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz", - "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==" + "version": "17.0.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", + "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==" }, "@types/qs": { "version": "6.9.7", @@ -1515,12 +1519,12 @@ } }, "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" } }, "ansi-regex": { @@ -1547,14 +1551,14 @@ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "aws-sdk": { - "version": "2.1043.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1043.0.tgz", - "integrity": "sha512-WysMTSLfi8ZCj6QAAitJkxObxOzGLhcu6FxoKHiEnrefvfQtSvwqUq7BbT/pIfijnF9dE/7e9XwjW8Dz/hqF4Q==", + "version": "2.1087.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1087.0.tgz", + "integrity": "sha512-m5EERT29Fwh2cv3SaSdygeAjJBXnjSaXRRERy70bf6PQ7KgmASJouBxY11g5G7LTEPK/yfB0TGshujKh3hEtPA==", "requires": { "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", - "jmespath": "0.15.0", + "jmespath": "0.16.0", "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", @@ -1573,20 +1577,20 @@ "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", "requires": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "1.7.2", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" } }, "buffer": { @@ -1600,14 +1604,14 @@ } }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" }, "camelcase-keys": { "version": "7.0.2", @@ -1618,13 +1622,6 @@ "map-obj": "^4.1.0", "quick-lru": "^5.1.1", "type-fest": "^1.2.1" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" - } } }, "cliui": { @@ -1656,11 +1653,11 @@ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" } }, "content-type": { @@ -1669,9 +1666,9 @@ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" }, "cookie-signature": { "version": "1.0.6", @@ -1731,9 +1728,9 @@ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "engine.io": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.2.tgz", - "integrity": "sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", + "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", "requires": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -1743,15 +1740,10 @@ "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.0.0", + "engine.io-parser": "~5.0.3", "ws": "~8.2.3" }, "dependencies": { - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - }, "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -1797,16 +1789,16 @@ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" }, "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", + "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", "requires": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.19.2", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.4.2", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", @@ -1820,13 +1812,13 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.9.7", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", "statuses": "~1.5.0", "type-is": "~1.6.18", "utils-merge": "1.0.1", @@ -1877,15 +1869,15 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "toidentifier": "1.0.1" } }, "iconv-lite": { @@ -1902,9 +1894,9 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ip6addr": { "version": "0.2.5", @@ -1931,9 +1923,9 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==" }, "json-schema": { "version": "0.4.0", @@ -2022,9 +2014,9 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "object-assign": { "version": "4.1.1", @@ -2113,9 +2105,9 @@ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" }, "querystring": { "version": "0.2.0", @@ -2133,12 +2125,12 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } @@ -2154,9 +2146,9 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", @@ -2169,9 +2161,9 @@ "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", "requires": { "debug": "2.6.9", "depd": "~1.1.2", @@ -2180,30 +2172,30 @@ "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "1.8.1", "mime": "1.6.0", - "ms": "2.1.1", + "ms": "2.1.3", "on-finished": "~2.3.0", "range-parser": "~1.2.1", "statuses": "~1.5.0" }, "dependencies": { "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.17.2" } }, "set-blocking": { @@ -2212,9 +2204,9 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "socket.io": { "version": "4.4.1", @@ -2308,9 +2300,9 @@ "integrity": "sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==" }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "type-fest": { "version": "1.4.0", @@ -2355,10 +2347,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, - "uWebSockets.js": { - "version": "git+ssh://git@github.com/uNetworking/uWebSockets.js.git#a58e810e47a23696410f6073c8c905dc38f75da5", - "from": "uWebSockets.js@github:uNetworking/uWebSockets.js#v20.6.0" - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -2390,9 +2378,9 @@ } }, "ws": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", - "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", "requires": {} }, "xml2js": { @@ -2439,6 +2427,13 @@ "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + } } } } diff --git a/utilities/package.json b/utilities/package.json index 79c8513a4..452c3fe00 100644 --- a/utilities/package.json +++ b/utilities/package.json @@ -24,7 +24,6 @@ "peer": "^0.6.1", "socket.io": "^4.4.1", "source-map": "^0.7.3", - "ua-parser-js": "^1.0.2", - "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.6.0" + "ua-parser-js": "^1.0.2" } } diff --git a/utilities/servers/peerjs-server.js b/utilities/servers/peerjs-server.js index b139e0104..434e5f4bc 100644 --- a/utilities/servers/peerjs-server.js +++ b/utilities/servers/peerjs-server.js @@ -1,11 +1,16 @@ var express = require('express'); var peerRouter = express.Router(); - +let PROJECT_KEY_LENGTH = parseInt(process.env.PROJECT_KEY_LENGTH) || 20; +let debug = process.env.debug === "1" || false; const extractPeerId = (peerId) => { let splited = peerId.split("-"); if (splited.length !== 2) { - console.error(`cannot split peerId: ${peerId}`); + debug && console.error(`cannot split peerId: ${peerId}`); + return {}; + } + if (PROJECT_KEY_LENGTH > 0 && splited[0].length !== PROJECT_KEY_LENGTH) { + debug && console.error(`wrong project key length for peerId: ${peerId}`); return {}; } return {projectKey: splited[0], sessionId: splited[1]}; @@ -13,30 +18,30 @@ const extractPeerId = (peerId) => { const connectedPeers = {}; const peerConnection = (client) => { - console.log(`initiating ${client.id}`); + debug && console.log(`initiating ${client.id}`); const {projectKey, sessionId} = extractPeerId(client.id); if (projectKey === undefined || sessionId === undefined) { return; } connectedPeers[projectKey] = connectedPeers[projectKey] || []; if (connectedPeers[projectKey].indexOf(sessionId) === -1) { - console.log(`new connexion ${client.id}`); + debug && console.log(`new connexion ${client.id}`); connectedPeers[projectKey].push(sessionId); } else { - console.log(`reconnecting peer ${client.id}`); + debug && console.log(`reconnecting peer ${client.id}`); } }; const peerDisconnect = (client) => { - console.log(`disconnect ${client.id}`); + debug && console.log(`disconnect ${client.id}`); const {projectKey, sessionId} = extractPeerId(client.id); if (projectKey === undefined || sessionId === undefined) { return; } const i = (connectedPeers[projectKey] || []).indexOf(sessionId); if (i === -1) { - console.log(`session not found ${client.id}`); + debug && console.log(`session not found ${client.id}`); } else { connectedPeers[projectKey].splice(i, 1); } @@ -49,13 +54,13 @@ const peerError = (error) => { peerRouter.get(`/${process.env.S3_KEY}/peers`, function (req, res) { - console.log("looking for all available sessions"); + debug && console.log("looking for all available sessions"); res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({"data": connectedPeers})); }); peerRouter.get(`/${process.env.S3_KEY}/peers/:projectKey`, function (req, res) { - console.log(`looking for available sessions for ${req.params.projectKey}`); + debug && console.log(`looking for available sessions for ${req.params.projectKey}`); res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({"data": connectedPeers[req.params.projectKey] || []})); diff --git a/utilities/servers/websocket.js b/utilities/servers/websocket.js index dfce5b4d7..b772228be 100644 --- a/utilities/servers/websocket.js +++ b/utilities/servers/websocket.js @@ -4,6 +4,7 @@ const uaParser = require('ua-parser-js'); const geoip2Reader = require('@maxmind/geoip2-node').Reader; var {extractPeerId} = require('./peerjs-server'); var wsRouter = express.Router(); +const UPDATE_EVENT = "UPDATE_SESSION"; const IDENTITIES = {agent: 'agent', session: 'session'}; const NEW_AGENT = "NEW_AGENT"; const NO_AGENTS = "NO_AGENT"; @@ -15,7 +16,8 @@ const SESSION_ALREADY_CONNECTED = "SESSION_ALREADY_CONNECTED"; let io; let debug = process.env.debug === "1" || false; -wsRouter.get(`/${process.env.S3_KEY}/sockets-list`, function (req, res) { + +const socketsList = function (req, res) { debug && console.log("[WS]looking for all available sessions"); let liveSessions = {}; for (let peerId of io.sockets.adapter.rooms.keys()) { @@ -28,8 +30,10 @@ wsRouter.get(`/${process.env.S3_KEY}/sockets-list`, function (req, res) { res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({"data": liveSessions})); -}); -wsRouter.get(`/${process.env.S3_KEY}/sockets-list/:projectKey`, function (req, res) { +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-list`, socketsList); + +const socketsListByProject = function (req, res) { debug && console.log(`[WS]looking for available sessions for ${req.params.projectKey}`); let liveSessions = {}; for (let peerId of io.sockets.adapter.rooms.keys()) { @@ -42,9 +46,10 @@ wsRouter.get(`/${process.env.S3_KEY}/sockets-list/:projectKey`, function (req, r res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({"data": liveSessions[req.params.projectKey] || []})); -}); +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-list/:projectKey`, socketsListByProject); -wsRouter.get(`/${process.env.S3_KEY}/sockets-live`, async function (req, res) { +const socketsLive = async function (req, res) { debug && console.log("[WS]looking for all available LIVE sessions"); let liveSessions = {}; for (let peerId of io.sockets.adapter.rooms.keys()) { @@ -63,8 +68,10 @@ wsRouter.get(`/${process.env.S3_KEY}/sockets-live`, async function (req, res) { res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({"data": liveSessions})); -}); -wsRouter.get(`/${process.env.S3_KEY}/sockets-live/:projectKey`, async function (req, res) { +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-live`, socketsLive); + +const socketsLiveByProject = async function (req, res) { debug && console.log(`[WS]looking for available LIVE sessions for ${req.params.projectKey}`); let liveSessions = {}; for (let peerId of io.sockets.adapter.rooms.keys()) { @@ -82,7 +89,8 @@ wsRouter.get(`/${process.env.S3_KEY}/sockets-live/:projectKey`, async function ( res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({"data": liveSessions[req.params.projectKey] || []})); -}); +} +wsRouter.get(`/${process.env.S3_KEY}/sockets-live/:projectKey`, socketsLiveByProject); const findSessionSocketId = async (io, peerId) => { const connected_sockets = await io.in(peerId).fetchSockets(); @@ -161,7 +169,7 @@ module.exports = { wsRouter, start: (server) => { io = _io(server, { - maxHttpBufferSize: 5e6, + maxHttpBufferSize: (parseInt(process.env.maxHttpBufferSize) || 5) * 1e6, cors: { origin: "*", methods: ["GET", "POST", "PUT"] @@ -226,6 +234,16 @@ module.exports = { } }); + socket.on(UPDATE_EVENT, async (...args) => { + debug && console.log(`${socket.id} sent update event.`); + if (socket.identity !== IDENTITIES.session) { + debug && console.log('Ignoring update event.'); + return + } + socket.handshake.query.sessionInfo = {...socket.handshake.query.sessionInfo, ...args[0]}; + socket.to(socket.peerId).emit(UPDATE_EVENT, args[0]); + }); + socket.onAny(async (eventName, ...args) => { socket.lastMessageReceivedAt = Date.now(); if (socket.identity === IDENTITIES.session) { @@ -268,5 +286,11 @@ module.exports = { console.error(e); } }, 20000, io); + }, + handlers: { + socketsList, + socketsListByProject, + socketsLive, + socketsLiveByProject } }; \ No newline at end of file diff --git a/utilities/servers/websocket_back.js b/utilities/servers/websocket_back.js index ab6a2c4d5..28d2626a6 100644 --- a/utilities/servers/websocket_back.js +++ b/utilities/servers/websocket_back.js @@ -161,7 +161,7 @@ module.exports = { wsRouter, start: (server) => { io = _io(server, { - maxHttpBufferSize: 1e6, + maxHttpBufferSize: (parseInt(process.env.maxHttpBufferSize) || 1) * 1e6, cors: { origin: "*", methods: ["GET", "POST", "PUT"]