diff --git a/.gitignore b/.gitignore index 7890890..aa3824b 100644 --- a/.gitignore +++ b/.gitignore @@ -111,4 +111,7 @@ git_push.sh # Others lib/ -docs/ \ No newline at end of file +docs/ + +# Test +*.geojson diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a38010e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "bibm"] + path = bibm + url = https://github.com/Cata-Dev/Best-itinerary-Bordeaux-Metropole.git + branch = dev diff --git a/badges/coverage-branches.svg b/badges/coverage-branches.svg index c8d98a2..82bc8c6 100644 --- a/badges/coverage-branches.svg +++ b/badges/coverage-branches.svg @@ -1 +1 @@ -Coverage: branches: 85.95%Coverage: branches85.95% \ No newline at end of file +Coverage: branches: 85.95%Coverage: branches85.95% diff --git a/badges/coverage-functions.svg b/badges/coverage-functions.svg index 66c721c..11a5d0e 100644 --- a/badges/coverage-functions.svg +++ b/badges/coverage-functions.svg @@ -1 +1 @@ -Coverage: functions: 93.84%Coverage: functions93.84% \ No newline at end of file +Coverage: functions: 93.84%Coverage: functions93.84% diff --git a/badges/coverage-lines.svg b/badges/coverage-lines.svg index fa8a6eb..da55e1d 100644 --- a/badges/coverage-lines.svg +++ b/badges/coverage-lines.svg @@ -1 +1 @@ -Coverage: lines: 95.68%Coverage: lines95.68% \ No newline at end of file +Coverage: lines: 95.68%Coverage: lines95.68% diff --git a/badges/coverage-statements.svg b/badges/coverage-statements.svg index 4d9345e..876a92e 100644 --- a/badges/coverage-statements.svg +++ b/badges/coverage-statements.svg @@ -1 +1 @@ -Coverage: statements: 94.54%Coverage: statements94.54% \ No newline at end of file +Coverage: statements: 94.54%Coverage: statements94.54% diff --git a/badges/coverage-total.svg b/badges/coverage-total.svg index cb54e8b..a01c7cc 100644 --- a/badges/coverage-total.svg +++ b/badges/coverage-total.svg @@ -1 +1 @@ -Coverage: total: 92.5%Coverage: total92.5% \ No newline at end of file +Coverage: total: 92.5%Coverage: total92.5% diff --git a/bench/.gitignore b/bench/.gitignore new file mode 100644 index 0000000..a53dce0 --- /dev/null +++ b/bench/.gitignore @@ -0,0 +1,2 @@ +/results/ +*.html \ No newline at end of file diff --git a/bench/analyze.ipynb b/bench/analyze.ipynb new file mode 100644 index 0000000..9faded7 --- /dev/null +++ b/bench/analyze.ipynb @@ -0,0 +1,607 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7eb589b8", + "metadata": {}, + "source": [ + "# Import data & parse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2c179db", + "metadata": {}, + "outputs": [], + "source": [ + "from os import listdir\n", + "from os.path import join, isdir, isfile\n", + "import re\n", + "import traceback\n", + "from typing import TypedDict\n", + "import json\n", + "\n", + "DATA_PREFIX = \"Using data type \"\n", + "DELAY_PREFIX = \"Using delay of \"\n", + "SHARED_SECURE_PREFIX = \"Shared secure \"\n", + "INSTANCE_PREFIX = \"Using instance type \"\n", + "CRITERIA_PREFIX = \"Using criteria \"\n", + "FP_QUERY_MAX_LEN_PREFIX = \"Foot paths query max len \"\n", + "FP_RUN_MAX_LEN_PREFIX = \"Foot paths run max len \"\n", + "BENCHMARK_PREFIX = \"Benchmark of \"\n", + "SCANNED_FP_PREFIX = \"scanned fp cnt \"\n", + "MARKED_TR_PREFIX = \"marked size traverse route \"\n", + "MARKED_FP_PREFIX = \"marked size fp lookup \"\n", + "F_ROUTE_BAG_SZ_PREFIX = \"final route bag sz=\"\n", + "FP_BAG_SZ_PREFIX = \"fp b sz \"\n", + "\n", + "UNKNOWN_LITERAL = \"Unknown\"\n", + "\n", + "\n", + "def parse_bench_time(bench_time: str) -> int:\n", + " \"\"\"00:00:093.9852490000003\"\"\"\n", + " total_ms = 0\n", + "\n", + " for i, part in enumerate(bench_time.split(\":\")):\n", + " total_ms += round(float(part)) * (\n", + " 60 * 1_000 if i == 0 else 1_000 if i == 1 else 1\n", + " )\n", + "\n", + " return total_ms\n", + "\n", + "\n", + "class Result(TypedDict):\n", + " data: str\n", + " delay: tuple[int, int] | None\n", + " instance: str\n", + " shared_secure: bool | None\n", + " criteria: list[str]\n", + " fp_query_max_len: int\n", + " fp_run_max_len: int\n", + "\n", + " # Benchmarks\n", + " compute_data: tuple[int, int]\n", + " create_instance: tuple[int, int]\n", + " run: tuple[int, int]\n", + " # {round, {step, [begin, end]}}\n", + " run_steps: dict[int, dict[str, tuple[float, float]]]\n", + " result: tuple[int, int]\n", + " post_treatment: tuple[int, int]\n", + "\n", + " # Run stats\n", + " scanned_fp: dict[int, list[int]]\n", + " marked_tr: dict[int, list[int]]\n", + " marked_fp: dict[int, list[int]]\n", + " # MC-specific\n", + " f_route_bag_sz: dict[int, list[int]] | None\n", + " fp_bag_sz: dict[int, list[int]] | None\n", + "\n", + "\n", + "results: dict[str, Result] = {}\n", + "\n", + "RESULTS_FOLDER = \"./results\"\n", + "\n", + "for node in listdir(RESULTS_FOLDER):\n", + " node_path = join(RESULTS_FOLDER, node)\n", + " if isdir(node_path):\n", + " for file in listdir(node_path):\n", + " file_path = join(node_path, file)\n", + " if file == \"out.txt\" and isfile(file_path):\n", + " print(f\"Loading {file_path} ...\", end=\" \")\n", + " try:\n", + " with open(file_path) as raw_output:\n", + " result = Result(\n", + " data=UNKNOWN_LITERAL,\n", + " delay=None,\n", + " instance=UNKNOWN_LITERAL,\n", + " shared_secure=None,\n", + " criteria=[UNKNOWN_LITERAL],\n", + " fp_query_max_len=-1,\n", + " fp_run_max_len=-1,\n", + " compute_data=(0, -1),\n", + " create_instance=(0, -1),\n", + " run=(0, -1),\n", + " run_steps={},\n", + " result=(0, -1),\n", + " post_treatment=(0, -1),\n", + " scanned_fp={},\n", + " marked_tr={},\n", + " marked_fp={},\n", + " f_route_bag_sz=None,\n", + " fp_bag_sz=None,\n", + " )\n", + "\n", + " k = 0\n", + "\n", + " for line in raw_output:\n", + " line = line[:-1]\n", + "\n", + " if line.startswith(DATA_PREFIX):\n", + " result[\"data\"] = line[len(DATA_PREFIX) :]\n", + " elif line.startswith(DELAY_PREFIX):\n", + " neg, pos = line[len(DELAY_PREFIX) : -1].split(\"s, \")\n", + " result[\"delay\"] = (int(neg), int(pos))\n", + " elif line.startswith(INSTANCE_PREFIX):\n", + " result[\"instance\"] = line[len(INSTANCE_PREFIX) :]\n", + " elif line.startswith(SHARED_SECURE_PREFIX):\n", + " result[\"shared_secure\"] = json.loads(\n", + " line[len(SHARED_SECURE_PREFIX) :]\n", + " )\n", + " elif line.startswith(CRITERIA_PREFIX):\n", + " result[\"criteria\"] = json.loads(\n", + " line[len(CRITERIA_PREFIX) :].replace(\"'\", '\"')\n", + " )\n", + " elif line.startswith(FP_QUERY_MAX_LEN_PREFIX):\n", + " result[\"fp_query_max_len\"] = json.loads(\n", + " line[len(FP_QUERY_MAX_LEN_PREFIX) :]\n", + " )\n", + " elif line.startswith(FP_RUN_MAX_LEN_PREFIX):\n", + " result[\"fp_run_max_len\"] = json.loads(\n", + " line[len(FP_RUN_MAX_LEN_PREFIX) :]\n", + " )\n", + "\n", + " elif line.startswith(BENCHMARK_PREFIX):\n", + " # Benchmarks\n", + " line = line[len(BENCHMARK_PREFIX) :]\n", + "\n", + " fun_name = line.split(\" \")[0]\n", + " line = line[len(fun_name + \" (\") :]\n", + "\n", + " times = int(line.split(\" \")[0])\n", + " line = line[len(str(times) + \" times): \") :]\n", + "\n", + " duration = parse_bench_time(line)\n", + "\n", + " if fun_name.startswith(\"compute\"):\n", + " result[\"compute_data\"] = (times, duration)\n", + " elif fun_name.startswith(\"create\"):\n", + " result[\"create_instance\"] = (times, duration)\n", + " elif fun_name.startswith(\"run\"):\n", + " result[\"run\"] = (times, duration)\n", + " elif fun_name.startswith(\"result\"):\n", + " result[\"result\"] = (times, duration)\n", + " elif fun_name.startswith(\"postTreatment\"):\n", + " result[\"post_treatment\"] = (times, duration)\n", + "\n", + " elif (\n", + " matches := re.search(\n", + " r\"^\\[(?P\\d+.\\d+)\\] (?Pbegin|end) (?P.+)$\",\n", + " line,\n", + " )\n", + " ) is not None:\n", + " step_name, step_kind, step_time = matches.group(\n", + " \"step_name\", \"step_kind\", \"step_time\"\n", + " )\n", + "\n", + " if step_name.startswith(\"round \"):\n", + " k = int(step_name[len(\"round \") :])\n", + "\n", + " run_steps_k = result[\"run_steps\"].setdefault(k, {})\n", + " (begin, end) = run_steps_k.setdefault(step_name, (0, 0))\n", + "\n", + " run_steps_k[step_name] = (\n", + " (begin + float(step_time), end)\n", + " if step_kind == \"begin\"\n", + " else (\n", + " begin,\n", + " end + float(step_time),\n", + " )\n", + " )\n", + "\n", + " if step_name == \"end\":\n", + " k = 0\n", + "\n", + " elif (\n", + " matches := re.search(\n", + " r\"^\\[(?P\\d+.\\d+)\\] (?P.+)$\",\n", + " line,\n", + " )\n", + " ) is not None:\n", + " line = matches.group(\"msg\")\n", + "\n", + " if line.startswith(SCANNED_FP_PREFIX):\n", + " result[\"scanned_fp\"].setdefault(k, []).append(\n", + " int(line[len(SCANNED_FP_PREFIX) :])\n", + " )\n", + " elif line.startswith(MARKED_TR_PREFIX):\n", + " result[\"marked_tr\"].setdefault(k, []).append(\n", + " int(line[len(MARKED_TR_PREFIX) :])\n", + " )\n", + " elif line.startswith(MARKED_FP_PREFIX):\n", + " result[\"marked_fp\"].setdefault(k, []).append(\n", + " int(line[len(MARKED_FP_PREFIX) :])\n", + " )\n", + " elif line.startswith(F_ROUTE_BAG_SZ_PREFIX):\n", + " if result[\"f_route_bag_sz\"] is None:\n", + " result[\"f_route_bag_sz\"] = {}\n", + " result[\"f_route_bag_sz\"].setdefault(k, []).append(\n", + " int(line[len(F_ROUTE_BAG_SZ_PREFIX) :])\n", + " )\n", + " elif line.startswith(FP_BAG_SZ_PREFIX):\n", + " if result[\"fp_bag_sz\"] is None:\n", + " result[\"fp_bag_sz\"] = {}\n", + " result[\"fp_bag_sz\"].setdefault(k, []).append(\n", + " int(line[len(FP_BAG_SZ_PREFIX) :])\n", + " )\n", + "\n", + " run_times = result[\"run\"][0]\n", + " for k, run_steps_k in result[\"run_steps\"].items():\n", + " for step_name, (begin, end) in run_steps_k.items():\n", + " run_steps_k[step_name] = (\n", + " begin / run_times,\n", + " end / run_times,\n", + " )\n", + "\n", + " results[node] = result\n", + " print(\"Done.\")\n", + " except Exception as exc:\n", + " print(\"Error: \\n\", \"\\n\".join(traceback.format_exception(exc)))\n", + "\n", + "# results" + ] + }, + { + "cell_type": "markdown", + "id": "bfb38243", + "metadata": {}, + "source": [ + "# Format data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1a4ee960", + "metadata": {}, + "outputs": [], + "source": [ + "from functools import reduce\n", + "\n", + "results_list = sorted(results.items(), key=lambda result: result[0])\n", + "\n", + "# {k: [result_idx, begin, end][]}\n", + "run_steps_round: dict[int, list[tuple[int, float, float]]] = {}\n", + "# {step_name: [k, result_idx, begin, end][]}\n", + "run_steps: dict[str, list[tuple[int, int, float, float]]] = {}\n", + "\n", + "for i, (_, result) in enumerate(results_list):\n", + " for k, run_steps_k in result[\"run_steps\"].items():\n", + " for step_name, (begin, end) in run_steps_k.items():\n", + " is_round = re.match(r\"round \\d+\", step_name) is not None\n", + "\n", + " if is_round:\n", + " run_steps_round.setdefault(k, []).append((i, begin, end))\n", + " else:\n", + " run_steps.setdefault(step_name, []).append((k, i, begin, end))\n", + "\n", + "\n", + "def dict_append_by_key[K, T](d: dict[K, list[T]], k: K, el: T) -> dict[K, list[T]]:\n", + " d.setdefault(k, []).append(el)\n", + " return d\n", + "\n", + "\n", + "results_by_data: dict[str, list[tuple[str, Result]]] = reduce(\n", + " lambda acc, v: dict_append_by_key(acc, v[1][\"data\"], v), results_list, {}\n", + ")\n", + "results_by_instance: dict[str, list[tuple[str, Result]]] = reduce(\n", + " lambda acc, v: dict_append_by_key(acc, v[1][\"instance\"], v), results_list, {}\n", + ")\n", + "results_by_data_instance: dict[str, list[tuple[str, Result]]] = reduce(\n", + " lambda acc, v: dict_append_by_key(acc, f\"{v[1][\"data\"]}-{v[1][\"instance\"]}\", v),\n", + " results_list,\n", + " {},\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "64a48ea5", + "metadata": {}, + "source": [ + "# Plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2469a8f6", + "metadata": {}, + "outputs": [], + "source": [ + "from math import floor\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.patches import Patch\n", + "from matplotlib.ticker import AutoMinorLocator\n", + "import numpy as np\n", + "\n", + "\n", + "def format_ms(ms: float):\n", + " return f\"{floor(ms / 1000)}:{ms % 1000}\"" + ] + }, + { + "cell_type": "markdown", + "id": "1cb781ac", + "metadata": {}, + "source": [ + "# Plot pre-running" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e0bb862", + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(figsize=(len(results_by_data_instance) + 2, 7))\n", + "\n", + "results_by_data_instance_list = list(results_by_data_instance.items())\n", + "\n", + "ax_plt = ax.plot(\n", + " [\n", + " sum(map(lambda result: result[1][\"compute_data\"][1], results)) / len(results)\n", + " for (_, results) in results_by_data_instance_list\n", + " ],\n", + " \"o--\",\n", + " color=\"black\",\n", + " label=\"Compute data\",\n", + ")\n", + "_ = ax.tick_params(axis=\"y\", labelcolor=ax_plt[0].get_color())\n", + "_ = ax.set_xticks(\n", + " range(len(results_by_data_instance_list)),\n", + " [data_instance for (data_instance, _) in results_by_data_instance_list],\n", + " rotation=45,\n", + " ha=\"right\",\n", + ")\n", + "ax.yaxis.set_major_formatter(lambda x, _: format_ms(x))\n", + "ax.yaxis.set_minor_locator(AutoMinorLocator())\n", + "_ = ax.set_ylabel(\"Duration (s:ms)\")\n", + "_ = ax.set_xlabel(\"Data-instance\")\n", + "\n", + "ax2 = ax.twinx()\n", + "ax2_plt = ax2.plot(\n", + " [\n", + " sum(map(lambda result: result[1][\"create_instance\"][1], results)) / len(results)\n", + " for (_, results) in results_by_data_instance_list\n", + " ],\n", + " \"x:\",\n", + " ms=5,\n", + " color=\"green\",\n", + " label=\"Create instance\",\n", + ")\n", + "_ = ax2.tick_params(axis=\"y\", labelcolor=ax2_plt[0].get_color())\n", + "ax2.yaxis.set_major_formatter(lambda x, _: format_ms(x))\n", + "_ = ax2.set_ylabel(\"Duration (s:ms)\")\n", + "\n", + "leg = fig.legend(\n", + " # loc=\"upper right\",\n", + " # # https://stackoverflow.com/a/47370214\n", + " # bbox_to_anchor=(1, 1),\n", + " # bbox_transform=ax.transAxes,\n", + ")\n", + "# Move titles to the left from https://stackoverflow.com/a/68261686\n", + "\n", + "_ = ax.set_title(\n", + " f\"Benchmarks of pre-running RAPTOR (fp_query_len={results_list[0][1][\"fp_query_max_len\"]},fp_run_len={results_list[0][1][\"fp_run_max_len\"]})\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "01d3903c", + "metadata": {}, + "source": [ + "# Plot running" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "01778364", + "metadata": {}, + "outputs": [], + "source": [ + "FIG_WIDTH=len(results) + 2\n", + "\n", + "fig, ax = plt.subplots(figsize=(FIG_WIDTH, 7))\n", + "\n", + "color_rounds = plt.get_cmap(\"magma\")(\n", + " np.linspace(\n", + " 0,\n", + " 1,\n", + " max([k for _, result in results_list for k, _ in result[\"run_steps\"].items()])\n", + " + 1,\n", + " )\n", + ")\n", + "step_names_to_idx = {step_name: i for i, step_name in enumerate(run_steps)}\n", + "color_steps = plt.get_cmap(\"viridis\")(\n", + " np.linspace(\n", + " 0,\n", + " 1,\n", + " len(step_names_to_idx),\n", + " )\n", + ")\n", + "line_rounds = []\n", + "for k, steps in run_steps_round.items():\n", + " line_rounds.append(\n", + " ax.vlines(\n", + " [i - 0.03 for i, _, _ in steps],\n", + " [begin for _, begin, _ in steps],\n", + " [end for _, _, end in steps],\n", + " colors=(color_rounds[k]),\n", + " linewidths=4,\n", + " label=str(k),\n", + " )\n", + " )\n", + "line_steps = []\n", + "for step_name, steps in run_steps.items():\n", + " line_steps.append(\n", + " ax.vlines(\n", + " [i + 0.03 for _, i, _, _ in steps],\n", + " [begin for _, _, begin, _ in steps],\n", + " [end for _, _, _, end in steps],\n", + " colors=(color_steps[step_names_to_idx[step_name]]),\n", + " linewidths=4,\n", + " label=step_name,\n", + " )\n", + " )\n", + "plt_run_dura = ax.plot(\n", + " [result[\"run\"][1] for (_, result) in results_list],\n", + " \"o--\",\n", + " color=\"black\",\n", + " label=\"run duration mean\",\n", + ")\n", + "_ = ax.set_xticks(\n", + " range(len(results_list)),\n", + " [result_name for (result_name, _) in results_list],\n", + " rotation=45,\n", + " ha=\"right\",\n", + ")\n", + "_ = ax.tick_params(axis=\"y\", labelcolor=plt_run_dura[0].get_color())\n", + "ax.yaxis.set_major_formatter(lambda x, _: format_ms(x))\n", + "ax.yaxis.set_minor_locator(AutoMinorLocator())\n", + "_ = ax.set_ylabel(\"Duration (s:ms)\")\n", + "_ = ax.set_xlabel(\"Benchmark name\")\n", + "\n", + "ax2 = ax.twinx()\n", + "plt_run_times = ax2.plot(\n", + " [result[\"run\"][0] for (_, result) in results_list],\n", + " \"x:\",\n", + " ms=5,\n", + " color=\"green\",\n", + " label=\"#run\",\n", + ")\n", + "_ = ax2.tick_params(axis=\"y\", labelcolor=plt_run_times[0].get_color())\n", + "_ = ax2.set_ylabel(\"#run\")\n", + "\n", + "leg = fig.legend(\n", + " handles=[\n", + " *plt_run_dura,\n", + " *plt_run_times,\n", + " Patch(visible=False, label=\"\\n$\\\\bf{Rounds}$\"),\n", + " *line_rounds,\n", + " Patch(visible=False, label=\"\\n$\\\\bf{Steps}$\"),\n", + " *line_steps,\n", + " ],\n", + " # loc=\"upper right\",\n", + " # # https://stackoverflow.com/a/47370214\n", + " # bbox_to_anchor=(1, 1),\n", + " # bbox_transform=ax.transAxes,\n", + ")\n", + "# Move titles to the left from https://stackoverflow.com/a/68261686\n", + "for handle, label in zip(leg.legend_handles, leg.texts):\n", + " if handle is not None and not handle.get_visible():\n", + " width = handle.get_window_extent().width\n", + " label.set_horizontalalignment(\"left\")\n", + " label.set_position((-2 * width, 0))\n", + "\n", + "_ = ax.set_title(\n", + " f\"Benchmarks of running RAPTOR (fp_len={results_list[0][1][\"fp_run_max_len\"]})\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "66580a30", + "metadata": {}, + "source": [ + "# Plot metrics" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b42abf33", + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Literal\n", + "from matplotlib.axes import Axes\n", + "\n", + "k_cnt = max(map(lambda result: len(result[\"run_steps\"]), results.values())) - 1\n", + "\n", + "metrics: list[\n", + " Literal[\"scanned_fp\"]\n", + " | Literal[\"marked_tr\"]\n", + " | Literal[\"marked_fp\"]\n", + " | Literal[\"f_route_bag_sz\"]\n", + " | Literal[\"fp_bag_sz\"]\n", + "] = [\n", + " \"scanned_fp\",\n", + " \"marked_tr\",\n", + " \"marked_fp\",\n", + " \"f_route_bag_sz\",\n", + " \"fp_bag_sz\",\n", + "]\n", + "\n", + "for metric in metrics:\n", + " fig = plt.figure(\n", + " layout=\"constrained\",\n", + " figsize=(\n", + " FIG_WIDTH,\n", + " 6 * k_cnt,\n", + " ),\n", + " )\n", + " _ = fig.suptitle(f\"{metric}\")\n", + "\n", + " axs: list[Axes] = fig.subplots(k_cnt, 1, sharex=True)\n", + "\n", + " for k, ax in enumerate(axs):\n", + " pos_data: list[tuple[int, list[int]]] = list(\n", + " filter(\n", + " lambda p_d: p_d[1] is not None,\n", + " [\n", + " (\n", + " i + 1,\n", + " (\n", + " result[metric][k + 1]\n", + " if k + 1 in (result[metric] or {})\n", + " else None\n", + " ),\n", + " )\n", + " for i, (_, result) in enumerate(results_list)\n", + " ],\n", + " )\n", + " )\n", + " _ = ax.violinplot(\n", + " [data for _, data in pos_data],\n", + " [pos for pos, _ in pos_data],\n", + " showmeans=True,\n", + " )\n", + " _ = ax.set_xticks(\n", + " range(1, len(results_list) + 1),\n", + " [result_name for (result_name, _) in results_list],\n", + " rotation=45,\n", + " ha=\"right\",\n", + " )\n", + " _ = ax.set_title(f\"Round {k+1}\")\n", + " # Thousand separator, from https://stackoverflow.com/questions/16670125/python-format-string-thousand-separator-with-spaces\n", + " ax.yaxis.set_major_formatter(lambda x, _: \"{:,}\".format(x))\n", + " _ = ax.yaxis.set_minor_locator(AutoMinorLocator())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/bench/bench.sh b/bench/bench.sh new file mode 100755 index 0000000..382796f --- /dev/null +++ b/bench/bench.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +RESULTS_FOLDER="$(dirname "$(realpath "$0")")/results" + +TIMES=1 +while getopts 'gct:d:' ARG; do + case $ARG in + g) + GLOBAL=true + ;; + c) + # Criteria + CRITERIA=true + ;; + t) + TIMES="$OPTARG" + echo "$TIMES" | grep -E '^[0-9]+$' >/dev/null || { + echo "Invalid times to run: $TIMES" + exit 1 + } + ;; + d) + echo "$OPTARG" | grep -E '^[0-9]+$' >/dev/null || { + echo "Invalid run transfer max len: $OPTARG" + exit 1 + } + FOOT_DISTANCE="--fp-run-len $OPTARG" + ;; + *) + echo "Options are: -g (global) -c (criteria) -t (times to run)" + exit 1 + ;; + esac +done + +shift $((OPTIND - 1)) + +echo "Running $TIMES time(s)" + +pnpm run build +mkdir "$RESULTS_FOLDER" 2>/dev/null || true + +if [ -n "$GLOBAL" ]; then + for DTYPE in \ + 'scal' \ + 'int'; do + for INSTANCE in \ + 'r' \ + 'sr' \ + 'mcr' \ + 'mcsr'; do + FOLDER="$RESULTS_FOLDER/$DTYPE-$INSTANCE" + mkdir "$FOLDER" 2>/dev/null || true + echo "Bench data type $DTYPE with instance $INSTANCE" + pnpm exec 0x -D "$FOLDER" lib/test/index.js -d "$DTYPE" -i "$INSTANCE" "$FOOT_DISTANCE" --runTimes "$TIMES" 1>"$FOLDER/out.txt" 2>"$FOLDER/err.txt" + sed -i "s|$(dirname "$PWD")/||g" "$FOLDER/flamegraph.html" + echo "Done at: $FOLDER/flamegraph.html" + done + done +fi + +if [ -n "$CRITERIA" ]; then + # Multi-criteria specific + for DTYPE in \ + 'scal' \ + 'int'; do + for INSTANCE in \ + 'mcr' \ + 'mcsr'; do + for CRITERIA in \ + '--fd' \ + '--bt' \ + '--spi' \ + '--bt --spi'; do + # '--fd --bt' # Might be very long... + for DELAY in \ + '--delay-pos=1 --delay-neg=0' \ + '--delay-pos=2 --delay-neg=1' \ + '--delay-pos=3 --delay-neg=2'; do + FOLDER="$RESULTS_FOLDER/$DTYPE-$INSTANCE$(echo "$CRITERIA" | sed 's/ //g')$(echo "$DELAY" | sed -E 's/( ?--delay|=)//g')" + mkdir "$FOLDER" 2>/dev/null || true + echo "Bench data type $DTYPE with instance $INSTANCE, criteria $CRITERIA and delays $DELAY" + # shellcheck disable=SC2086 + pnpm exec 0x -D "$FOLDER" lib/test/index.js -d "$DTYPE" -i "$INSTANCE" "$FOOT_DISTANCE" $CRITERIA $DELAY --runTimes "$TIMES" 1>"$FOLDER/out.txt" 2>"$FOLDER/err.txt" + sed -i "s|$(dirname "$PWD")/||g" "$FOLDER/flamegraph.html" + echo "Done at: $FOLDER/flamegraph.html" + done + done + done + done +fi + +# flamegraph UI doc https://github.com/davidmarkclements/0x/blob/master/docs/ui.md diff --git a/bibm b/bibm new file mode 160000 index 0000000..6f8247e --- /dev/null +++ b/bibm @@ -0,0 +1 @@ +Subproject commit 6f8247e17aaac6ca6cfc5826ee182933afeccbdf diff --git a/jest.config.js b/jest.config.js index 134cee4..28219a0 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,6 +5,7 @@ const tsJestTransformCfg = createDefaultPreset().transform; /** @type {import("jest").Config} **/ module.exports = { collectCoverageFrom: ["src/**/*.ts"], + coveragePathIgnorePatterns: ["src/test/"], coverageReporters: ["text", "lcov", "json-summary"], // Using https://jestjs.io/docs/configuration#rootdir-string testMatch: ["/test/**/*.test.ts"], diff --git a/package.json b/package.json index d68b60e..c35e964 100644 --- a/package.json +++ b/package.json @@ -25,10 +25,23 @@ }, "author": "Catatomik", "license": "MIT", + "dependencies": { + "@bibm/common": "link:bibm/Common", + "@bibm/compute": "link:bibm/Compute", + "@bibm/data": "link:bibm/Data", + "@catatomik/dijkstra": "github:catatomik/dijkstra", + "@typegoose/typegoose": "^12.19.0", + "core-js": "^3.44.0", + "minimist": "^1.2.8", + "mongodb": "^6.19.0", + "mongoose": "^8.18.0" + }, "devDependencies": { + "0x": "^6.0.0", "@eslint/js": "^9.35.0", "@jest/globals": "^30.1.2", "@tsconfig/node22": "^22.0.2", + "@types/minimist": "^1.2.5", "@types/node": "^22", "eslint": "^9.35.0", "globals": "^16.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fdd0157..3c5a66f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,7 +7,38 @@ settings: importers: .: + dependencies: + '@bibm/common': + specifier: link:bibm/Common + version: link:bibm/Common + '@bibm/compute': + specifier: link:bibm/Compute + version: link:bibm/Compute + '@bibm/data': + specifier: link:bibm/Data + version: link:bibm/Data + '@catatomik/dijkstra': + specifier: github:catatomik/dijkstra + version: https://codeload.github.com/catatomik/dijkstra/tar.gz/e3304b71e4bda9aefb04d2d18b32e7aa369a4aed + '@typegoose/typegoose': + specifier: ^12.19.0 + version: 12.19.0(mongoose@8.18.0) + core-js: + specifier: ^3.44.0 + version: 3.45.1 + minimist: + specifier: ^1.2.8 + version: 1.2.8 + mongodb: + specifier: ^6.19.0 + version: 6.19.0 + mongoose: + specifier: ^8.18.0 + version: 8.18.0 devDependencies: + 0x: + specifier: ^6.0.0 + version: 6.0.0 '@eslint/js': specifier: ^9.35.0 version: 9.35.0 @@ -17,9 +48,12 @@ importers: '@tsconfig/node22': specifier: ^22.0.2 version: 22.0.2 + '@types/minimist': + specifier: ^1.2.5 + version: 1.2.5 '@types/node': specifier: ^22 - version: 22.15.32 + version: 22.18.1 eslint: specifier: ^9.35.0 version: 9.35.0 @@ -28,13 +62,13 @@ importers: version: 16.3.0 jest: specifier: ^30.1.3 - version: 30.1.3(@types/node@22.15.32) + version: 30.1.3(@types/node@22.18.1) prettier: specifier: ^3.6.2 version: 3.6.2 ts-jest: specifier: ^29.4.1 - version: 29.4.1(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.0.5)(babel-jest@30.1.2(@babel/core@7.28.4))(jest-util@30.0.5)(jest@30.1.3(@types/node@22.15.32))(typescript@5.9.2) + version: 29.4.1(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.0.5)(babel-jest@30.1.2(@babel/core@7.28.4))(jest-util@30.0.5)(jest@30.1.3(@types/node@22.18.1))(typescript@5.9.2) typedoc: specifier: ^0.28.12 version: 0.28.12(typescript@5.9.2) @@ -47,6 +81,11 @@ importers: packages: + 0x@6.0.0: + resolution: {integrity: sha512-4JrGHSPTaoEL3MZiKYH5BlNv67X2F48FmR3dKJZOoR/Z1CLVtVOwUb/n4PMf7B+sP9RPz+X50EbIFuwtfYguRQ==} + engines: {node: '>=8.5.0'} + hasBin: true + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -212,6 +251,10 @@ packages: '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@catatomik/dijkstra@https://codeload.github.com/catatomik/dijkstra/tar.gz/e3304b71e4bda9aefb04d2d18b32e7aa369a4aed': + resolution: {tarball: https://codeload.github.com/catatomik/dijkstra/tar.gz/e3304b71e4bda9aefb04d2d18b32e7aa369a4aed} + version: 1.0.0 + '@emnapi/core@1.5.0': resolution: {integrity: sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==} @@ -259,8 +302,8 @@ packages: resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@gerrit0/mini-shiki@3.12.0': - resolution: {integrity: sha512-CF1vkfe2ViPtmoFEvtUWilEc4dOCiFzV8+J7/vEISSsslKQ97FjeTPNMCqUhZEiKySmKRgK3UO/CxtkyOp7DvA==} + '@gerrit0/mini-shiki@3.12.2': + resolution: {integrity: sha512-HKZPmO8OSSAAo20H2B3xgJdxZaLTwtlMwxg0967scnrDlPwe6j5+ULGHyIqwgTbFCn9yv/ff8CmfWZLE9YKBzA==} '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} @@ -388,6 +431,9 @@ packages: '@jridgewell/trace-mapping@0.3.30': resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==} + '@mongodb-js/saslprep@1.3.0': + resolution: {integrity: sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==} + '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} @@ -411,17 +457,17 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@shikijs/engine-oniguruma@3.12.1': - resolution: {integrity: sha512-hbYq+XOc55CU7Irkhsgwh8WgQbx2W5IVzHV4l+wZ874olMLSNg5o3F73vo9m4SAhimFyqq/86xnx9h+T30HhhQ==} + '@shikijs/engine-oniguruma@3.12.2': + resolution: {integrity: sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w==} - '@shikijs/langs@3.12.1': - resolution: {integrity: sha512-Y1MbMfVO5baRz7Boo7EoD36TmzfUx/I5n8e+wZumx6SlUA81Zj1ZwNJL871iIuSHrdsheV4AxJtHQ9mlooklmg==} + '@shikijs/langs@3.12.2': + resolution: {integrity: sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww==} - '@shikijs/themes@3.12.1': - resolution: {integrity: sha512-9JrAm9cA5hqM/YXymA3oAAZdnCgQf1zyrNDtsnM105nNEoEpux4dyzdoOjc2KawEKj1iUs/WH2ota6Atp7GYkQ==} + '@shikijs/themes@3.12.2': + resolution: {integrity: sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A==} - '@shikijs/types@3.12.1': - resolution: {integrity: sha512-Is/p+1vTss22LIsGCJTmGrxu7ZC1iBL9doJFYLaZ4aI8d0VDXb7Mn0kBzhkc7pdsRpmUbQLQ5HXwNpa3H6F8og==} + '@shikijs/types@3.12.2': + resolution: {integrity: sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q==} '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} @@ -441,6 +487,12 @@ packages: '@tybys/wasm-util@0.10.0': resolution: {integrity: sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==} + '@typegoose/typegoose@12.19.0': + resolution: {integrity: sha512-rsHMd3M6Rj6YYw6ecZU6YtXjiBzCqO3zJtgrrVCau1bEp6na8sbMcqRy8kNbTRyA2QCBAGEvM7nXTM8hdxeEiQ==} + engines: {node: '>=16.20.1'} + peerDependencies: + mongoose: ~8.18.0 + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -471,8 +523,11 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@22.15.32': - resolution: {integrity: sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==} + '@types/minimist@1.2.5': + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + + '@types/node@22.18.1': + resolution: {integrity: sha512-rzSDyhn4cYznVG+PCzGe1lwuMYJrcBS1fc3JqSa2PvtABwWo+dZ1ij5OVok3tqfpEBCBoaR4d7upFJk73HRJDw==} '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} @@ -480,6 +535,12 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + '@types/webidl-conversions@7.0.3': + resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} + + '@types/whatwg-url@11.0.5': + resolution: {integrity: sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==} + '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} @@ -545,6 +606,9 @@ packages: resolution: {integrity: sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@tyriar/fibonacci-heap@2.0.9': + resolution: {integrity: sha512-bYuSNomfn4hu2tPiDN+JZtnzCpSpbJ/PNeulmocDy3xN2X5OkJL65zo6rPZp65cPPhLF9vfT/dgE+RtFRCSxOA==} + '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} @@ -643,11 +707,27 @@ packages: cpu: [x64] os: [win32] + JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-node@1.8.2: + resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==} + + acorn-walk@7.2.0: + resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} + engines: {node: '>=0.4.0'} + + acorn@7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + acorn@8.15.0: resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} @@ -656,10 +736,17 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} + ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -668,6 +755,10 @@ packages: resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} + ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -690,6 +781,16 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + asn1.js@4.10.1: + resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} + + assert@1.5.1: + resolution: {integrity: sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A==} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + babel-jest@30.1.2: resolution: {integrity: sha512-IQCus1rt9kaSh7PQxLYRY5NmkNrNlU2TpabzwV7T2jljnpdHOcmnYYv8QmE04Li4S3a2Lj8/yXyET5pBarPr6g==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -718,6 +819,15 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bn.js@4.12.2: + resolution: {integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==} + + bn.js@5.2.2: + resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -728,6 +838,44 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + + browser-pack@6.1.0: + resolution: {integrity: sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==} + hasBin: true + + browser-process-hrtime@0.1.3: + resolution: {integrity: sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==} + + browser-resolve@2.0.0: + resolution: {integrity: sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==} + + browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + + browserify-cipher@1.0.1: + resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} + + browserify-des@1.0.2: + resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} + + browserify-rsa@4.1.1: + resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} + engines: {node: '>= 0.10'} + + browserify-sign@4.2.3: + resolution: {integrity: sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==} + engines: {node: '>= 0.12'} + + browserify-zlib@0.2.0: + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} + + browserify@17.0.1: + resolution: {integrity: sha512-pxhT00W3ylMhCHwG5yfqtZjNnFuX5h2IJdaBfSo4ChaaBsIp9VLrEMQ1bHV+Xr1uLPXuNDDM1GlJkjli0qkRsw==} + engines: {node: '>= 0.8'} + hasBin: true + browserslist@4.25.4: resolution: {integrity: sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -740,13 +888,44 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + bson@6.10.4: + resolution: {integrity: sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==} + engines: {node: '>=16.20.1'} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + + buffer@5.2.1: + resolution: {integrity: sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==} + + builtin-status-codes@3.0.0: + resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} + + cached-path-relative@1.1.0: + resolution: {integrity: sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + camel-case@3.0.0: + resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} + camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -758,6 +937,10 @@ packages: caniuse-lite@1.0.30001741: resolution: {integrity: sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==} + chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -770,6 +953,10 @@ packages: resolution: {integrity: sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==} engines: {node: '>=8'} + cipher-base@1.0.6: + resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} + engines: {node: '>= 0.10'} + cjs-module-lexer@2.1.0: resolution: {integrity: sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==} @@ -781,6 +968,10 @@ packages: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + code-point-at@1.1.0: + resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} + engines: {node: '>=0.10.0'} + collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} @@ -791,16 +982,121 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + combine-source-map@0.8.0: + resolution: {integrity: sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg==} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + concat-stream@1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + + concat-stream@2.0.0: + resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} + engines: {'0': node >= 6.0} + + console-browserify@1.2.0: + resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} + + constants-browserify@1.0.0: + resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} + + convert-source-map@1.1.3: + resolution: {integrity: sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==} + + convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + core-js@3.45.1: + resolution: {integrity: sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + create-ecdh@4.0.4: + resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + + create-hash@1.1.3: + resolution: {integrity: sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==} + + create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + + create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + crypto-browserify@3.12.1: + resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} + engines: {node: '>= 0.10'} + + d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + + d3-color@1.4.1: + resolution: {integrity: sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==} + + d3-color@2.0.0: + resolution: {integrity: sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==} + + d3-dispatch@1.0.6: + resolution: {integrity: sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==} + + d3-drag@1.2.5: + resolution: {integrity: sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==} + + d3-ease@1.0.7: + resolution: {integrity: sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==} + + d3-fg@6.14.0: + resolution: {integrity: sha512-M4QpFZOEvAq4ZDzwabJp2inL+KXS85T2SQl00zWwjnolaCJR+gHxUbT7Ha4GxTeW1NXwzbykhv/38I1fxQqbyg==} + + d3-format@2.0.0: + resolution: {integrity: sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==} + + d3-hierarchy@1.1.9: + resolution: {integrity: sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==} + + d3-interpolate@1.4.0: + resolution: {integrity: sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==} + + d3-interpolate@2.0.1: + resolution: {integrity: sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==} + + d3-scale@3.3.0: + resolution: {integrity: sha512-1JGp44NQCt5d1g+Yy+GeOnZP7xHo0ii8zsQp6PGzd+C1/dl0KGsp9A7Mxwp+1D1o4unbTTxVdU/ZOIEBoeZPbQ==} + + d3-selection@1.4.2: + resolution: {integrity: sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==} + + d3-time-format@3.0.0: + resolution: {integrity: sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==} + + d3-time@2.1.1: + resolution: {integrity: sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==} + + d3-timer@1.0.10: + resolution: {integrity: sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==} + + d3-transition@1.3.2: + resolution: {integrity: sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==} + + d3-zoom@1.8.3: + resolution: {integrity: sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==} + + dash-ast@1.0.0: + resolution: {integrity: sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==} + + debounce@1.2.1: + resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} + debug@4.4.1: resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} @@ -825,16 +1121,59 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + defined@1.0.1: + resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==} + + deps-sort@2.0.1: + resolution: {integrity: sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==} + hasBin: true + + des.js@1.1.0: + resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} + detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} + detective@5.2.1: + resolution: {integrity: sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==} + engines: {node: '>=0.8.0'} + hasBin: true + + diffie-hellman@5.0.3: + resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + + domain-browser@1.2.0: + resolution: {integrity: sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==} + engines: {node: '>=0.4', npm: '>=1.2'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + duplexer2@0.1.4: + resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} + + duplexify@4.1.3: + resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} electron-to-chromium@1.5.214: resolution: {integrity: sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q==} + elliptic@6.6.1: + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} + emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} engines: {node: '>=12'} @@ -845,17 +1184,39 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + env-string@1.0.1: + resolution: {integrity: sha512-/DhCJDf5DSFK32joQiWRpWrT0h7p3hVQfMKxiBb7Nt8C8IF8BYyPtclDnuGGLOoj16d/8udKeiE7JbkotDmorQ==} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + escape-string-regexp@2.0.0: resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} engines: {node: '>=8'} @@ -907,14 +1268,27 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-is-member-expression@1.0.0: + resolution: {integrity: sha512-Ec+X44CapIGExvSZN+pGkmr5p7HwUVQoPQSd458Lqwvaf4/61k/invHSh4BYK8OXnCkfEhWuIoG5hayKLQStIg==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} + execspawn@1.0.1: + resolution: {integrity: sha512-s2k06Jy9i8CUkYe0+DxRlvtkZoOkwwfhB+Xxo5HGUtrISVW2m98jO2tr67DGRFxZwkjQqloA3v/tNtjhBRBieg==} + exit-x@0.2.2: resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} engines: {node: '>= 0.8.0'} @@ -936,6 +1310,12 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -965,10 +1345,18 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -977,18 +1365,32 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + get-assigned-identifiers@1.2.0: + resolution: {integrity: sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + get-package-type@0.1.0: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} engines: {node: '>=8.0.0'} + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -1017,6 +1419,10 @@ packages: resolution: {integrity: sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==} engines: {node: '>=18'} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -1028,17 +1434,71 @@ packages: engines: {node: '>=0.4.7'} hasBin: true + has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + + hash-base@2.0.2: + resolution: {integrity: sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==} + + hash-base@3.0.5: + resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} + engines: {node: '>= 0.10'} + + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + + hsl-to-rgb-for-reals@1.1.1: + resolution: {integrity: sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + htmlescape@1.1.1: + resolution: {integrity: sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg==} + engines: {node: '>=0.10'} + + https-browserify@1.0.0: + resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} + hyperscript-attribute-to-property@1.0.2: + resolution: {integrity: sha512-oerMul16jZCmrbNsUw8QgrtDzF8lKgFri1bKQjReLw1IhiiNkI59CWuzZjJDGT79UQ1YiWqXhJMv/tRMVqgtkA==} + + hyperx@2.5.4: + resolution: {integrity: sha512-iOkSh7Yse7lsN/B9y7OsevLWjeXPqGuHQ5SbwaiJM5xAhWFqhoN6erpK1dQsS12OFU36lyai1pnx1mmzWLQqcA==} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1064,16 +1524,55 @@ packages: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inline-source-map@0.6.3: + resolution: {integrity: sha512-1aVsPEsJWMJq/pdMU61CDlm1URcW702MTB4w9/zUjMus6H/Py8o7g68Pr9D4I6QluWGt/KdmswuRhaA05xVR1w==} + + insert-module-globals@7.2.1: + resolution: {integrity: sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==} + hasBin: true + + internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-boolean-attribute@0.0.1: + resolution: {integrity: sha512-0kXT52Scokg2Miscvsn5UVqg6y1691vcLJcagie1YHJB4zOEuAhMERLX992jtvaStGy2xQTqOtJhvmG/MK1T5w==} + + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + + is-buffer@2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-fullwidth-code-point@1.0.0: + resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==} + engines: {node: '>=0.10.0'} + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} @@ -1082,6 +1581,10 @@ packages: resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} engines: {node: '>=6'} + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + engines: {node: '>= 0.4'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -1090,10 +1593,28 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-wsl@1.1.0: + resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==} + engines: {node: '>=4'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -1273,6 +1794,9 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -1281,9 +1805,28 @@ packages: engines: {node: '>=6'} hasBin: true + jsonfile@6.2.0: + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + jsonstream2@3.0.0: + resolution: {integrity: sha512-8ngq2XB8NjYrpe3+Xtl9lFJl6RoV2dNT4I7iyaHwxUpTBwsj0AlAR7epGfeYVP0z4Z7KxMoSxRgJWrd2jmBT/Q==} + engines: {node: '>=5.10.0'} + hasBin: true + + kareem@2.6.3: + resolution: {integrity: sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==} + engines: {node: '>=12.0.0'} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + labeled-stream-splicer@2.0.2: + resolution: {integrity: sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==} + leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -1306,12 +1849,25 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.memoize@3.0.4: + resolution: {integrity: sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==} + lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + loglevel@1.9.2: + resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==} + engines: {node: '>= 0.6.0'} + + lower-case@1.1.4: + resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -1321,6 +1877,13 @@ packages: lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + magic-string@0.23.2: + resolution: {integrity: sha512-oIUZaAxbcxYIp4AyLafV6OVKoB3YouZs0UTCJ8mOKBHNyJgGDaMJ4TgA+VylJh6fx7EQCC52XkbURxxG9IoJXA==} + + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} @@ -1335,9 +1898,22 @@ packages: resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} hasBin: true + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + memory-pager@1.5.0: + resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} + + merge-source-map@1.0.4: + resolution: {integrity: sha512-PGSmS0kfnTnMJCzJ16BLLCEe6oeYCamKFFdQKshi4BmM6FUwipjVOcBFGxqtQtirtAG4iZvHlqST9CpZKqlRjA==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -1349,10 +1925,20 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + miller-rabin@4.0.1: + resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} + hasBin: true + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -1367,9 +1953,102 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + + module-deps@6.2.3: + resolution: {integrity: sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==} + engines: {node: '>= 0.8.0'} + hasBin: true + + mongodb-connection-string-url@3.0.2: + resolution: {integrity: sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==} + + mongodb@6.18.0: + resolution: {integrity: sha512-fO5ttN9VC8P0F5fqtQmclAkgXZxbIkYRTUi1j8JO6IYwvamkhtYDilJr35jOPELR49zqCJgXZWwCtW7B+TM8vQ==} + engines: {node: '>=16.20.1'} + peerDependencies: + '@aws-sdk/credential-providers': ^3.188.0 + '@mongodb-js/zstd': ^1.1.0 || ^2.0.0 + gcp-metadata: ^5.2.0 + kerberos: ^2.0.1 + mongodb-client-encryption: '>=6.0.0 <7' + snappy: ^7.2.2 + socks: ^2.7.1 + peerDependenciesMeta: + '@aws-sdk/credential-providers': + optional: true + '@mongodb-js/zstd': + optional: true + gcp-metadata: + optional: true + kerberos: + optional: true + mongodb-client-encryption: + optional: true + snappy: + optional: true + socks: + optional: true + + mongodb@6.19.0: + resolution: {integrity: sha512-H3GtYujOJdeKIMLKBT9PwlDhGrQfplABNF1G904w6r5ZXKWyv77aB0X9B+rhmaAwjtllHzaEkvi9mkGVZxs2Bw==} + engines: {node: '>=16.20.1'} + peerDependencies: + '@aws-sdk/credential-providers': ^3.188.0 + '@mongodb-js/zstd': ^1.1.0 || ^2.0.0 + gcp-metadata: ^5.2.0 + kerberos: ^2.0.1 + mongodb-client-encryption: '>=6.0.0 <7' + snappy: ^7.3.2 + socks: ^2.7.1 + peerDependenciesMeta: + '@aws-sdk/credential-providers': + optional: true + '@mongodb-js/zstd': + optional: true + gcp-metadata: + optional: true + kerberos: + optional: true + mongodb-client-encryption: + optional: true + snappy: + optional: true + socks: + optional: true + + mongoose@8.18.0: + resolution: {integrity: sha512-3TixPihQKBdyaYDeJqRjzgb86KbilEH07JmzV8SoSjgoskNTpa6oTBmDxeoF9p8YnWQoz7shnCyPkSV/48y3yw==} + engines: {node: '>=16.20.1'} + + morphdom@2.7.7: + resolution: {integrity: sha512-04GmsiBcalrSCNmzfo+UjU8tt3PhZJKzcOy+r1FlGA7/zri8wre3I1WkYN9PT3sIeIKfW9bpyElA+VzOg2E24g==} + + mpath@0.9.0: + resolution: {integrity: sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==} + engines: {node: '>=4.0.0'} + + mquery@5.0.0: + resolution: {integrity: sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==} + engines: {node: '>=14.0.0'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mutexify@1.4.0: + resolution: {integrity: sha512-pbYSsOrSB/AKN5h/WzzLRMFgZhClWccf2XIB4RSMC8JbquiB0e0/SH5AIfdQMdyHmYtv4seU7yV/TvAwPLJ1Yg==} + + nanoassert@1.1.0: + resolution: {integrity: sha512-C40jQ3NzfkP53NsO8kEOFd79p4b9kDXQMwgiY1z8ZwrDZgUyom0AHwGegF4Dm99L+YoYhuaB0ceerUcXmqr1rQ==} + + nanobench@2.1.1: + resolution: {integrity: sha512-z+Vv7zElcjN+OpzAxAquUayFLGK3JI/ubCl0Oh64YQqsTGG09CGqieJVQw4ui8huDnnAgrvTv93qi5UaOoNj8A==} + hasBin: true + + nanohtml@1.10.0: + resolution: {integrity: sha512-r/3AQl+jxAxUIJRiKExUjBtFcE1cm4yTOsTIdVqqlxPNtBxJh522ANrcQYzdNHhPzbPgb7j6qujq6eGehBX0kg==} + napi-postinstall@0.3.3: resolution: {integrity: sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -1381,12 +2060,19 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + no-case@2.3.2: + resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} + node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} node-releases@2.0.20: resolution: {integrity: sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==} + normalize-html-whitespace@0.2.0: + resolution: {integrity: sha512-5CZAEQ4bQi8Msqw0GAT6rrkrjNN4ZKqAG3+jJMwms4O6XoMvh6ekwOueG4mRS1LbPUR1r9EdnhxxfpzMTOdzKw==} + engines: {node: '>= 0.10'} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -1395,6 +2081,26 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} + number-is-nan@1.0.1: + resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + on-net-listen@1.1.2: + resolution: {integrity: sha512-y1HRYy8s/RlcBvDUwKXSmkODMdx4KSuIvloCnQYJ2LdBBC1asY4HtfhXwe3UWknLakATZDnbzht2Ijw3M1EqFg==} + engines: {node: '>=9.4.0 || ^8.9.4'} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -1402,10 +2108,17 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + opn@5.5.0: + resolution: {integrity: sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==} + engines: {node: '>=4'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} + os-browserify@0.3.0: + resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} + p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -1429,14 +2142,27 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parents@1.0.1: + resolution: {integrity: sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==} + + parse-asn1@5.1.7: + resolution: {integrity: sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==} + engines: {node: '>= 0.10'} + parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -1449,10 +2175,21 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-platform@0.11.15: + resolution: {integrity: sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==} + engines: {node: '>= 0.8.0'} + path-scurry@1.11.1: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + pbkdf2@3.1.3: + resolution: {integrity: sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==} + engines: {node: '>=0.12'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1472,6 +2209,10 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -1485,10 +2226,33 @@ packages: resolution: {integrity: sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + pretty-hrtime@1.0.3: + resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} + engines: {node: '>= 0.8'} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + public-encrypt@4.0.3: + resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} + + pump@3.0.3: + resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + + pumpify@2.0.1: + resolution: {integrity: sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==} + punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} + punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -1496,16 +2260,50 @@ packages: pure-rand@7.0.1: resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + + querystring-es3@0.2.1: + resolution: {integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==} + engines: {node: '>=0.4.x'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + randomfill@1.0.4: + resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + read-only-stream@2.0.0: + resolution: {integrity: sha512-3ALe0bjBVZtkdWKIcThYpQCLbBMd/+Tbh2CDSrAIDO3UsZ4Xs+tnyjv2MjCOMMgBG+AsUOeuP1cgtY1INISc8w==} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -1518,13 +2316,34 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + ripemd160@2.0.1: + resolution: {integrity: sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==} + + ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -1534,6 +2353,18 @@ packages: engines: {node: '>=10'} hasBin: true + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + sha.js@2.4.12: + resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==} + engines: {node: '>= 0.10'} + hasBin: true + + shasum-object@1.0.0: + resolution: {integrity: sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -1542,6 +2373,29 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shell-quote@1.8.3: + resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} + engines: {node: '>= 0.4'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + sift@17.1.3: + resolution: {integrity: sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -1549,6 +2403,12 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + single-line-log@1.1.2: + resolution: {integrity: sha512-awzaaIPtYFdexLr6TBpcZSGPB6D1RInNO/qNetgaJloPDF/D0GkVtLvGEp8InfmLV7CyLyQ5fIRP+tVN/JmWQA==} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -1556,10 +2416,25 @@ packages: source-map-support@0.5.13: resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + + sparse-bitfield@3.0.3: + resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -1567,10 +2442,29 @@ packages: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} + stream-browserify@3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + + stream-combiner2@1.1.1: + resolution: {integrity: sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==} + + stream-http@3.2.0: + resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==} + + stream-shift@1.0.3: + resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} + + stream-splicer@2.0.1: + resolution: {integrity: sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==} + string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} + string-width@1.0.2: + resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==} + engines: {node: '>=0.10.0'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -1579,6 +2473,16 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -1599,6 +2503,13 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + subarg@1.0.0: + resolution: {integrity: sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==} + + supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -1607,21 +2518,58 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + synckit@0.11.11: resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} engines: {node: ^14.18.0 || >=16.0.0} + syntax-error@1.4.0: + resolution: {integrity: sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==} + + tachyons@4.12.0: + resolution: {integrity: sha512-2nA2IrYFy3raCM9fxJ2KODRGHVSZNTW3BR0YnlGsLUf1DA3pk3YfWZ/DdfbnZK6zLZS+jUenlUGJsKcA5fUiZg==} + test-exclude@6.0.0: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} + through2@2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + + through2@3.0.2: + resolution: {integrity: sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==} + + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + timers-browserify@1.4.2: + resolution: {integrity: sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q==} + engines: {node: '>=0.6.0'} + tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + to-buffer@1.2.1: + resolution: {integrity: sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==} + engines: {node: '>= 0.4'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + + transform-ast@2.4.4: + resolution: {integrity: sha512-AxjeZAcIOUO2lev2GDe3/xZ1Q0cVGjIMk5IsriTy8zbWlsEnjeB025AhkhBJHoy997mXpLd4R+kRbvnnQVuQHQ==} + ts-api-utils@2.1.0: resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} @@ -1658,10 +2606,16 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tty-browserify@0.0.1: + resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-component@0.0.1: + resolution: {integrity: sha512-mDZRBQS2yZkwRQKfjJvQ8UIYJeBNNWCq+HBNstl9N5s9jZ4dkVYXEGkVPsSCEh5Ld4JM1kmrZTzjnrqSAIQ7dw==} + type-detect@4.0.8: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} @@ -1674,6 +2628,13 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + typedoc@0.28.12: resolution: {integrity: sha512-H5ODu4f7N+myG4MfuSp2Vh6wV+WLoZaEYxKPt2y8hmmqNEMVrH69DAjjdmYivF4tP/C2jrIZCZhPalZlTU/ipA==} engines: {node: '>= 18', pnpm: '>= 10'} @@ -1701,9 +2662,21 @@ packages: engines: {node: '>=0.8.0'} hasBin: true + umd@3.0.3: + resolution: {integrity: sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==} + hasBin: true + + undeclared-identifiers@1.1.3: + resolution: {integrity: sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==} + hasBin: true + undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} @@ -1713,16 +2686,50 @@ packages: peerDependencies: browserslist: '>= 4.21.0' + upper-case@1.1.3: + resolution: {integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==} + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + url@0.11.4: + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util-extend@1.0.3: + resolution: {integrity: sha512-mLs5zAK+ctllYBj+iAQvlDCwoxU/WDOUaJkcFudeiAX6OajC6BKXJUa9a+tbtkC11dz2Ufb7h0lyvIOVn4LADA==} + + util@0.10.4: + resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + v8-to-istanbul@9.3.0: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} + vm-browserify@1.1.2: + resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} + walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -1750,6 +2757,10 @@ packages: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -1776,6 +2787,39 @@ packages: snapshots: + 0x@6.0.0: + dependencies: + ajv: 8.17.1 + browserify: 17.0.1 + concat-stream: 2.0.0 + d3-fg: 6.14.0 + debounce: 1.2.1 + debug: 4.4.1 + end-of-stream: 1.4.5 + env-string: 1.0.1 + escape-string-regexp: 4.0.0 + execspawn: 1.0.1 + fs-extra: 10.1.0 + has-unicode: 2.0.1 + hsl-to-rgb-for-reals: 1.1.1 + jsonstream2: 3.0.0 + make-dir: 3.1.0 + minimist: 1.2.8 + morphdom: 2.7.7 + nanohtml: 1.10.0 + on-net-listen: 1.1.2 + opn: 5.5.0 + pump: 3.0.3 + pumpify: 2.0.1 + semver: 7.7.2 + single-line-log: 1.1.2 + split2: 4.2.0 + tachyons: 4.12.0 + through2: 4.0.2 + which: 2.0.2 + transitivePeerDependencies: + - supports-color + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -1965,6 +3009,10 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} + '@catatomik/dijkstra@https://codeload.github.com/catatomik/dijkstra/tar.gz/e3304b71e4bda9aefb04d2d18b32e7aa369a4aed': + dependencies: + '@tyriar/fibonacci-heap': 2.0.9 + '@emnapi/core@1.5.0': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -2025,12 +3073,12 @@ snapshots: '@eslint/core': 0.15.2 levn: 0.4.1 - '@gerrit0/mini-shiki@3.12.0': + '@gerrit0/mini-shiki@3.12.2': dependencies: - '@shikijs/engine-oniguruma': 3.12.1 - '@shikijs/langs': 3.12.1 - '@shikijs/themes': 3.12.1 - '@shikijs/types': 3.12.1 + '@shikijs/engine-oniguruma': 3.12.2 + '@shikijs/langs': 3.12.2 + '@shikijs/themes': 3.12.2 + '@shikijs/types': 3.12.2 '@shikijs/vscode-textmate': 10.0.2 '@humanfs/core@0.19.1': {} @@ -2066,7 +3114,7 @@ snapshots: '@jest/console@30.1.2': dependencies: '@jest/types': 30.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 chalk: 4.1.2 jest-message-util: 30.1.0 jest-util: 30.0.5 @@ -2080,14 +3128,14 @@ snapshots: '@jest/test-result': 30.1.3 '@jest/transform': 30.1.2 '@jest/types': 30.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 4.3.0 exit-x: 0.2.2 graceful-fs: 4.2.11 jest-changed-files: 30.0.5 - jest-config: 30.1.3(@types/node@22.15.32) + jest-config: 30.1.3(@types/node@22.18.1) jest-haste-map: 30.1.0 jest-message-util: 30.1.0 jest-regex-util: 30.0.1 @@ -2114,7 +3162,7 @@ snapshots: dependencies: '@jest/fake-timers': 30.1.2 '@jest/types': 30.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 jest-mock: 30.0.5 '@jest/expect-utils@30.1.2': @@ -2132,7 +3180,7 @@ snapshots: dependencies: '@jest/types': 30.0.5 '@sinonjs/fake-timers': 13.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 jest-message-util: 30.1.0 jest-mock: 30.0.5 jest-util: 30.0.5 @@ -2150,7 +3198,7 @@ snapshots: '@jest/pattern@30.0.1': dependencies: - '@types/node': 22.15.32 + '@types/node': 22.18.1 jest-regex-util: 30.0.1 '@jest/reporters@30.1.3': @@ -2161,7 +3209,7 @@ snapshots: '@jest/transform': 30.1.2 '@jest/types': 30.0.5 '@jridgewell/trace-mapping': 0.3.30 - '@types/node': 22.15.32 + '@types/node': 22.18.1 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit-x: 0.2.2 @@ -2238,7 +3286,7 @@ snapshots: '@jest/schemas': 30.0.5 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.15.32 + '@types/node': 22.18.1 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -2261,6 +3309,10 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@mongodb-js/saslprep@1.3.0': + dependencies: + sparse-bitfield: 3.0.3 + '@napi-rs/wasm-runtime@0.2.12': dependencies: '@emnapi/core': 1.5.0 @@ -2285,20 +3337,20 @@ snapshots: '@pkgr/core@0.2.9': {} - '@shikijs/engine-oniguruma@3.12.1': + '@shikijs/engine-oniguruma@3.12.2': dependencies: - '@shikijs/types': 3.12.1 + '@shikijs/types': 3.12.2 '@shikijs/vscode-textmate': 10.0.2 - '@shikijs/langs@3.12.1': + '@shikijs/langs@3.12.2': dependencies: - '@shikijs/types': 3.12.1 + '@shikijs/types': 3.12.2 - '@shikijs/themes@3.12.1': + '@shikijs/themes@3.12.2': dependencies: - '@shikijs/types': 3.12.1 + '@shikijs/types': 3.12.2 - '@shikijs/types@3.12.1': + '@shikijs/types@3.12.2': dependencies: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 @@ -2322,6 +3374,15 @@ snapshots: tslib: 2.8.1 optional: true + '@typegoose/typegoose@12.19.0(mongoose@8.18.0)': + dependencies: + lodash: 4.17.21 + loglevel: 1.9.2 + mongoose: 8.18.0 + reflect-metadata: 0.2.2 + semver: 7.7.2 + tslib: 2.8.1 + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.28.4 @@ -2361,7 +3422,9 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@22.15.32': + '@types/minimist@1.2.5': {} + + '@types/node@22.18.1': dependencies: undici-types: 6.21.0 @@ -2369,6 +3432,12 @@ snapshots: '@types/unist@3.0.3': {} + '@types/webidl-conversions@7.0.3': {} + + '@types/whatwg-url@11.0.5': + dependencies: + '@types/webidl-conversions': 7.0.3 + '@types/yargs-parser@21.0.3': {} '@types/yargs@17.0.33': @@ -2468,6 +3537,8 @@ snapshots: '@typescript-eslint/types': 8.43.0 eslint-visitor-keys: 4.2.1 + '@tyriar/fibonacci-heap@2.0.9': {} + '@ungap/structured-clone@1.3.0': {} '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -2529,10 +3600,25 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true + JSONStream@1.3.5: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: acorn: 8.15.0 + acorn-node@1.8.2: + dependencies: + acorn: 7.4.1 + acorn-walk: 7.2.0 + xtend: 4.0.2 + + acorn-walk@7.2.0: {} + + acorn@7.4.1: {} + acorn@8.15.0: {} ajv@6.12.6: @@ -2542,14 +3628,25 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 + ansi-regex@2.1.1: {} + ansi-regex@5.0.1: {} ansi-regex@6.2.2: {} + ansi-styles@2.2.1: {} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 @@ -2569,6 +3666,21 @@ snapshots: argparse@2.0.1: {} + asn1.js@4.10.1: + dependencies: + bn.js: 4.12.2 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + assert@1.5.1: + dependencies: + object.assign: 4.1.7 + util: 0.10.4 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + babel-jest@30.1.2(@babel/core@7.28.4): dependencies: '@babel/core': 7.28.4 @@ -2625,6 +3737,12 @@ snapshots: balanced-match@1.0.2: {} + base64-js@1.5.1: {} + + bn.js@4.12.2: {} + + bn.js@5.2.2: {} + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -2638,6 +3756,119 @@ snapshots: dependencies: fill-range: 7.1.1 + brorand@1.1.0: {} + + browser-pack@6.1.0: + dependencies: + JSONStream: 1.3.5 + combine-source-map: 0.8.0 + defined: 1.0.1 + safe-buffer: 5.2.1 + through2: 2.0.5 + umd: 3.0.3 + + browser-process-hrtime@0.1.3: {} + + browser-resolve@2.0.0: + dependencies: + resolve: 1.22.10 + + browserify-aes@1.2.0: + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.6 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-cipher@1.0.1: + dependencies: + browserify-aes: 1.2.0 + browserify-des: 1.0.2 + evp_bytestokey: 1.0.3 + + browserify-des@1.0.2: + dependencies: + cipher-base: 1.0.6 + des.js: 1.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-rsa@4.1.1: + dependencies: + bn.js: 5.2.2 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + browserify-sign@4.2.3: + dependencies: + bn.js: 5.2.2 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + create-hmac: 1.1.7 + elliptic: 6.6.1 + hash-base: 3.0.5 + inherits: 2.0.4 + parse-asn1: 5.1.7 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + + browserify-zlib@0.2.0: + dependencies: + pako: 1.0.11 + + browserify@17.0.1: + dependencies: + JSONStream: 1.3.5 + assert: 1.5.1 + browser-pack: 6.1.0 + browser-resolve: 2.0.0 + browserify-zlib: 0.2.0 + buffer: 5.2.1 + cached-path-relative: 1.1.0 + concat-stream: 1.6.2 + console-browserify: 1.2.0 + constants-browserify: 1.0.0 + crypto-browserify: 3.12.1 + defined: 1.0.1 + deps-sort: 2.0.1 + domain-browser: 1.2.0 + duplexer2: 0.1.4 + events: 3.3.0 + glob: 7.2.3 + hasown: 2.0.2 + htmlescape: 1.1.1 + https-browserify: 1.0.0 + inherits: 2.0.4 + insert-module-globals: 7.2.1 + labeled-stream-splicer: 2.0.2 + mkdirp-classic: 0.5.3 + module-deps: 6.2.3 + os-browserify: 0.3.0 + parents: 1.0.1 + path-browserify: 1.0.1 + process: 0.11.10 + punycode: 1.4.1 + querystring-es3: 0.2.1 + read-only-stream: 2.0.0 + readable-stream: 2.3.8 + resolve: 1.22.10 + shasum-object: 1.0.0 + shell-quote: 1.8.3 + stream-browserify: 3.0.0 + stream-http: 3.2.0 + string_decoder: 1.3.0 + subarg: 1.0.0 + syntax-error: 1.4.0 + through2: 2.0.5 + timers-browserify: 1.4.2 + tty-browserify: 0.0.1 + url: 0.11.4 + util: 0.12.5 + vm-browserify: 1.1.2 + xtend: 4.0.2 + browserslist@4.25.4: dependencies: caniuse-lite: 1.0.30001741 @@ -2653,16 +3884,59 @@ snapshots: dependencies: node-int64: 0.4.0 + bson@6.10.4: {} + buffer-from@1.1.2: {} + buffer-xor@1.0.3: {} + + buffer@5.2.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + builtin-status-codes@3.0.0: {} + + cached-path-relative@1.1.0: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + callsites@3.1.0: {} + camel-case@3.0.0: + dependencies: + no-case: 2.3.2 + upper-case: 1.1.3 + camelcase@5.3.1: {} camelcase@6.3.0: {} caniuse-lite@1.0.30001741: {} + chalk@1.1.3: + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -2672,6 +3946,11 @@ snapshots: ci-info@4.3.0: {} + cipher-base@1.0.6: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + cjs-module-lexer@2.1.0: {} cliui@8.0.1: @@ -2682,6 +3961,8 @@ snapshots: co@4.6.0: {} + code-point-at@1.1.0: {} + collect-v8-coverage@1.0.2: {} color-convert@2.0.1: @@ -2690,16 +3971,175 @@ snapshots: color-name@1.1.4: {} + combine-source-map@0.8.0: + dependencies: + convert-source-map: 1.1.3 + inline-source-map: 0.6.3 + lodash.memoize: 3.0.4 + source-map: 0.5.7 + concat-map@0.0.1: {} + concat-stream@1.6.2: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.8 + typedarray: 0.0.6 + + concat-stream@2.0.0: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.2 + typedarray: 0.0.6 + + console-browserify@1.2.0: {} + + constants-browserify@1.0.0: {} + + convert-source-map@1.1.3: {} + + convert-source-map@1.9.0: {} + convert-source-map@2.0.0: {} + core-js@3.45.1: {} + + core-util-is@1.0.3: {} + + create-ecdh@4.0.4: + dependencies: + bn.js: 4.12.2 + elliptic: 6.6.1 + + create-hash@1.1.3: + dependencies: + cipher-base: 1.0.6 + inherits: 2.0.4 + ripemd160: 2.0.1 + sha.js: 2.4.12 + + create-hash@1.2.0: + dependencies: + cipher-base: 1.0.6 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.12 + + create-hmac@1.1.7: + dependencies: + cipher-base: 1.0.6 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.12 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 + crypto-browserify@3.12.1: + dependencies: + browserify-cipher: 1.0.1 + browserify-sign: 4.2.3 + create-ecdh: 4.0.4 + create-hash: 1.2.0 + create-hmac: 1.1.7 + diffie-hellman: 5.0.3 + hash-base: 3.0.5 + inherits: 2.0.4 + pbkdf2: 3.1.3 + public-encrypt: 4.0.3 + randombytes: 2.1.0 + randomfill: 1.0.4 + + d3-array@2.12.1: + dependencies: + internmap: 1.0.1 + + d3-color@1.4.1: {} + + d3-color@2.0.0: {} + + d3-dispatch@1.0.6: {} + + d3-drag@1.2.5: + dependencies: + d3-dispatch: 1.0.6 + d3-selection: 1.4.2 + + d3-ease@1.0.7: {} + + d3-fg@6.14.0: + dependencies: + d3-array: 2.12.1 + d3-dispatch: 1.0.6 + d3-ease: 1.0.7 + d3-hierarchy: 1.1.9 + d3-scale: 3.3.0 + d3-selection: 1.4.2 + d3-zoom: 1.8.3 + escape-string-regexp: 1.0.5 + hsl-to-rgb-for-reals: 1.1.1 + + d3-format@2.0.0: {} + + d3-hierarchy@1.1.9: {} + + d3-interpolate@1.4.0: + dependencies: + d3-color: 1.4.1 + + d3-interpolate@2.0.1: + dependencies: + d3-color: 2.0.0 + + d3-scale@3.3.0: + dependencies: + d3-array: 2.12.1 + d3-format: 2.0.0 + d3-interpolate: 2.0.1 + d3-time: 2.1.1 + d3-time-format: 3.0.0 + + d3-selection@1.4.2: {} + + d3-time-format@3.0.0: + dependencies: + d3-time: 2.1.1 + + d3-time@2.1.1: + dependencies: + d3-array: 2.12.1 + + d3-timer@1.0.10: {} + + d3-transition@1.3.2: + dependencies: + d3-color: 1.4.1 + d3-dispatch: 1.0.6 + d3-ease: 1.0.7 + d3-interpolate: 1.4.0 + d3-selection: 1.4.2 + d3-timer: 1.0.10 + + d3-zoom@1.8.3: + dependencies: + d3-dispatch: 1.0.6 + d3-drag: 1.2.5 + d3-interpolate: 1.4.0 + d3-selection: 1.4.2 + d3-transition: 1.3.2 + + dash-ast@1.0.0: {} + + debounce@1.2.1: {} + debug@4.4.1: dependencies: ms: 2.1.3 @@ -2710,29 +4150,112 @@ snapshots: deepmerge@4.3.1: {} + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + defined@1.0.1: {} + + deps-sort@2.0.1: + dependencies: + JSONStream: 1.3.5 + shasum-object: 1.0.0 + subarg: 1.0.0 + through2: 2.0.5 + + des.js@1.1.0: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + detect-newline@3.1.0: {} + detective@5.2.1: + dependencies: + acorn-node: 1.8.2 + defined: 1.0.1 + minimist: 1.2.8 + + diffie-hellman@5.0.3: + dependencies: + bn.js: 4.12.2 + miller-rabin: 4.0.1 + randombytes: 2.1.0 + + domain-browser@1.2.0: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexer2@0.1.4: + dependencies: + readable-stream: 2.3.8 + + duplexify@4.1.3: + dependencies: + end-of-stream: 1.4.5 + inherits: 2.0.4 + readable-stream: 3.6.2 + stream-shift: 1.0.3 + eastasianwidth@0.2.0: {} electron-to-chromium@1.5.214: {} + elliptic@6.6.1: + dependencies: + bn.js: 4.12.2 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + emittery@0.13.1: {} emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + entities@4.5.0: {} + env-string@1.0.1: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - escalade@3.2.0: {} + es-define-property@1.0.1: {} - escape-string-regexp@2.0.0: {} + es-errors@1.3.0: {} - escape-string-regexp@4.0.0: {} + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + escalade@3.2.0: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@2.0.0: {} + + escape-string-regexp@4.0.0: {} eslint-scope@8.4.0: dependencies: @@ -2801,8 +4324,17 @@ snapshots: estraverse@5.3.0: {} + estree-is-member-expression@1.0.0: {} + esutils@2.0.3: {} + events@3.3.0: {} + + evp_bytestokey@1.0.3: + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -2815,6 +4347,10 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + execspawn@1.0.1: + dependencies: + util-extend: 1.0.3 + exit-x@0.2.2: {} expect@30.1.2: @@ -2840,6 +4376,10 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-safe-stringify@2.1.1: {} + + fast-uri@3.1.0: {} + fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -2873,22 +4413,54 @@ snapshots: flatted@3.3.3: {} + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + fs.realpath@1.0.0: {} fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + gensync@1.0.0-beta.2: {} + get-assigned-identifiers@1.2.0: {} + get-caller-file@2.0.5: {} + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + get-package-type@0.1.0: {} + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + get-stream@6.0.1: {} glob-parent@5.1.2: @@ -2921,6 +4493,8 @@ snapshots: globals@16.3.0: {} + gopd@1.2.0: {} + graceful-fs@4.2.11: {} graphemer@1.4.0: {} @@ -2934,12 +4508,66 @@ snapshots: optionalDependencies: uglify-js: 3.19.3 + has-ansi@2.0.0: + dependencies: + ansi-regex: 2.1.1 + has-flag@4.0.0: {} + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + has-unicode@2.0.1: {} + + hash-base@2.0.2: + dependencies: + inherits: 2.0.4 + + hash-base@3.0.5: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hmac-drbg@1.0.1: + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + hsl-to-rgb-for-reals@1.1.1: {} + html-escaper@2.0.2: {} + htmlescape@1.1.1: {} + + https-browserify@1.0.0: {} + human-signals@2.1.0: {} + hyperscript-attribute-to-property@1.0.2: {} + + hyperx@2.5.4: + dependencies: + hyperscript-attribute-to-property: 1.0.2 + + ieee754@1.2.1: {} + ignore@5.3.2: {} ignore@7.0.5: {} @@ -2961,24 +4589,90 @@ snapshots: once: 1.4.0 wrappy: 1.0.2 + inherits@2.0.3: {} + inherits@2.0.4: {} + inline-source-map@0.6.3: + dependencies: + source-map: 0.5.7 + + insert-module-globals@7.2.1: + dependencies: + JSONStream: 1.3.5 + acorn-node: 1.8.2 + combine-source-map: 0.8.0 + concat-stream: 1.6.2 + is-buffer: 1.1.6 + path-is-absolute: 1.0.1 + process: 0.11.10 + through2: 2.0.5 + undeclared-identifiers: 1.1.3 + xtend: 4.0.2 + + internmap@1.0.1: {} + + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-arrayish@0.2.1: {} + is-boolean-attribute@0.0.1: {} + + is-buffer@1.1.6: {} + + is-buffer@2.0.5: {} + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + is-extglob@2.1.1: {} + is-fullwidth-code-point@1.0.0: + dependencies: + number-is-nan: 1.0.1 + is-fullwidth-code-point@3.0.0: {} is-generator-fn@2.1.0: {} + is-generator-function@1.1.0: + dependencies: + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 is-number@7.0.0: {} + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + is-stream@2.0.1: {} + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.19 + + is-wsl@1.1.0: {} + + isarray@1.0.0: {} + + isarray@2.0.5: {} + isexe@2.0.0: {} istanbul-lib-coverage@3.2.2: {} @@ -3030,7 +4724,7 @@ snapshots: '@jest/expect': 30.1.2 '@jest/test-result': 30.1.3 '@jest/types': 30.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 chalk: 4.1.2 co: 4.6.0 dedent: 1.7.0 @@ -3050,7 +4744,7 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@30.1.3(@types/node@22.15.32): + jest-cli@30.1.3(@types/node@22.18.1): dependencies: '@jest/core': 30.1.3 '@jest/test-result': 30.1.3 @@ -3058,7 +4752,7 @@ snapshots: chalk: 4.1.2 exit-x: 0.2.2 import-local: 3.2.0 - jest-config: 30.1.3(@types/node@22.15.32) + jest-config: 30.1.3(@types/node@22.18.1) jest-util: 30.0.5 jest-validate: 30.1.0 yargs: 17.7.2 @@ -3069,7 +4763,7 @@ snapshots: - supports-color - ts-node - jest-config@30.1.3(@types/node@22.15.32): + jest-config@30.1.3(@types/node@22.18.1): dependencies: '@babel/core': 7.28.4 '@jest/get-type': 30.1.0 @@ -3096,7 +4790,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 22.15.32 + '@types/node': 22.18.1 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -3125,7 +4819,7 @@ snapshots: '@jest/environment': 30.1.2 '@jest/fake-timers': 30.1.2 '@jest/types': 30.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 jest-mock: 30.0.5 jest-util: 30.0.5 jest-validate: 30.1.0 @@ -3133,7 +4827,7 @@ snapshots: jest-haste-map@30.1.0: dependencies: '@jest/types': 30.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -3172,7 +4866,7 @@ snapshots: jest-mock@30.0.5: dependencies: '@jest/types': 30.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 jest-util: 30.0.5 jest-pnp-resolver@1.2.3(jest-resolve@30.1.3): @@ -3206,7 +4900,7 @@ snapshots: '@jest/test-result': 30.1.3 '@jest/transform': 30.1.2 '@jest/types': 30.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 chalk: 4.1.2 emittery: 0.13.1 exit-x: 0.2.2 @@ -3235,7 +4929,7 @@ snapshots: '@jest/test-result': 30.1.3 '@jest/transform': 30.1.2 '@jest/types': 30.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 chalk: 4.1.2 cjs-module-lexer: 2.1.0 collect-v8-coverage: 1.0.2 @@ -3282,7 +4976,7 @@ snapshots: jest-util@30.0.5: dependencies: '@jest/types': 30.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 chalk: 4.1.2 ci-info: 4.3.0 graceful-fs: 4.2.11 @@ -3301,7 +4995,7 @@ snapshots: dependencies: '@jest/test-result': 30.1.3 '@jest/types': 30.0.5 - '@types/node': 22.15.32 + '@types/node': 22.18.1 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -3310,18 +5004,18 @@ snapshots: jest-worker@30.1.0: dependencies: - '@types/node': 22.15.32 + '@types/node': 22.18.1 '@ungap/structured-clone': 1.3.0 jest-util: 30.0.5 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@30.1.3(@types/node@22.15.32): + jest@30.1.3(@types/node@22.18.1): dependencies: '@jest/core': 30.1.3 '@jest/types': 30.0.5 import-local: 3.2.0 - jest-cli: 30.1.3(@types/node@22.15.32) + jest-cli: 30.1.3(@types/node@22.18.1) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -3348,14 +5042,37 @@ snapshots: json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json5@2.2.3: {} + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonparse@1.3.1: {} + + jsonstream2@3.0.0: + dependencies: + jsonparse: 1.3.1 + through2: 3.0.2 + type-component: 0.0.1 + + kareem@2.6.3: {} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 + labeled-stream-splicer@2.0.2: + dependencies: + inherits: 2.0.4 + stream-splicer: 2.0.1 + leven@3.1.0: {} levn@0.4.1: @@ -3377,10 +5094,18 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.memoize@3.0.4: {} + lodash.memoize@4.1.2: {} lodash.merge@4.6.2: {} + lodash@4.17.21: {} + + loglevel@1.9.2: {} + + lower-case@1.1.4: {} + lru-cache@10.4.3: {} lru-cache@5.1.1: @@ -3389,6 +5114,14 @@ snapshots: lunr@2.3.9: {} + magic-string@0.23.2: + dependencies: + sourcemap-codec: 1.4.8 + + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + make-dir@4.0.0: dependencies: semver: 7.7.2 @@ -3408,8 +5141,22 @@ snapshots: punycode.js: 2.3.1 uc.micro: 2.1.0 + math-intrinsics@1.1.0: {} + + md5.js@1.3.5: + dependencies: + hash-base: 3.0.5 + inherits: 2.0.4 + safe-buffer: 5.2.1 + mdurl@2.0.0: {} + memory-pager@1.5.0: {} + + merge-source-map@1.0.4: + dependencies: + source-map: 0.5.7 + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -3419,8 +5166,17 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + miller-rabin@4.0.1: + dependencies: + bn.js: 4.12.2 + brorand: 1.1.0 + mimic-fn@2.1.0: {} + minimalistic-assert@1.0.1: {} + + minimalistic-crypto-utils@1.0.1: {} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.12 @@ -3433,24 +5189,140 @@ snapshots: minipass@7.1.2: {} + mkdirp-classic@0.5.3: {} + + module-deps@6.2.3: + dependencies: + JSONStream: 1.3.5 + browser-resolve: 2.0.0 + cached-path-relative: 1.1.0 + concat-stream: 1.6.2 + defined: 1.0.1 + detective: 5.2.1 + duplexer2: 0.1.4 + inherits: 2.0.4 + parents: 1.0.1 + readable-stream: 2.3.8 + resolve: 1.22.10 + stream-combiner2: 1.1.1 + subarg: 1.0.0 + through2: 2.0.5 + xtend: 4.0.2 + + mongodb-connection-string-url@3.0.2: + dependencies: + '@types/whatwg-url': 11.0.5 + whatwg-url: 14.2.0 + + mongodb@6.18.0: + dependencies: + '@mongodb-js/saslprep': 1.3.0 + bson: 6.10.4 + mongodb-connection-string-url: 3.0.2 + + mongodb@6.19.0: + dependencies: + '@mongodb-js/saslprep': 1.3.0 + bson: 6.10.4 + mongodb-connection-string-url: 3.0.2 + + mongoose@8.18.0: + dependencies: + bson: 6.10.4 + kareem: 2.6.3 + mongodb: 6.18.0 + mpath: 0.9.0 + mquery: 5.0.0 + ms: 2.1.3 + sift: 17.1.3 + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - gcp-metadata + - kerberos + - mongodb-client-encryption + - snappy + - socks + - supports-color + + morphdom@2.7.7: {} + + mpath@0.9.0: {} + + mquery@5.0.0: + dependencies: + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + ms@2.1.3: {} + mutexify@1.4.0: + dependencies: + queue-tick: 1.0.1 + + nanoassert@1.1.0: {} + + nanobench@2.1.1: + dependencies: + browser-process-hrtime: 0.1.3 + chalk: 1.1.3 + mutexify: 1.4.0 + pretty-hrtime: 1.0.3 + + nanohtml@1.10.0: + dependencies: + acorn-node: 1.8.2 + camel-case: 3.0.0 + convert-source-map: 1.9.0 + estree-is-member-expression: 1.0.0 + hyperx: 2.5.4 + is-boolean-attribute: 0.0.1 + nanoassert: 1.1.0 + nanobench: 2.1.1 + normalize-html-whitespace: 0.2.0 + through2: 2.0.5 + transform-ast: 2.4.4 + napi-postinstall@0.3.3: {} natural-compare@1.4.0: {} neo-async@2.6.2: {} + no-case@2.3.2: + dependencies: + lower-case: 1.1.4 + node-int64@0.4.0: {} node-releases@2.0.20: {} + normalize-html-whitespace@0.2.0: {} + normalize-path@3.0.0: {} npm-run-path@4.0.1: dependencies: path-key: 3.1.1 + number-is-nan@1.0.1: {} + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + on-net-listen@1.1.2: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -3459,6 +5331,10 @@ snapshots: dependencies: mimic-fn: 2.1.0 + opn@5.5.0: + dependencies: + is-wsl: 1.1.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -3468,6 +5344,8 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + os-browserify@0.3.0: {} + p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -3488,10 +5366,25 @@ snapshots: package-json-from-dist@1.0.1: {} + pako@1.0.11: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 + parents@1.0.1: + dependencies: + path-platform: 0.11.15 + + parse-asn1@5.1.7: + dependencies: + asn1.js: 4.10.1 + browserify-aes: 1.2.0 + evp_bytestokey: 1.0.3 + hash-base: 3.0.5 + pbkdf2: 3.1.3 + safe-buffer: 5.2.1 + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.27.1 @@ -3499,17 +5392,32 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + path-browserify@1.0.1: {} + path-exists@4.0.0: {} path-is-absolute@1.0.1: {} path-key@3.1.1: {} + path-parse@1.0.7: {} + + path-platform@0.11.15: {} + path-scurry@1.11.1: dependencies: lru-cache: 10.4.3 minipass: 7.1.2 + pbkdf2@3.1.3: + dependencies: + create-hash: 1.1.3 + create-hmac: 1.1.7 + ripemd160: 2.0.1 + safe-buffer: 5.2.1 + sha.js: 2.4.12 + to-buffer: 1.2.1 + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -3522,6 +5430,8 @@ snapshots: dependencies: find-up: 4.1.0 + possible-typed-array-names@1.1.0: {} + prelude-ls@1.2.1: {} prettier@3.6.2: {} @@ -3532,18 +5442,87 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 + pretty-hrtime@1.0.3: {} + + process-nextick-args@2.0.1: {} + + process@0.11.10: {} + + public-encrypt@4.0.3: + dependencies: + bn.js: 4.12.2 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + parse-asn1: 5.1.7 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + pump@3.0.3: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + pumpify@2.0.1: + dependencies: + duplexify: 4.1.3 + inherits: 2.0.4 + pump: 3.0.3 + punycode.js@2.3.1: {} + punycode@1.4.1: {} + punycode@2.3.1: {} pure-rand@7.0.1: {} + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + + querystring-es3@0.2.1: {} + queue-microtask@1.2.3: {} + queue-tick@1.0.1: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + randomfill@1.0.4: + dependencies: + randombytes: 2.1.0 + safe-buffer: 5.2.1 + react-is@18.3.1: {} + read-only-stream@2.0.0: + dependencies: + readable-stream: 2.3.8 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + reflect-metadata@0.2.2: {} + require-directory@2.1.1: {} + require-from-string@2.0.2: {} + resolve-cwd@3.0.0: dependencies: resolve-from: 5.0.0 @@ -3552,26 +5531,109 @@ snapshots: resolve-from@5.0.0: {} + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + reusify@1.1.0: {} + ripemd160@2.0.1: + dependencies: + hash-base: 2.0.2 + inherits: 2.0.4 + + ripemd160@2.0.2: + dependencies: + hash-base: 3.0.5 + inherits: 2.0.4 + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + semver@6.3.1: {} semver@7.7.2: {} + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + sha.js@2.4.12: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + to-buffer: 1.2.1 + + shasum-object@1.0.0: + dependencies: + fast-safe-stringify: 2.1.1 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 shebang-regex@3.0.0: {} + shell-quote@1.8.3: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + sift@17.1.3: {} + signal-exit@3.0.7: {} signal-exit@4.1.0: {} + simple-concat@1.0.1: {} + + single-line-log@1.1.2: + dependencies: + string-width: 1.0.2 + slash@3.0.0: {} source-map-support@0.5.13: @@ -3579,19 +5641,59 @@ snapshots: buffer-from: 1.1.2 source-map: 0.6.1 + source-map@0.5.7: {} + source-map@0.6.1: {} + sourcemap-codec@1.4.8: {} + + sparse-bitfield@3.0.3: + dependencies: + memory-pager: 1.5.0 + + split2@4.2.0: {} + sprintf-js@1.0.3: {} stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 + stream-browserify@3.0.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + + stream-combiner2@1.1.1: + dependencies: + duplexer2: 0.1.4 + readable-stream: 2.3.8 + + stream-http@3.2.0: + dependencies: + builtin-status-codes: 3.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + xtend: 4.0.2 + + stream-shift@1.0.3: {} + + stream-splicer@2.0.1: + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.8 + string-length@4.0.2: dependencies: char-regex: 1.0.2 strip-ansi: 6.0.1 + string-width@1.0.2: + dependencies: + code-point-at: 1.1.0 + is-fullwidth-code-point: 1.0.0 + strip-ansi: 3.0.1 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -3604,6 +5706,18 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.2 + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@3.0.1: + dependencies: + ansi-regex: 2.1.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -3618,6 +5732,12 @@ snapshots: strip-json-comments@3.1.1: {} + subarg@1.0.0: + dependencies: + minimist: 1.2.8 + + supports-color@2.0.0: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -3626,32 +5746,80 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} + synckit@0.11.11: dependencies: '@pkgr/core': 0.2.9 + syntax-error@1.4.0: + dependencies: + acorn-node: 1.8.2 + + tachyons@4.12.0: {} + test-exclude@6.0.0: dependencies: '@istanbuljs/schema': 0.1.3 glob: 7.2.3 minimatch: 3.1.2 + through2@2.0.5: + dependencies: + readable-stream: 2.3.8 + xtend: 4.0.2 + + through2@3.0.2: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + + through2@4.0.2: + dependencies: + readable-stream: 3.6.2 + + through@2.3.8: {} + + timers-browserify@1.4.2: + dependencies: + process: 0.11.10 + tmpl@1.0.5: {} + to-buffer@1.2.1: + dependencies: + isarray: 2.0.5 + safe-buffer: 5.2.1 + typed-array-buffer: 1.0.3 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + + transform-ast@2.4.4: + dependencies: + acorn-node: 1.8.2 + convert-source-map: 1.9.0 + dash-ast: 1.0.0 + is-buffer: 2.0.5 + magic-string: 0.23.2 + merge-source-map: 1.0.4 + nanobench: 2.1.1 + ts-api-utils@2.1.0(typescript@5.9.2): dependencies: typescript: 5.9.2 - ts-jest@29.4.1(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.0.5)(babel-jest@30.1.2(@babel/core@7.28.4))(jest-util@30.0.5)(jest@30.1.3(@types/node@22.15.32))(typescript@5.9.2): + ts-jest@29.4.1(@babel/core@7.28.4)(@jest/transform@30.1.2)(@jest/types@30.0.5)(babel-jest@30.1.2(@babel/core@7.28.4))(jest-util@30.0.5)(jest@30.1.3(@types/node@22.18.1))(typescript@5.9.2): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 handlebars: 4.7.8 - jest: 30.1.3(@types/node@22.15.32) + jest: 30.1.3(@types/node@22.18.1) json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 @@ -3666,22 +5834,33 @@ snapshots: babel-jest: 30.1.2(@babel/core@7.28.4) jest-util: 30.0.5 - tslib@2.8.1: - optional: true + tslib@2.8.1: {} + + tty-browserify@0.0.1: {} type-check@0.4.0: dependencies: prelude-ls: 1.2.1 + type-component@0.0.1: {} + type-detect@4.0.8: {} type-fest@0.21.3: {} type-fest@4.41.0: {} + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typedarray@0.0.6: {} + typedoc@0.28.12(typescript@5.9.2): dependencies: - '@gerrit0/mini-shiki': 3.12.0 + '@gerrit0/mini-shiki': 3.12.2 lunr: 2.3.9 markdown-it: 14.1.0 minimatch: 9.0.5 @@ -3706,8 +5885,20 @@ snapshots: uglify-js@3.19.3: optional: true + umd@3.0.3: {} + + undeclared-identifiers@1.1.3: + dependencies: + acorn-node: 1.8.2 + dash-ast: 1.0.0 + get-assigned-identifiers: 1.2.0 + simple-concat: 1.0.1 + xtend: 4.0.2 + undici-types@6.21.0: {} + universalify@2.0.1: {} + unrs-resolver@1.11.1: dependencies: napi-postinstall: 0.3.3 @@ -3738,20 +5929,62 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 + upper-case@1.1.3: {} + uri-js@4.4.1: dependencies: punycode: 2.3.1 + url@0.11.4: + dependencies: + punycode: 1.4.1 + qs: 6.14.0 + + util-deprecate@1.0.2: {} + + util-extend@1.0.3: {} + + util@0.10.4: + dependencies: + inherits: 2.0.3 + + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.2.0 + is-generator-function: 1.1.0 + is-typed-array: 1.1.15 + which-typed-array: 1.1.19 + v8-to-istanbul@9.3.0: dependencies: '@jridgewell/trace-mapping': 0.3.30 '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 + vm-browserify@1.1.2: {} + walker@1.0.8: dependencies: makeerror: 1.0.12 + webidl-conversions@7.0.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + + which-typed-array@1.1.19: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + which@2.0.2: dependencies: isexe: 2.0.0 @@ -3779,6 +6012,8 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 4.1.0 + xtend@4.0.2: {} + y18n@5.0.8: {} yallist@3.1.1: {} diff --git a/src/McRAPTOR.ts b/src/McRAPTOR.ts index 669a5ae..7a0f065 100644 --- a/src/McRAPTOR.ts +++ b/src/McRAPTOR.ts @@ -138,6 +138,7 @@ export default class McRAPTOR Bpi.values().some((jsPi) => (jsPi.compare(jsPt) ?? 1) > 0))) ) this.marked.add(pi); + this.trace(`added ${added}, new sz=${this.bags[this.k].get(pi)!.size}`); // Step 3: populating route bag with previous round & update // Update current route bag with possible new earliest catchable trips thanks to previous round @@ -148,9 +149,13 @@ export default class McRAPTOR): void { + this.trace("fp b sz", this.bags[this.k].get(stopId)!.size); + for (const pJourneyStep of this.bags[this.k].get(stopId)!) { // Prevent chaining transfers if ("transfer" in pJourneyStep) continue; diff --git a/src/base.ts b/src/base.ts index 48b83f8..861afba 100644 --- a/src/base.ts +++ b/src/base.ts @@ -47,11 +47,17 @@ export default class BaseRAPTOR(); + protected runBeginTs = 0; + /** * @description Creates a new RAPTOR instance for a defined network. */ constructor(protected readonly data: IRAPTORData) {} + protected trace(msg: string, ...args: unknown[]) { + console.log(`[${performance.now() - this.runBeginTs}] ${msg}`, ...args); + } + /** * Getter on stops from {@link data} */ @@ -109,6 +115,7 @@ export default class BaseRAPTOR) { + this.trace("begin mark"); Q.clear(); for (const p of this.marked) { const connectedRoutes = this.stops.get(p)!.connectedRoutes; @@ -120,6 +127,7 @@ export default class BaseRAPTOR */ const Q = new Map(); for (this.k = 1; this.k < rounds; this.k++) { + this.trace(`begin round ${this.k}`); + + this.trace(`begin begin round`); this.beginRound(); + this.trace(`end begin round`); this.mark(Q); // Traverse each route - for (const [r, p] of Q) this.traverseRoute(this.routes.get(r)!, p); + this.trace(`begin traverse route`); + for (const [r, p] of Q) { + this.traverseRoute(this.routes.get(r)!, p); + } + this.trace(`end traverse route`); + this.trace(`marked size traverse route ${this.marked.size}`); // Look at foot-paths + this.trace(`begin fp lookup`); if (this.k === 1) // Mark source so foot paths from it are considered in first round this.marked.add(ps); // Copy current state of marked stops + let cnt = 0; for (const p of new Set(this.marked)) { const stop = this.stops.get(p)!; if (stop.transfers(this.runParams.settings.maxTransferLength).next().done ?? true) continue; this.traverseFootPaths(p, stop); + cnt += stop.transfers(this.runParams.settings.maxTransferLength).reduce((acc) => acc + 1, 0); } + this.trace(`end fp lookup`); + this.trace(`scanned fp cnt ${cnt}`); + this.trace(`marked size fp lookup ${this.marked.size}`); + this.trace(`end round ${this.k}`); // Stopping criterion if (this.marked.size === 0) break; } + this.trace("end"); } protected traceBackFromStep(from: JourneyStep, initRound: number): Journey { diff --git a/src/test/index.ts b/src/test/index.ts new file mode 100644 index 0000000..e5cbf6a --- /dev/null +++ b/src/test/index.ts @@ -0,0 +1,821 @@ +import initDB from "./utils/mongoose"; + +// Needed to solve "Reflect.getMetadata is not a function" error of typegoose +import "core-js/features/reflect"; + +import { Override, UnpackRefType } from "@bibm/common/types"; +import { journeyDBFormatter } from "@bibm/compute/jobs/compute"; +import { makeMapId, Providers } from "@bibm/compute/jobs/preCompute/utils"; +import NonScheduledRoutesModelInit, { dbFootPaths } from "@bibm/data/models/Compute/NonScheduledRoutes.model"; +import ResultModelInit, { LocationAddress, LocationTBM, PointType } from "@bibm/data/models/Compute/result.model"; +import { Schedule } from "@bibm/data/models/Compute/types"; +import SNCFScheduledRoutesModelInit, { dbSNCF_ScheduledRoutes } from "@bibm/data/models/SNCF/SNCFScheduledRoutes.model"; +import { dbSNCF_Schedules } from "@bibm/data/models/SNCF/SNCF_schedules.model"; +import SNCFStopsModelInit, { dbSNCF_Stops } from "@bibm/data/models/SNCF/SNCF_stops.model"; +// Those 2 are local because of conflicting Mongoose instances between BIBM and here +// Otherwise, we get NotValidModelError [TypeError]: Expected "getDiscriminatorModelForClass.from" to be a valid mongoose.Model! (got: "function model(doc, fields, skipId) ...") [E205] +import TBMScheduledRoutesModelInit, { dbTBM_ScheduledRoutes } from "./models/TBMScheduledRoutes.model"; +import TBMSchedulesModelInit, { dbTBM_Schedules_rt } from "./models/TBM_schedules.model"; +import TBMStopsModelInit, { dbTBM_Stops } from "@bibm/data/models/TBM/TBM_stops.model"; +import { DocumentType } from "@typegoose/typegoose"; +import minimist from "minimist"; +import { exit } from "process"; +import { inspect } from "util"; +import { + bufferTime, + convertBackJourneyStep, + convertJourneyStep, + Criterion, + footDistance, + InternalTimeInt, + IRAPTORData, + Journey, + McRAPTOR, + McSharedRAPTOR, + measureJourney, + RAPTOR, + RAPTORData, + RAPTORRunSettings, + SharedID, + SharedRAPTOR, + SharedRAPTORData, + sharedTimeIntOrderLow, + sharedTimeScal, + Stop, + successProbaInt, + Time, + TimeInt, + TimeScal, + Timestamp, + Trip, +} from "../"; +import BaseRAPTOR from "../base"; +import { Combinations } from "./utils"; +import { benchmark } from "./utils/benchmark"; + +async function queryData(fpReqLen: number) { + console.debug("Querying data..."); + const sourceDB = await initDB("bibm"); + const computeDB = await initDB("bibm-compute"); + const TBMStopsModel = TBMStopsModelInit(sourceDB); + const SNCFStopsModel = SNCFStopsModelInit(sourceDB); + const TBMSchedulesModel = TBMSchedulesModelInit(sourceDB)[1]; + const TBMScheduledRoutesModel = TBMScheduledRoutesModelInit(sourceDB); + const SNCFScheduledRoutesModel = SNCFScheduledRoutesModelInit(sourceDB); + const NonScheduledRoutesModel = NonScheduledRoutesModelInit(sourceDB); + + const resultModel = ResultModelInit(computeDB); + + /** DB Types */ + + // Stops + // TBM + const dbTBMStopProjection = { _id: 1 } satisfies Partial>; + type TBMStop = Pick; + + // SNCF + const dbSNCFStopProjection = { _id: 1 } satisfies Partial>; + type SNCFStop = Pick; + + // Schedules + const schedulesProjection = { arr_int_hor: 1, dep_int_hor: 1 } satisfies Partial>; + type dbSchedule = Pick; + + // Scheduled Routes + // TBM + const dbTBMSchedulesProjection = { hor_theo: 1 } satisfies Partial>; + const dbTBMScheduledRoutesProjection = { _id: 1, stops: 1, trips: 1 } satisfies Partial>; + type dbTBMScheduledRoute = Pick; + interface TBMScheduledRoutesOverwritten /* extends dbTBM_ScheduledRoutes */ { + _id: UnpackRefType; + stops: UnpackRefType; + trips: { + // Not a Document because of lean + schedules: (Pick & dbSchedule)[]; + }[]; + } + type TBMScheduledRoute = Override; + + // SNCF + const dbSNCFSchedulesProjection = { baseArrival: 1, baseDeparture: 1 } satisfies Partial>; + const dbSNCFScheduledRoutesProjection = { _id: 1, stops: 1, trips: 1 } satisfies Partial>; + type dbSNCFScheduledRoute = Pick; + interface SNCFScheduledRoutesOverwritten /* extends dbSNCF_ScheduledRoutes */ { + stops: UnpackRefType; + trips: { + // Not a Document because of lean + schedules: (Pick & dbSchedule)[]; + }[]; + } + type SNCFScheduledRoute = Omit & SNCFScheduledRoutesOverwritten; + + type ProviderRouteId = TBMScheduledRoute["_id"] | SNCFScheduledRoute["_id"]; + // eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents + type ProviderStopId = TBMStop["_id"] | SNCFStop["_id"]; + + // Non Schedules Routes + const dbNonScheduledRoutesProjection = { from: 1, to: 1, distance: 1 } satisfies Partial>; + type dbNonScheduledRoute = Pick; + + // Virtual IDs (stops routes) management + + const stopIdsMappingF = new Map<`${Providers}-${ProviderStopId}`, number>(); + const stopIdsMappingB = new Map(); + const TBMStopsCount = (await TBMStopsModel.estimatedDocumentCount()) * 1.5; + const SNCFStopsCount = (await SNCFStopsModel.estimatedDocumentCount()) * 1.5; + const stopIdsRanges = { + [Providers.TBM]: [0, TBMStopsCount, -1], + [Providers.SNCF]: [TBMStopsCount + 1, TBMStopsCount + 1 + SNCFStopsCount, -1], + } satisfies Record; + const [mapStopId, unmapStopId] = makeMapId(stopIdsRanges, stopIdsMappingF, stopIdsMappingB); + + const routeIdsMappingF = new Map<`${Providers}-${ProviderRouteId}`, number>(); + const routeIdsMappingB = new Map(); + // Memoizing allows us to only remember backward mapping, forward mapping is stored inside memoize + const TBMSRCount = (await TBMScheduledRoutesModel.estimatedDocumentCount()) * 1.5; + const SNCFSRCount = (await SNCFScheduledRoutesModel.estimatedDocumentCount()) * 1.5; + const routeIdsRanges = { + [Providers.TBM]: [0, TBMSRCount, -1], + [Providers.SNCF]: [TBMSRCount + 1, TBMSRCount + 1 + SNCFSRCount, -1], + } satisfies Record; + const [mapRouteId, unmapRouteId] = makeMapId(routeIdsRanges, routeIdsMappingF, routeIdsMappingB); + + // Non scheduled routes + + // Query must associate (s, from) AND (from, s) forall s in stops ! + const dbNonScheduledRoutes = ( + (await NonScheduledRoutesModel.find>( + { distance: { $lte: fpReqLen } }, + { ...dbNonScheduledRoutesProjection, _id: 0 }, + ) + .lean() + .exec()) as dbNonScheduledRoute[] + ).reduce>[1][number][2]>>((acc, { from, to, distance }) => { + const mappedFrom = mapStopId(parseInt(from.substring(3).split("-")[0]), parseInt(from.split("-")[1])); + const mappedTo = mapStopId(parseInt(to.substring(3).split("-")[0]), parseInt(to.split("-")[1])); + + for (const [from, to] of [ + [mappedFrom, mappedTo], + [mappedTo, mappedFrom], + ]) { + let stopNonScheduledRoutes = acc.get(from); + if (!stopNonScheduledRoutes) { + stopNonScheduledRoutes = []; + acc.set(from, stopNonScheduledRoutes); + } + + stopNonScheduledRoutes.push({ length: distance, to }); + } + + return acc; + }, new Map()); + + // TBM stops & routes + + const dbTBMScheduledRoutes = ( + (await TBMScheduledRoutesModel.find>({}, dbTBMScheduledRoutesProjection) + .populate("trips.schedules", { ...schedulesProjection, ...dbTBMSchedulesProjection, _id: 0, __t: 0 }) + .lean() + .exec()) as TBMScheduledRoute[] + ).map(({ _id, stops, trips }) => ({ + _id, + stops: stops.map((stop) => mapStopId(Providers.TBM, stop)), + trips, + })); + + const TBMStops = dbTBMScheduledRoutes.reduce, undefined>]>>( + (acc, { _id: routeId, stops }) => { + for (const stopId of stops) { + let stop = acc.get(stopId); + if (!stop) { + stop = [[], dbNonScheduledRoutes.get(stopId) ?? []]; + acc.set(stopId, stop); + } + + stop[0].push(mapRouteId(Providers.TBM, routeId)); + } + + return acc; + }, + new Map( + ( + (await TBMStopsModel.find>({ coords: { $not: { $elemMatch: { $eq: Infinity } } } }, dbTBMStopProjection) + .lean() + .exec()) as TBMStop[] + ).map(({ _id }) => { + const mappedId = mapStopId(Providers.TBM, _id); + + return [mappedId, [[], dbNonScheduledRoutes.get(mappedId) ?? []]]; + }), + ), + ); + + // SNCF stops & routes + + const dbSNCFScheduledRoutes = ( + (await SNCFScheduledRoutesModel.find>({}, dbSNCFScheduledRoutesProjection) + .populate("trips.schedules", { ...schedulesProjection, ...dbSNCFSchedulesProjection, _id: 0 }) + .lean() + .exec()) as SNCFScheduledRoute[] + ).map(({ _id, stops, trips }) => ({ + _id, + stops: stops.map((stop) => mapStopId(Providers.SNCF, stop)), + trips, + })); + + const SNCFStops = dbSNCFScheduledRoutes.reduce, undefined>]>>( + (acc, { _id: routeId, stops }) => { + for (const stopId of stops) { + let stop = acc.get(stopId); + if (!stop) { + stop = [[], dbNonScheduledRoutes.get(stopId) ?? []]; + acc.set(stopId, stop); + } + + stop[0].push(mapRouteId(Providers.SNCF, routeId)); + } + + return acc; + }, + new Map( + ( + (await SNCFStopsModel.find>({ coords: { $not: { $elemMatch: { $eq: Infinity } } } }, dbSNCFStopProjection) + .lean() + .exec()) as SNCFStop[] + ).map(({ _id }) => { + const mappedId = mapStopId(Providers.SNCF, _id); + + return [mappedId, [[], dbNonScheduledRoutes.get(mappedId) ?? []]]; + }), + ), + ); + return { + TBMStops, + SNCFStops, + dbTBMScheduledRoutes, + dbSNCFScheduledRoutes, + dbNonScheduledRoutes, + TBMSchedulesModel, + resultModel, + mapStopId, + unmapStopId, + mapRouteId, + unmapRouteId, + }; +} + +function getArgsOptNumber(args: ReturnType, opt: string): number | null { + if (opt in args) { + if (typeof args[opt] === "number") return args[opt]; + + console.warn(`Supplied "${opt}" was not of type number`, args[opt]); + } + + return null; +} + +type DataType = "scalar" | "interval"; + +function computeRAPTORData( + { TBMStops, SNCFStops, dbTBMScheduledRoutes, dbSNCFScheduledRoutes, mapRouteId }: Awaited>, + dataType: DataType, + /** In ms, [neg, pos] */ + delay: [number, number] | null, +) { + const scheduleMapperInt = + (getBaseArr: (schedule: T) => Timestamp, getBaseDep: (schedule: T) => Timestamp) => + (schedule: T): NonNullable["at"]>> => { + if (delay) + return [ + [getBaseArr(schedule) - delay[0], getBaseArr(schedule) + delay[1]] satisfies InternalTimeInt, + [getBaseDep(schedule) - delay[0], getBaseDep(schedule) + delay[1]] satisfies InternalTimeInt, + ]; + else { + return [ + schedule.arr_int_hor.map((date) => date.getTime()) as [number, number], + schedule.dep_int_hor.map((date) => date.getTime()) as [number, number], + ]; + } + }; + + return [ + dataType === "scalar" ? TimeScal : TimeInt, + [ + ...TBMStops.entries().map( + ([id, [connectedRoutes, nonScheduledRoutes]]) => [id, connectedRoutes, nonScheduledRoutes] satisfies [unknown, unknown, unknown], + ), + ...SNCFStops.entries().map( + ([id, [connectedRoutes, nonScheduledRoutes]]) => [id, connectedRoutes, nonScheduledRoutes] satisfies [unknown, unknown, unknown], + ), + ], + [ + ...dbTBMScheduledRoutes.map( + ({ _id, stops, trips }) => + [ + // Don't forget to finally map route ID! + mapRouteId(Providers.TBM, _id), + stops, + trips.map(({ schedules }) => + // Make schedules intervals + schedules.map["at"]>>>( + dataType === "interval" + ? scheduleMapperInt( + (schedule) => schedule.hor_theo.getTime(), + (schedule) => schedule.hor_theo.getTime(), + ) + : (schedule) => [schedule.hor_theo.getTime(), schedule.hor_theo.getTime()] as [number, number], + ), + ), + ] satisfies [unknown, unknown, unknown], + ), + ...dbSNCFScheduledRoutes.map( + ({ _id, stops, trips }) => + [ + // Don't forget to finally map route ID! + mapRouteId(Providers.SNCF, _id), + stops, + trips.map(({ schedules }) => + schedules.map["at"]>>>( + dataType === "interval" + ? scheduleMapperInt( + (schedule) => schedule.baseArrival.getTime(), + (schedule) => schedule.baseDeparture.getTime(), + ) + : (schedule) => [schedule.baseArrival.getTime(), schedule.baseDeparture.getTime()] as [number, number], + ), + ), + ] satisfies [unknown, unknown, unknown], + ), + ], + ] as ConstructorParameters>; +} + +function computeSharedRAPTORData([_, stops, routes]: Awaited>, dataType: DataType) { + return [dataType === "scalar" ? sharedTimeScal : sharedTimeIntOrderLow, stops, routes] as Parameters< + typeof SharedRAPTORData.makeFromRawData + >; +} + +function createRAPTOR(data: ConstructorParameters>) { + const RAPTORDataInst = new RAPTORData(...data); + return [RAPTORDataInst, new RAPTOR(RAPTORDataInst)] as const; +} + +function createSharedRAPTOR(data: Parameters>) { + const SharedRAPTORDataInst = SharedRAPTORData.makeFromRawData(...data); + return [SharedRAPTORDataInst, new SharedRAPTOR(SharedRAPTORDataInst)] as const; +} + +function createMcRAPTOR( + data: ConstructorParameters>, + criteria: ConstructorParameters>[1], +) { + const RAPTORDataInst = new RAPTORData(...data); + return [RAPTORDataInst, new McRAPTOR(RAPTORDataInst, criteria)] as const; +} + +function createMcSharedRAPTOR( + data: Parameters>, + criteria: ConstructorParameters>[1], +) { + const SharedRAPTORDataInst = SharedRAPTORData.makeFromRawData(...data); + return [SharedRAPTORDataInst, new McSharedRAPTOR(SharedRAPTORDataInst, criteria)] as const; +} + +type InstanceType = "RAPTOR" | "SharedRAPTOR" | "McRAPTOR" | "McSharedRAPTOR"; + +function postTreatment( + postCriteria: Criterion[], + data: IRAPTORData, + instanceType: InstanceType, + results: ReturnType["getBestJourneys"]>, + pt: SharedID, +) { + const timeType = data.timeType; + + for (const postCriterion of postCriteria) { + // Add success proba as post treatment + results = results.map((journeys) => + journeys.map((journey) => { + const measured = measureJourney( + postCriterion, + timeType, + (instanceType === "McSharedRAPTOR" + ? journey.map((js) => convertJourneyStep(data as SharedRAPTORData)(js)) + : journey) as unknown as Journey, + pt, + ); + + return instanceType === "McSharedRAPTOR" + ? measured.map((js) => convertBackJourneyStep(data as SharedRAPTORData)(js)) + : measured; + }), + ) as unknown as typeof results; + } + + return results; +} + +async function insertResults( + resultModel: Awaited>["resultModel"], + unmapStopId: Awaited>["unmapStopId"], + unmapRouteId: Awaited>["unmapRouteId"], + timeType: Time, + from: [mappedId: number, LocationAddress | LocationTBM], + to: [mappedId: number, LocationAddress | LocationTBM], + departureTime: TimeVal, + settings: RAPTORRunSettings, + results: ReturnType["getBestJourneys"]>, +) { + if (!results.length) throw new Error("No journey found"); + + const { _id } = await resultModel.create({ + from, + to, + departureTime: typeof departureTime !== "number" ? departureTime[0] : departureTime, + journeys: results + .flat() + // Sort by arrival time + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + .sort((a, b) => timeType.strict.order(a.at(-1)!.label.time, b.at(-1)!.label.time)) + .map((journey) => + journeyDBFormatter( + [from[0], from[1].id as UnpackRefType<(typeof from)[1]["id"]>], + [to[0], to[1].id as UnpackRefType<(typeof from)[1]["id"]>], + unmapStopId, + unmapRouteId, + // @ts-expect-error Giving Timestamp | InternalTimeInt as TimeVal instead of InternalTimeInt but it's safe, just copying time field + // It will try to write a Timestamp instead of a InternalTimeInt, so model validation should fail + journey, + ), + ), + settings, + }); + + return _id; +} + +function man() { + console.log(` +Command-line interface: + h, help, -h, --h, --help: see this message + --fp-req-len=: maximum foot paths' length to retrieve and store un RAPTOR data + --fp-run-len=: maximum foot paths' length to consider during itineraries search + --rounds=: (max) number of RAPTOR rounds to perform + (-d[ ] | --d=): time data type, scalar or interval + --delay-pos=: positive delay (in sec), interval time only + --delay-neg=: negative delay (in sec), interval time only + (-i[ ] | --i=): instance type, RAPTOR or SharedRAPTOR or MultiCriteriaRAPTOR or MultiCriteriaSharedRAPTOR + --shared-secure: with a Shared instance type, check all RAPTOR data calls + --createTimes=: number of times to run the instance creation step + --runTimes=: number of times to run the itinerary search step + --getResTimes=: number of times to run the results retrieval step + --fd, --bt, --spi: add criterion to a MultiCriteria instance, foot distance or buffer time or success probability (interval time) + --fd=post, --bt=post, --spi=post: add post-criterion (measurement) to a MultiCriteria instance, foot distance or buffer time or success probability (interval time) + --save: save results in database + --ps=: source stop in source database for the itinerary query + --pt=: target stop in source database for the itinerary query + --ota: make OTA (One-To-All) runs, ignores pt +`); +} + +// Main IIFE test function +(async () => { + // Setup params from command line + const args = minimist(process.argv); + console.debug(`Using args`, args); + + if (("h" in args && args.h === true) || ("help" in args && args.help === true) || args._.includes("h") || args._.includes("help")) { + man(); + + return; + } + + const fpReqLen = getArgsOptNumber(args, "fp-req-len") ?? 3_000; + console.debug(`Foot paths query max len`, fpReqLen); + const fpRunLen = getArgsOptNumber(args, "fp-run-len") ?? 2_000; + console.debug(`Foot paths run max len`, fpRunLen); + + const maxRounds = getArgsOptNumber(args, "rounds") ?? undefined; + console.debug(`Performing maximal rounds of`, maxRounds); + + let dataType: DataType; + if ("d" in args) { + switch ((args.d as string).toLowerCase()) { + case "scal": + dataType = "scalar"; + break; + + case "int": + dataType = "interval"; + break; + + default: + throw new Error(`Unexpected data type "${args.d}"`); + } + } else dataType = "interval"; + console.debug("Using data type", dataType); + + // Delay + + const delayPos = getArgsOptNumber(args, "delay-pos"); + if (delayPos !== null && dataType === "scalar" && delayPos > 0) + console.warn(`Ignoring positive delay of ${delayPos}s because data type is ${dataType}`); + + const delayNeg = getArgsOptNumber(args, "delay-neg"); + if (delayNeg !== null && dataType === "scalar" && delayNeg > 0) + console.warn(`Ignoring negative delay of ${delayNeg}s because data type is ${dataType}`); + + /** [neg, pos] */ + let delay: [number, number] | null = null; + if (delayNeg !== null || delayPos !== null) delay = [delayNeg ?? 0, delayPos ?? 0]; + + if (dataType !== "scalar") console.debug(delay ? `Using delay of -${delay[0]}s, ${delay[1]}s` : `Using natural delay`); + + let instanceType: InstanceType; + if ("i" in args) { + switch ((args.i as string).toLowerCase()) { + case "r": + instanceType = "RAPTOR"; + break; + + case "sr": + instanceType = "SharedRAPTOR"; + break; + + case "mcr": + instanceType = "McRAPTOR"; + break; + + case "mcsr": + instanceType = "McSharedRAPTOR"; + break; + + default: + throw new Error(`Unexpected instance type "${args.i}"`); + } + } else instanceType = "McSharedRAPTOR"; + console.debug("Using instance type", instanceType); + + let sharedSecure = false; + if ("shared-secure" in args) { + if (instanceType !== "SharedRAPTOR" && instanceType !== "McSharedRAPTOR") + console.warn("Ignoring shared secure because instance type isn't shared"); + else if (args["shared-secure"]) sharedSecure = true; + } + if (instanceType === "SharedRAPTOR" || instanceType === "McSharedRAPTOR") console.debug(`Shared secure`, sharedSecure); + + const createTimes = getArgsOptNumber(args, "createTimes") ?? 1; + const runTimes = getArgsOptNumber(args, "runTimes") ?? 1; + const getResTimes = getArgsOptNumber(args, "getResTimes") ?? 1; + + const criteria = [] as Combinations<[typeof footDistance, typeof bufferTime, typeof successProbaInt]>; + const postCriteria: (typeof footDistance | typeof bufferTime | typeof successProbaInt)[] = []; + if ("fd" in args) { + if (args.fd === true) (criteria as [typeof footDistance]).push(footDistance); + else if (args.fd === "post") postCriteria.push(footDistance); + } + if ("bt" in args) { + if (args.bt === true) (criteria as [typeof bufferTime]).push(bufferTime); + else if (args.bt === "post") postCriteria.push(bufferTime); + } + if ("spi" in args) { + if (dataType !== "interval") console.warn(`Ignoring "${successProbaInt.name}" criterion because data type isn't interval`); + else { + if (args.spi === true) (criteria as [typeof successProbaInt]).push(successProbaInt); + else if (args.spi === "post") postCriteria.push(successProbaInt); + } + } + + console.debug( + "Using criteria", + criteria.map((c) => c.name), + ); + console.debug( + "Using post-criteria (measurement)", + postCriteria.map((c) => c.name), + ); + if (criteria.length && instanceType !== "McRAPTOR" && instanceType !== "McSharedRAPTOR") + console.warn("Got some criteria but instance type is uni-criteria."); + + const saveResults = "save" in args && args.save === true ? true : false; + console.debug(`Saving results`, saveResults); + + const b1 = await benchmark(queryData, [fpReqLen]); + const queriedData = b1.lastReturn; + if (!queriedData) throw new Error("No queried data"); + + // Setup source & destination + let ps: number; + let from: LocationAddress | LocationTBM; + + const psOpt = getArgsOptNumber(args, "ps"); + if (psOpt === null) { + ps = queriedData.mapStopId(Providers.TBM, 974); // Barrière d'Ornano + from = { type: PointType.Address, id: 174287 }; + } else { + ps = queriedData.mapStopId(Providers.TBM, psOpt); + from = { type: PointType.TBMStop, id: ps }; + } + // Fake stop ID, foot proxy to ps + const psRawId = 1_000_000; + let psId: number | SharedID = psRawId; + + const OTA = args.ota === true ? true : false; + console.debug("OTA mode set to", OTA); + + const pt = OTA + ? null + : queriedData.mapStopId( + Providers.TBM, + getArgsOptNumber(args, "pt") ?? + // Béthanie + 3846, + ); + + // Compute RAPTOR data + + const distances: Record = { + // Need the true ps + [ps]: 100, + }; + + const b2 = await benchmark(computeRAPTORData, [queriedData, dataType, delay]); + const rawRAPTORData = b2.lastReturn; + if (!rawRAPTORData) throw new Error("No raw RAPTOR data"); + + let rawSharedRAPTORData: Awaited>; + + if (instanceType === "SharedRAPTOR" || instanceType === "McSharedRAPTOR") { + // Shared-specific RAPTOR data computation + + const b3 = await benchmark(computeSharedRAPTORData, [rawRAPTORData, dataType]); + if (!b3.lastReturn) throw new Error("No raw Shared RAPTOR data"); + rawSharedRAPTORData = b3.lastReturn; + + psId = SharedRAPTORData.serializeId(psRawId); + } + + // Create RAPTOR + + type CA = Combinations<[[number, "footDistance"], [number, "bufferTime"], [number, "successProbaInt"]]>; + + const b4 = await (instanceType === "RAPTOR" + ? benchmark(createRAPTOR, [rawRAPTORData], undefined, createTimes) + : instanceType === "SharedRAPTOR" + ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + benchmark(createSharedRAPTOR, [rawSharedRAPTORData!], undefined, createTimes) + : instanceType === "McRAPTOR" + ? benchmark( + createMcRAPTOR, + [rawRAPTORData, criteria as Parameters>[1]], + undefined, + createTimes, + ) + : benchmark( + createMcSharedRAPTOR, + [ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + rawSharedRAPTORData!, + criteria as Parameters>[1], + ], + undefined, + createTimes, + )); + if (!b4.lastReturn) throw new Error("No RAPTOR instance"); + const [RAPTORDataInst, RAPTORInstance] = b4.lastReturn as readonly [ + Omit, "attachStops"> & { + attachStops: SharedRAPTORData["attachStops"]; + }, + BaseRAPTOR, + ]; + + if (sharedSecure) (RAPTORDataInst as SharedRAPTORData).secure = true; + + // Attach stops + + const attachStops = new Map>>(); + + attachStops.set(psRawId, [ + psRawId, + [], + Object.keys(distances).map((k) => { + const sId = parseInt(k); + + return { to: sId, length: distances[sId] }; + }), + ]); + + Object.keys(distances).forEach((k) => { + const sId = parseInt(k); + + attachStops.set(sId, [sId, [], [{ to: psRawId, length: distances[sId] }]]); + }); + + RAPTORDataInst.attachStops(Array.from(attachStops.values())); + + // Run params + + // https://www.mongodb.com/docs/manual/core/aggregation-pipeline-optimization/#-sort----limit-coalescence + const minSchedule = ( + await queriedData.TBMSchedulesModel.find({ hor_theo: { $gt: new Date(0) } }) + .sort({ hor_theo: 1 }) + .limit(1) + ).at(0)?.hor_theo; + const maxSchedule = (await queriedData.TBMSchedulesModel.find().sort({ hor_theo: -1 }).limit(1)).at(0)?.hor_theo; + if (!minSchedule || !maxSchedule) throw new Error("Could not find latest & oldest TBM schedules"); + + const meanSchedule = new Date(Math.round((minSchedule.getTime() + maxSchedule.getTime()) / 2)).getTime(); + const departureTime = dataType === "interval" ? ([meanSchedule, meanSchedule] satisfies [unknown, unknown]) : meanSchedule; + + const settings: RAPTORRunSettings = { walkSpeed: 1.5, maxTransferLength: fpRunLen }; + + // Run + + function runRAPTOR() { + RAPTORInstance.run(psId, pt, departureTime, settings, maxRounds); + } + console.log( + `Running with: ps=${psId}, pt=${pt}, departure time=${new Date(typeof departureTime === "number" ? departureTime : departureTime[0]).toLocaleString()}, settings=${JSON.stringify(settings)}`, + ); + await benchmark(runRAPTOR, [], undefined, runTimes); + + // Get results + + function resultRAPTOR() { + return OTA + ? new Map(Array.from(RAPTORDataInst.stops).map(([_, { id }]) => [id, RAPTORInstance.getBestJourneys(id)])) + : // OTA is false <=> pt is number + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + RAPTORInstance.getBestJourneys(pt!); + } + const b6 = await benchmark(resultRAPTOR, [], undefined, getResTimes); + if (!b6.lastReturn) throw new Error(`No best journeys`); + console.debug("Best journeys", inspect(b6.lastReturn, false, 6)); + + // Allow post-treating in OTA mode too + function postTreatmentAdapter() { + if (b6.lastReturn instanceof Array) + return postTreatment( + postCriteria as Criterion[], + RAPTORDataInst, + instanceType, + b6.lastReturn, + // If best journeys is an array, there was a target + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + pt!, + ); + + if (b6.lastReturn instanceof Map) { + return new Map( + b6.lastReturn + .entries() + .map(([stopId, bestJourneys]) => [ + stopId, + postTreatment( + postCriteria as Criterion[], + RAPTORDataInst, + instanceType, + bestJourneys, + stopId, + ), + ]), + ); + } + + // Should never happen + return []; + } + const b7 = await benchmark(postTreatmentAdapter, []); + if (!b7.lastReturn) throw new Error(`No post treatment`); + console.debug("Post treatment", inspect(b7.lastReturn, false, 6)); + + if (saveResults) { + // Save results + + if (OTA) { + console.warn("Saving results is not supported in OTA mode"); + return; + } + + const b8 = await benchmark(insertResults, [ + queriedData.resultModel, + queriedData.unmapStopId, + queriedData.unmapRouteId, + RAPTORDataInst.timeType, + [psRawId, from], + // OTA === false <=> pt is number + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + [pt!, { type: PointType.TBMStop, id: queriedData.unmapStopId(pt!)![0] }], + departureTime, + settings, + b7.lastReturn as ReturnType>, + ]); + console.log("Saved result id", b8.lastReturn); + } +})() + .then(() => { + console.log("Main ended"); + exit(0); + }) + .catch(console.error); diff --git a/src/test/lintScheduledRoutes.ts b/src/test/lintScheduledRoutes.ts new file mode 100644 index 0000000..d48c270 --- /dev/null +++ b/src/test/lintScheduledRoutes.ts @@ -0,0 +1,62 @@ +import initDB from "./utils/mongoose"; + +// Needed to solve "Reflect.getMetadata is not a function" error of typegoose +import "core-js/features/reflect"; + +import TBMScheduledRoutesModelInit, { dbTBM_ScheduledRoutes } from "@bibm/data/models/TBM/TBMScheduledRoutes.model"; +import TBMLinesRoutesModelInit from "@bibm/data/models/TBM/TBM_lines.model"; +import TBMLinesModelInit from "@bibm/data/models/TBM/TBM_lines_routes.model"; + +import { UnpackRefs } from "./utils"; +import { benchmark } from "./utils/benchmark"; + +(async () => { + async function queryData() { + console.debug("Querying data..."); + const sourceDB = await initDB("bibm"); + + TBMLinesRoutesModelInit(sourceDB); + const TBMLinesRoutesModel = TBMLinesModelInit(sourceDB); + + const dbScheduledRoutesProjection = { _id: 1, stops: 1, trips: 1 } satisfies Partial>; + type dbScheduledRoute = Pick; + type ScheduledRoutesOverwritten = UnpackRefs; + type ScheduledRoute = Omit & ScheduledRoutesOverwritten; + const TBMScheduledRoutesModel = TBMScheduledRoutesModelInit(sourceDB); + + return { + dbScheduledRoutes: TBMScheduledRoutesModel.find({}, dbScheduledRoutesProjection).populate("trips.schedules").lean().cursor(), + TBMScheduledRoutesModel, + TBMLinesRoutesModel, + }; + } + + async function lintScheduledRoutes({ dbScheduledRoutes, TBMScheduledRoutesModel, TBMLinesRoutesModel }: Awaited>) { + // Lint schedules routes + console.debug("Linting..."); + + for await (const scheduledRoute of dbScheduledRoutes) + for (const [tripIndex, trip] of scheduledRoute.trips.entries()) + for (const [i, schedule] of trip.schedules.entries()) + if (typeof schedule !== "object" || (schedule.rs_sv_arret_p !== Infinity && schedule.rs_sv_arret_p !== scheduledRoute.stops[i])) { + const scheduledRoutePop = await TBMScheduledRoutesModel.populate(scheduledRoute, { path: "_id", options: { lean: true } }); + scheduledRoutePop._id = await TBMLinesRoutesModel.populate(scheduledRoutePop._id, { path: "rs_sv_ligne_a", options: { lean: true } }); + + console.log( + `Route ${typeof scheduledRoutePop._id === "object" ? `${typeof scheduledRoutePop._id.rs_sv_ligne_a === "object" ? scheduledRoutePop._id.rs_sv_ligne_a.libelle : scheduledRoutePop._id.rs_sv_ligne_a} ${scheduledRoutePop._id.libelle} (${scheduledRoutePop._id._id})` : scheduledRoutePop._id}, trip idx ${tripIndex} (${trip.tripId}): at idx ${i}, schedule's stop ${typeof schedule === "object" ? `${schedule.rs_sv_arret_p as number} / ${schedule.hor_theo.toLocaleString()}` : `${schedule} [NOT POPULATED]`} !== stop ${scheduledRoute.stops[i]}`, + ); + } + } + + const b1 = await benchmark(queryData, []); + if (!b1.lastReturn) throw new Error("No queried data"); + + await benchmark(lintScheduledRoutes, [b1.lastReturn]); + + console.debug("Done."); +})() + .then(() => process.exit(0)) + .catch((err: unknown) => { + console.error(err); + process.exit(1); + }); diff --git a/src/test/models/TBMScheduledRoutes.model.ts b/src/test/models/TBMScheduledRoutes.model.ts new file mode 100644 index 0000000..5885625 --- /dev/null +++ b/src/test/models/TBMScheduledRoutes.model.ts @@ -0,0 +1,45 @@ +// TBMScheduledRoutes-model.js - A mongoose model +// +// See http://mongoosejs.com/docs/models.html + +import { TBMEndpoints } from "@bibm/data/models/TBM/index"; +import { dbTBM_Lines_routes } from "@bibm/data/models/TBM/TBM_lines_routes.model"; +import { dbTBM_Stops } from "@bibm/data/models/TBM/TBM_stops.model"; +import { deleteModelWithClass, getModelForClass, prop, type Ref, type ReturnModelType } from "@typegoose/typegoose"; +import { TimeStamps } from "@typegoose/typegoose/lib/defaultClasses"; +import { modelOptions } from "@typegoose/typegoose/lib/modelOptions"; +import { Connection } from "mongoose"; +import { dbTBM_Schedules_rt, default as TBMSchedulesRtInit } from "./TBM_schedules.model"; + +@modelOptions({ schemaOptions: { _id: false } }) +export class TripOfScheduledRoute { + @prop({ required: true }) + public tripId!: number; + + @prop({ required: true, ref: () => dbTBM_Schedules_rt, type: () => Number }) + public schedules!: Ref[]; +} + +@modelOptions({ options: { customName: TBMEndpoints.ScheduledRoutes } }) +export class dbTBM_ScheduledRoutes extends TimeStamps { + @prop({ required: true, ref: () => dbTBM_Lines_routes, type: () => Number }) + public _id!: Ref; + + @prop({ required: true, type: () => TripOfScheduledRoute }) + public trips!: TripOfScheduledRoute[]; + + @prop({ required: true, ref: () => dbTBM_Stops, type: () => Number }) + public stops!: Ref[]; +} + +export default function init(db: Connection): ReturnModelType { + TBMSchedulesRtInit(db); + + deleteModelWithClass(dbTBM_ScheduledRoutes); + + return getModelForClass(dbTBM_ScheduledRoutes, { + existingConnection: db, + }); +} + +export type dbTBM_ScheduledRoutesModel = ReturnType; diff --git a/src/test/models/TBM_schedules.model.ts b/src/test/models/TBM_schedules.model.ts new file mode 100644 index 0000000..06fb15f --- /dev/null +++ b/src/test/models/TBM_schedules.model.ts @@ -0,0 +1,82 @@ +// tbm_schedules-model.js - A mongoose model +// +// See http://mongoosejs.com/docs/models.html + +export enum RtScheduleState { + Annule = "ANNULE", + Non_realise = "NON_REALISE", + Realise = "REALISE", + Devie = "DEVIE", +} + +export enum RtScheduleType { + Regulier = "REGULIER", + Deviation = "DEVIATION", +} + +import { Schedule } from "@bibm/data/models/Compute/types"; +import { TBMEndpoints } from "@bibm/data/models/TBM/index"; +import { dbTBM_Stops } from "@bibm/data/models/TBM/TBM_stops.model"; +import { dbTBM_Trips } from "@bibm/data/models/TBM/TBM_trips.model"; +import { + deleteModelWithClass, + getDiscriminatorModelForClass, + getModelForClass, + index, + prop, + type Ref, + type ReturnModelType, +} from "@typegoose/typegoose"; +import { TimeStamps } from "@typegoose/typegoose/lib/defaultClasses"; +import { modelOptions } from "@typegoose/typegoose/lib/modelOptions"; +import { Connection } from "mongoose"; + +@index({ _id: 1, realtime: 1 }, { unique: true }) +@modelOptions({ options: { customName: TBMEndpoints.Schedules } }) +export class dbTBM_Schedules extends TimeStamps { + @prop({ required: true }) + public _id!: number; + + @prop({ required: true }) + public hor_theo!: Date; + + @prop({ required: true }) + public realtime!: boolean; + + @prop({ required: true, ref: () => dbTBM_Stops, type: () => Number }) + public rs_sv_arret_p!: Ref; + + @prop({ required: true, ref: () => dbTBM_Trips, type: () => Number, index: true }) + public rs_sv_cours_a!: Ref; +} + +@modelOptions({ options: { customName: TBMEndpoints.Schedules_rt } }) +export class dbTBM_Schedules_rt extends dbTBM_Schedules implements Schedule { + @prop({ required: true }) + public hor_app!: Date; + + @prop({ required: true }) + public hor_estime!: Date; + + @prop({ required: true }) + public arr_int_hor!: [Date, Date]; + + @prop({ required: true }) + public dep_int_hor!: [Date, Date]; + + @prop({ required: true, enum: RtScheduleState }) + public etat!: RtScheduleState; + + @prop({ required: true, enum: RtScheduleType }) + public type!: RtScheduleType; +} + +export default function init(db: Connection): readonly [ReturnModelType, ReturnModelType] { + deleteModelWithClass(dbTBM_Schedules); + const dbTBM_SchedulesModel = getModelForClass(dbTBM_Schedules, { existingConnection: db }); + + return [dbTBM_SchedulesModel, getDiscriminatorModelForClass(dbTBM_SchedulesModel, dbTBM_Schedules_rt)] as const; +} + +export type dbTBM_SchedulesModel = ReturnType[0]; +export type dbTBM_Schedules_rtModel = ReturnType[1]; diff --git a/src/test/utils/Link.ts b/src/test/utils/Link.ts new file mode 100644 index 0000000..d992d24 --- /dev/null +++ b/src/test/utils/Link.ts @@ -0,0 +1,123 @@ +const emptyLink = Symbol("emptyLink"); + +export type LinkOrEmpty = Link | typeof emptyLink; + +/** + * @description Class of chained array + */ +export class Link { + static emptyLink: typeof emptyLink = emptyLink; + + private _value: Type; + private _next: LinkOrEmpty; + + /** + * @description Construction of the first LinkOrEmpty + * @param val Any type of data to LinkOrEmpty + */ + constructor(val: Type, next: LinkOrEmpty = Link.emptyLink) { + this._value = val; + this._next = next; + } + + static isLink(l: LinkOrEmpty): l is Link { + return l instanceof Link; + } + + /** + * @description Get the value of this LinkOrEmpty + */ + get value(): Type { + return this._value; + } + + set value(v: Type) { + this._value = v; + } + + /** + * @description Get the next LinkOrEmpty of this chained array + */ + get next(): LinkOrEmpty { + return this._next; + } + + set next(v: LinkOrEmpty) { + if (!Link.isLink(v) && v != Link.emptyLink) throw new Error("Next value of the LinkOrEmpty can only be a Link or an empty Link."); + this._next = v; + } + + /** + * @description Get depth of the LinkOrEmpty {Number} + */ + get depth(): number { + if (!Link.isLink(this._next)) return 1; + return 1 + this._next.depth; + } + + toArrayRec(): Type[] { + if (!Link.isLink(this.next)) return [this.value]; + const next = this.next.toArrayRec(); + return [this.value, ...next]; + } + + toArray(): Type[] { + return Array.from(this); + } + + toArrayRevertedRec(): Type[] { + if (!(this._next instanceof Link)) return [this.value]; + const next = this._next.toArray(); + return [...next, this.value]; + } + + toArrayReverted(): Type[] { + return this.toArray().reverse(); + } + + *[Symbol.iterator]() { + // eslint-disable-next-line @typescript-eslint/no-this-alias + let el: LinkOrEmpty = this; + while (Link.isLink(el)) { + yield el.value; + el = el._next; + } + } + + /** + * @description Get the n(th) element of the LinkOrEmpty + * @param {Number} n Index of the element to access to + */ + get_rec(n: number): Type { + if (n < 0) throw new Error("Invalid index"); + if (n == 0) return this.value; + if (this._next instanceof Link) return this._next.get(n - 1); + else throw new Error("Index out of range"); + } + + /** + * @description Get the n(th) element of the LinkOrEmpty + * @param {Number} n Index of the element to access to + */ + get(n: number): Type { + if (n < 0) throw new Error("Invalid index"); + let i = 0; + for (const el of this) { + if (n === i) return el; + i++; + } + throw new Error("Index out of range"); + } + + /** + * @description Create chained array from array + * @param {Array} a The array to convert into chained array + */ + static fromArray(a: T[] = []): LinkOrEmpty { + let m: LinkOrEmpty = Link.emptyLink; + for (let i = a.length - 1; i >= 0; i--) { + m = new this(a[i], m); + } + return m; + } +} diff --git a/src/test/utils/Queue.ts b/src/test/utils/Queue.ts new file mode 100644 index 0000000..df2cc4a --- /dev/null +++ b/src/test/utils/Queue.ts @@ -0,0 +1,44 @@ +import { LinkOrEmpty, Link } from "./Link"; + +export class Queue { + private front: LinkOrEmpty; + private back: LinkOrEmpty; + private _size: number; + + constructor() { + this.front = Link.emptyLink; + this.back = Link.emptyLink; + this._size = 0; + } + + get size(): number { + return this._size; + } + + enqueue(val: Type): this { + if (this.size === 0) { + this.front = new Link(val); + this.back = this.front; + } else { + (this.back as Link).next = new Link(val); + this.back = (this.back as Link).next; + } + this._size++; + return this; + } + + dequeue(): Type { + if (!this.size) throw new Error("Queue is empty."); + const v = (this.front as Link).value; + this.front = (this.front as Link).next; + this._size--; + return v; + } + + toArray(): Type[] { + if (!this.size) return []; + return (this.front as Link).toArray(); + } +} + +export type unpackQueue = Q extends Queue ? T : never; diff --git a/src/test/utils/TypedEmitter.ts b/src/test/utils/TypedEmitter.ts new file mode 100644 index 0000000..c603395 --- /dev/null +++ b/src/test/utils/TypedEmitter.ts @@ -0,0 +1,13 @@ +import { EventEmitter } from "events"; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type EmittedEvents = Record any>; + +export declare interface TypedEventEmitter { + on(event: Exclude, listener: Events[E]): this; + + emit(event: Exclude, ...args: Parameters): boolean; +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-unsafe-declaration-merging +export class TypedEventEmitter extends EventEmitter {} diff --git a/src/test/utils/Workers.ts b/src/test/utils/Workers.ts new file mode 100644 index 0000000..a7bbd77 --- /dev/null +++ b/src/test/utils/Workers.ts @@ -0,0 +1,162 @@ +import { Worker } from "worker_threads"; +import { Duration } from "./benchmark"; +import { Queue, unpackQueue } from "./Queue"; +import { TypedEventEmitter } from "./TypedEmitter"; +import { ResolveCb, RejectCb, Deferred } from "."; +const nsPerMs = BigInt(1e6); + +enum Status { + Idle, + Busy, +} + +interface poolWorker { + id: number; + status: Status; + worker: Worker; + work: queuedJob | null; +} + +type queuedJob = [T, ResolveCb, RejectCb]; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type workerPoolEvents = { + queuedJob: (queueSize: number) => void; + runningJob: (job: queuedJob) => void; + jobEnded: (result: R | object) => void; +}; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export class WorkerPool unknown, F extends (...args: any[]) => unknown> extends TypedEventEmitter< + workerPoolEvents, Awaited>> +> { + readonly pool: poolWorker, Awaited>>[]; + readonly queue: Queue, Awaited>>>; + + constructor( + readonly script: string, + readonly size: number, + initData?: Parameters[0], + readonly debug = false, + ) { + super(); + this.pool = new Array<(typeof this.pool)[number]>(this.size); + this.queue = new Queue(); + + for (let i = 0; i < this.size; i++) { + this.pool[i] = { + id: i, + status: Status.Idle, + worker: new Worker(this.script), + work: null, + }; + + if (initData) { + const worker = this.pool[i]; + worker.status = Status.Busy; + + if (this.debug) console.log(`Initializing worker ${worker.id}`); + + worker.worker.once("message", (v) => { + if (v === true) { + worker.status = Status.Idle; + + if (this.debug) console.log(`Initialized worker ${worker.id}`); + + this.runCallback(); + } + }); + worker.worker.once("error", console.error); + + worker.worker.postMessage({ ...initData }); + } + } + } + + run(data: Parameters, res: ResolveCb>>, rej: RejectCb): void; + run(data: Parameters): Promise>>; + async run(data: Parameters, res?: ResolveCb>>, rej?: RejectCb) { + let def: Deferred>> | null = null; + let resolve: ResolveCb>>; + let reject: RejectCb; + + if (!res || !rej) { + def = new Deferred>>(); + resolve = def.resolve; + reject = def.reject; + } else { + resolve = res; + reject = rej; + } + + const job: unpackQueue = [data, resolve, reject]; + + const worker = this.getIdleWorker(); + if (!worker) { + this.queue.enqueue(job); + if (this.debug) console.log(`Delayed, queued (${this.queue.size})`); + this.emit("queuedJob", this.queue.size); + return def?.promise; + } + + if (this.debug) console.log(`Running worker ${worker.id} (${this.queue.size})`); + this.emit("runningJob", job); + + worker.status = Status.Busy; + worker.work = job; + + const startTime = process.hrtime.bigint(); + worker.worker.postMessage(data); + + const onceMessage = (result: Awaited>) => { + const delta = new Duration(Number((process.hrtime.bigint() - startTime) / nsPerMs)); + worker.status = Status.Idle; + resolve(result); + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + if (this.debug) console.log(`Finished worker ${worker.id} after ${delta} (${this.queue.size})`); + this.emit("jobEnded", result); + this.runCallback(); + worker.worker.removeListener("message", onceMessage); + worker.worker.removeListener("error", onceError); + }; + const onceError = (err: unknown) => { + worker.status = Status.Idle; + reject(err); + if (this.debug) console.log(`Errored worker ${worker.id} (${this.queue.size})`); + this.emit("jobEnded", err as object); + this.runCallback(); + worker.worker.removeListener("error", onceError); + worker.worker.removeListener("message", onceMessage); + }; + + worker.worker.once("message", onceMessage); + worker.worker.once("error", onceError); + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + if (!res || !rej) return def!.promise; + } + + protected runCallback(job?: queuedJob, Awaited>>) { + if (!job) { + if (!this.queue.size) return; + job = this.queue.dequeue(); + } + this.run(...job); + } + + protected getIdleWorker(): poolWorker, Awaited>> | undefined { + return this.pool.find((w) => w.status === Status.Idle); + } + + public waitForIdleWorker(): Promise { + const def = new Deferred(); + + if (this.getIdleWorker()) def.resolve(); + else + this.on("jobEnded", () => { + def.resolve(); + }); + + return def.promise; + } +} diff --git a/src/test/utils/benchmark.ts b/src/test/utils/benchmark.ts new file mode 100644 index 0000000..a45d079 --- /dev/null +++ b/src/test/utils/benchmark.ts @@ -0,0 +1,89 @@ +/** + * Benchmark a function + * @param f The function to do the benchmark on, sync or async + * @param args The argument(s) to pass to the function {@link f} + * @param thisArg A custom "this" to pass to the function {@link f} + * @param times Number of times to repeat the benchmark + * @param logStats Whether to log to the bench to the console at its end, or not + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export async function benchmark any>( + this: unknown, + f: F, + args: Parameters, + thisArg: unknown = this, // TODO : deeper look on thisArg + ThisType + times = 1, + logStats = true, +) { + const starts = new Array(times); + const ends = new Array(times); + let lastReturn: Awaited> | null = null; + for (let i = 0; i < times; i++) { + starts[i] = performance.now(); + lastReturn = (await f.call(thisArg, ...args)) as Awaited>; + ends[i] = performance.now(); + } + const durations = ends.map((e, i) => new Duration(e - starts[i])); + const totalDuration = new Duration(durations.reduce((acc, v) => acc + v.ms, 0)); + const averageDuration = new Duration(totalDuration.ms / times); + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + if (logStats) console.log(`Benchmark of ${f.name || "anonymous"} (${times} time${times > 1 ? "s" : ""}): ${averageDuration}`); + return { + fName: f.name, + args, + starts, + ends, + durations, + totalDuration, + averageDuration, + times, + lastReturn, + }; +} + +export class Duration { + private time: number; + + static getLeadingZeros(time: number, expectedNumbers: number) { + const repeats = expectedNumbers - time.toString().length; + return "0".repeat(repeats < 0 ? 0 : repeats); + } + + constructor(ms: number) { + this.time = ms; + } + + get ms() { + return this.time; + } + + set ms(ms: number) { + this.time = ms; + } + + get rMs() { + return this.time % 1000; + } + + get totalSeconds() { + return Math.floor(this.time / 1000); + } + + get rSeconds() { + return Math.floor(this.rMinuts / 1000); + } + + get totalMinuts() { + return Math.floor(this.time / 60000); + } + + get rMinuts() { + return this.time % 60000; + } + + toString() { + return `${Duration.getLeadingZeros(this.totalMinuts, 2)}${this.totalMinuts}:${Duration.getLeadingZeros(this.rSeconds, 2)}${ + this.rSeconds + }:${Duration.getLeadingZeros(Math.floor(this.rMs), 3)}${this.rMs}`; + } +} diff --git a/src/test/utils/index.ts b/src/test/utils/index.ts new file mode 100644 index 0000000..03a0c12 --- /dev/null +++ b/src/test/utils/index.ts @@ -0,0 +1,102 @@ +import { Ref } from "@typegoose/typegoose"; +import { RefType } from "@typegoose/typegoose/lib/types"; + +type ResolveCb = (value: T) => void; +type RejectCb = (reason?: unknown) => void; + +class Deferred { + public promise: Promise; + public resolve!: ResolveCb; + public reject!: RejectCb; + + constructor() { + this.promise = new Promise((resolve, reject) => { + this.reject = reject; + this.resolve = resolve; + }); + } +} + +/** + * @description Checks unicity of a value in an array + */ +function unique(v: T, i: number, arr: T[]): boolean { + return arr.indexOf(v) === i; +} + +/** + * @description Search for a value in a **sorted** array, in O(log2(n)). + * @param arr The **sorted** array where performing the search + * @param el The element to look for, which will be compared + * @param compare A compare function that takes 2 arguments : `a` el and `b` an element of the array. + * It returns : + * - a negative number if `a` is before `b`; + * - 0 if `a` is equal to `b`; + * - a positive number of `a` is after `b`. + * @returns The index of el if positive ; index of insertion if negative + */ +function binarySearch(arr: T[], el: C, compare: (a: C, b: T) => number) { + let low = 0; + let high = arr.length - 1; + while (low <= high) { + const mid = (high + low) >> 1; // x >> 1 == Math.floor(x/2) + const cmp = compare(el, arr[mid]); + if (cmp > 0) { + low = mid + 1; + } else if (cmp < 0) { + high = mid - 1; + } else { + return mid; + } + } + return ~low; // ~x == -x-1 +} + +function binaryFilter(arr: T[], el: C, compare: (a: C, b: T) => number): T[] { + const binarySearchResult = binarySearch(arr, el, compare); + if (binarySearchResult < 0) return []; + let low = binarySearchResult; + while (low >= 0 && compare(el, arr[low]) === 0) { + low--; + } + let high = binarySearchResult; + while (high < arr.length && compare(el, arr[high]) === 0) { + high++; + } + return arr.slice(low, high + 1); +} + +async function mapAsync(array: I[], callback: (value: I, index: number, array: I[]) => Promise): Promise { + return await Promise.all(array.map(callback)); +} + +function wait(ms = 1000): Promise { + const defP = new Deferred(); + + setTimeout(() => { + defP.resolve(null); + }, ms); + + return defP.promise; +} + +type UnpackRefs = Omit & { + [P in K]: D[P] extends Ref + ? T extends { + _id?: RefType; + } + ? T["_id"] + : never + : D[P] extends Ref[] + ? T extends { + _id?: RefType; + } + ? T["_id"][] + : never + : never; +}; + +type Combinations = T extends [infer E, ...infer R] ? [E, ...Combinations] | Combinations : T extends [] ? [] : never; + +export { binaryFilter, binarySearch, Deferred, mapAsync, unique, wait }; +export type { Combinations, RejectCb, ResolveCb, UnpackRefs }; diff --git a/src/test/utils/mongoose.ts b/src/test/utils/mongoose.ts new file mode 100644 index 0000000..298bf6e --- /dev/null +++ b/src/test/utils/mongoose.ts @@ -0,0 +1,11 @@ +import { createConnection } from "mongoose"; + +export default async function (dbName: string) { + const connection = createConnection(`mongodb://0.0.0.0:27017/${dbName}`); + + await connection.asPromise(); + + console.info(`Database ${dbName} connected.`); + + return connection; +} diff --git a/tsconfig.jest.json b/tsconfig.jest.json index 23f06db..d8b648e 100644 --- a/tsconfig.jest.json +++ b/tsconfig.jest.json @@ -6,6 +6,8 @@ "sourceMap": true, "declaration": true, "isolatedModules": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, "types": [ "node", "jest" diff --git a/tsconfig.json b/tsconfig.json index f830169..c41597d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,16 +1,14 @@ { - "extends": [ - "@tsconfig/node22/tsconfig.json", - ], + "extends": ["@tsconfig/node22/tsconfig.json"], "compilerOptions": { "outDir": "./lib", "rootDir": "./src", "target": "es2015", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, "sourceMap": true, "declaration": true, "isolatedModules": true }, - "include": [ - "src/**/*.ts" - ] -} \ No newline at end of file + "include": ["src/**/*.ts"] +}