From 730150c3ace79d441c2fd323f36c8cf43bbcb10a Mon Sep 17 00:00:00 2001 From: Victor Algaze Date: Fri, 8 Mar 2024 21:50:34 -0800 Subject: [PATCH] add typo fixes + cleanup, replace websocket dependency --- .gitignore | 4 +- .npmignore | 5 +- README.md | 126 +- contributing.md | 13 + docs/.vitepress/components/SendMsg.vue | 7 + .../components/SpeedyCardEditor.vue | 8 +- docs/.vitepress/components/token_handler.vue | 64 +- docs/.vitepress/components/webhooks.vue | 22 +- docs/.vitepress/config.mts | 18 +- docs/.vitepress/theme/style.css | 20 + docs/.vitepress/util/store.ts | 76 +- docs/api-docs/README.md | 126 +- docs/api-docs/classes/SpeedyBot.md | 123 +- docs/api-docs/classes/SpeedyCard.md | 60 +- docs/api-docs/modules.md | 2 +- docs/examples/lambda/README.md | 8 +- docs/examples/llm-stream/README.md | 2 +- docs/examples/standard-server/README.md | 2 +- docs/index.md | 6 +- docs/new.md | 40 +- docs/patterns.md | 2 +- docs/sb_logo.svg | 72 + examples/lambda/README.md | 6 +- examples/llm-stream/README.md | 2 +- examples/llm-stream/package.json | 17 +- examples/llm-stream/util/cli.ts | 11 +- examples/llm-stream/util/index.ts | 71 +- examples/llm-stream/util/launch.ts | 13 + examples/llm-stream/util/websockets.ts | 658 ++ examples/location/settings/location.ts | 2 +- .../speedybot-starter-legacy/.env.example | 7 + examples/speedybot-starter-legacy/.gitignore | 3 + examples/speedybot-starter-legacy/README.md | 76 + .../speedybot-starter-legacy/package.json | 44 + .../speedybot-starter-legacy/settings/bot.ts | 718 ++ .../settings/launch.ts | 0 .../speedybot-starter-legacy/tsconfig.json | 25 + examples/speedybot-starter-legacy/util/cli.ts | 144 + .../speedybot-starter-legacy/util/index.ts | 74 + .../util/utils.ts | 0 examples/speedybot-starter/package.json | 7 +- examples/speedybot-starter/util/cli.ts | 11 +- examples/speedybot-starter/util/index.ts | 72 +- examples/speedybot-starter/util/launch.ts | 13 + examples/speedybot-starter/util/utils.ts | 146 - examples/speedybot-starter/util/websockets.ts | 658 ++ examples/voiceflow-kb/package.json | 7 +- examples/voiceflow-kb/util/cli.ts | 11 +- examples/voiceflow-kb/util/index.ts | 71 +- .../voiceflow-kb/{settings => util}/launch.ts | 15 +- examples/voiceflow-kb/util/utils.ts | 146 - examples/voiceflow-kb/util/websockets.ts | 658 ++ examples/voiceflow/package.json | 7 +- examples/voiceflow/util/cli.ts | 11 +- examples/voiceflow/util/index.ts | 71 +- .../voiceflow/{settings => util}/launch.ts | 15 +- examples/voiceflow/util/utils.ts | 146 - examples/voiceflow/util/websockets.ts | 658 ++ examples/worker/settings/bot.ts | 8 - package-lock.json | 7304 +++++------------ package.json | 14 +- src/speedybot.ts | 109 + src/types.ts | 16 +- 63 files changed, 6527 insertions(+), 6324 deletions(-) create mode 100644 contributing.md create mode 100644 docs/sb_logo.svg create mode 100644 examples/llm-stream/util/launch.ts create mode 100644 examples/llm-stream/util/websockets.ts create mode 100644 examples/speedybot-starter-legacy/.env.example create mode 100644 examples/speedybot-starter-legacy/.gitignore create mode 100644 examples/speedybot-starter-legacy/README.md create mode 100644 examples/speedybot-starter-legacy/package.json create mode 100644 examples/speedybot-starter-legacy/settings/bot.ts rename examples/{speedybot-starter => speedybot-starter-legacy}/settings/launch.ts (100%) create mode 100644 examples/speedybot-starter-legacy/tsconfig.json create mode 100644 examples/speedybot-starter-legacy/util/cli.ts create mode 100644 examples/speedybot-starter-legacy/util/index.ts rename examples/{llm-stream => speedybot-starter-legacy}/util/utils.ts (100%) create mode 100644 examples/speedybot-starter/util/launch.ts delete mode 100644 examples/speedybot-starter/util/utils.ts create mode 100644 examples/speedybot-starter/util/websockets.ts rename examples/voiceflow-kb/{settings => util}/launch.ts (56%) delete mode 100644 examples/voiceflow-kb/util/utils.ts create mode 100644 examples/voiceflow-kb/util/websockets.ts rename examples/voiceflow/{settings => util}/launch.ts (56%) delete mode 100644 examples/voiceflow/util/utils.ts create mode 100644 examples/voiceflow/util/websockets.ts diff --git a/.gitignore b/.gitignore index 26ea823..209e3f5 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,6 @@ abc.ts .vitepress/cache docs/.vitepress/cache/* coverage/ -todo.md \ No newline at end of file +todo.md +message_log.txt +changelog.md \ No newline at end of file diff --git a/.npmignore b/.npmignore index 8097810..ca32df9 100644 --- a/.npmignore +++ b/.npmignore @@ -14,4 +14,7 @@ coverage/ todo.md .github .vscode -trickyoperation.ts \ No newline at end of file +trickyoperation.ts +contributing.md +devtools/ +changelog.md \ No newline at end of file diff --git a/README.md b/README.md index c05156b..b4f1f73 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ -tl;dr: SpeedyBot helps you efficiently design, deploy, and secure rich conversation systems +tl;dr: SpeedyBot helps you efficiently design, deploy, and secure rich conversation systems-- go from zero to a bot in seconds **[here](https://speedybot.js.org/new)** ## Setup @@ -21,7 +21,7 @@ npm install speedybot ## Speedy & Easy -- SpeedyBot offers a buttery-smooth developer experience to keep you building your bots rather than scouring the docs. It's written in typescript + built-in type hints with autocomplete, has zero external dependencies, supports ESM + CommonJS, provides lots of other DX goodness that makes building bots a breeze like local development with live-reload (see **[here for details](https://github.com/valgaze/speedybot/blob/v2/examples/speedybot-starter/settings/bot.ts)**). +- SpeedyBot offers a buttery-smooth developer experience to keep you building your bots rather than scouring the docs. It's written in typescript + built-in type hints with autocomplete, **has zero external dependencies**, supports ESM + CommonJS, provides lots of other DX goodness like live-reload on code changes that makes building bots speedy and easy (see **[here for details](https://speedybot.js.org/new)**). - SpeedyBot shrinks away all the complexity and makes it a breeze to handle user input regardless of the source/modality-- text, file uploads, form submission from SpeedyCards, etc @@ -29,97 +29,93 @@ npm install speedybot ## SpeedyBot basics -You can see fleshed-out examples at **[https://speedybot.js.org/examples/](https://speedybot.js.org/examples/)** and see how SpeedyBot has you covered for crafting bots that can do it all-- securely integrate w/ LLMs + content management systems, **[process file-uploads](https://speedybot.js.org/patterns.md#handle-file-uploads)**, **[segment content based on user data + behavior](https://speedybot.js.org/patterns.md#restrict-emails)**, create + manage **[SpeedyCards](https://speedybot.js.org/speedycard)**, ask for a user's location in a privacy-respecting way and lots more. +You can get a bot up and running fast by grabbing one of the batteries-included samples at **[https://speedybot.js.org/examples](https://speedybot.js.org/examples/)** and see how SpeedyBot has you covered for crafting bots that can do it all-- **[securely integrate w/ LLMs + content management systems](https://speedybot.js.org/examples/voiceflow/README)**, **[process file-uploads](https://speedybot.js.org/patterns.md#handle-file-uploads)**, **[segment content based on user data + behavior](https://speedybot.js.org/patterns.md#restrict-emails)**, create + manage **[SpeedyCards](https://speedybot.js.org/speedycard)**, **[ask for a user's location in a privacy-respecting way](https://speedybot.js.org/examples/location/README)** and lots more. -### Auto-binding +## The basics -As a convenience, SpeedyBot's "magic" $ parameter will auto-bind to the incoming message and give you access to all kinds of useful features +- SpeedyBot streamlines the creation of conversation systems, making it easy to deploy and manage bots. When your SpeedyBot receives an event from a user (such as a message, card, or file upload), it processes the event through a sequence of steps, similar to how a car moves through a carwash. -```js -const Bot = new SpeedyBot(); +- Each step is just a function which **must** return either $.next to proceed to the next step or $.end to terminate the chain. Each step can be synchronous or asynchronous depending on what you need to do -// You get an incoming messsage -Bot.addStep(async ($) => { - await $.send("Hello the originating person/room"); - await $.reply("Reply to the originating person/room"); +- A step can do **whatever** you want (ex send the user a message or a **[SpeedyCard](https://speedybot.js.org/speedycard)**, call an API to interact with some external system, or do nothing at all) + +- Whatever you're up to in a step, however, try not to take too long to do it because you probably don't want to keep your user waiting - // The same as the following - await Bot.sendTo($.author.email, "my message"); +Here's a starter `bot.ts`: - const parentMessageID = $.id; - await Bot.replyTo(parentMessageID, $.author.email, "my great reply message"); +```ts +import { SpeedyBot } from "speedybot"; +const Bot = new SpeedyBot(); + +Bot.addStep(async ($) => { + await $.send("Step 1"); + if ($.text === "hi") { + await $.reply(`Hi there ${$.author.name}!`); + } return $.next; }); -``` -There's also a lot more you can do +Bot.addStep(($) => { + $.ctx.scribbledData = "someData_" + Math.random(); + return $.next; +}); - +Bot.addStep(async ($) => { + await $.send("Step 2"); + const card = $.card() + .addTitle("My great card!") + .addText(`The random scribbled data is ${$.ctx.scribbledData}`) + .addTable([ + ["Label", "Data 1"], + ["Label 2", "Data 2"], + ["Label 3", "Data 3"], + ]); + await $.send(card); // send a card, not just text + return $.next; +}); -## SpeedyCards +Bot.addStep(async ($) => { + await $.send("Step 3"); + return $.end; // <--- Stops the train! +}); -SpeedyCards make it (yep) speedy and easy to build **[Adaptive Cards](https://adaptivecards.io)** where you can easily collect structured data from users and add colors, "chips", formatting and other visual embellishments. +Bot.addStep(async ($) => { + await $.send("Step 4 (we never reach this!"); + return $.end; +}); +``` - + - +- The $ parameter provides a bunch of useful features, allowing you to reply to messages, send and check card data (see **[details on that](https://speedybot.js.org/patterns.html#simple-card-handler)**), and access information about the message and its author. -## LLM Token Streaming + -SpeedyBot makes it speedy & easy to build serverless bots for the LLM era. See the **[LLM steam example](https://speedybot.js.org/examples/llm-stream)** +- Important: Avoid excessive usage of steps. If you find yourself writing a lot of "handlers" or checks in your steps you might be making things harder than they need to be. For a natural language "conversation", for example, focus on capturing user utterances (`$.text`) in your steps and then all you need to do is transmit back and forth to an external service and keep your steps short and sweet and simple - +- Execution Order: Generally speaking, steps will fire in the order they are added to your `bot.ts`-- for convenience, there is a `Bot.insertStepToFront` step which will slip the supplied step to the front of the chain and also `Bot.addStepSequence` to add a list of steps all at once -## SpeedyBot "listener" +## Garage -You can use SpeedyBot to only send messages + cards and nothing more. But if you have data on those cards you want to capture or if you want to provide an automated conversation experience SpeedyBot takes of all the hassle. +SpeedyBot's docs are special-- they're interactive and you can do things with them. From the Patterns docs you can grab **[code snippets](https://speedybot.js.org/patterns)** and throw them right into your bot. Inside the visaul **[SpeedyBot Garage](https://speedybot.js.org/garage)** experience you can register webhooks and design + preview + send **[SpeedyCards](https://speedybot.js.org/speedycard)** -Ex. Here is a minimal handler that will echo back information if a user transmits data via text, file, and adaptive card. Write "show card" to display a card. You can chain multiple addSteps if you need to, but in this era you probably don't need/want to be doing much logic in code. + -See full example applications here: **[https://speedybot.js.org/examples](https://speedybot.js.org/examples)** +## SpeedyCards -```ts -import { SpeedyBot } from "speedybot"; +SpeedyCards make it speedy and easy to build **[Adaptive Cards](https://adaptivecards.io)** where you can easily collect structured data from users and add colors, "chips", formatting and other visual embellishments. -const Bot = new SpeedyBot(); -Bot.addStep(async ($) => { - // handle text - if ($.text) { - await $.send(`You said "${$.text}`); - - if ($.text.toLowerCase() === "showcard") { - const card = $.card() - .addTitle("Capture data") - .addTextarea("Submit data") - .addPickerDropdown(["option 1", "option 2", "option 3", "option 4"]); - await $.send(card); - } - } + - // file handler - if ($.file) { - const { name, extension, contentType } = $.file; - await $.send( - `You uploaded "${name}", a *.${extension} file [${contentType}]` - ); - // Fetch raw bytes (which you can pass onto other systems) - // const TheData = await $.file.getData(); // do something w/ the contents/bytes - } + - // form/card submissions - if ($.data) { - const dataSnippet = $.buildDataSnippet($.data); - await $.send(`This data was submitted:`); - await $.send(dataSnippet); - } +## LLM Token Streaming - return $.next; -}); +SpeedyBot makes it speedy & easy to build serverless bots for the LLM era. See the **[LLM steam example](https://speedybot.js.org/examples/llm-stream)** -export default Bot; -``` + ## 🐍 Speedybot-Python -If you want to build bots with Python rather than Typescript, you can check out [🐍Speedybot-Python🐍](https://pypi.org/project/speedybot) +If you want to build bots with Python rather than Typescript, you can also check out [🐍Speedybot-Python🐍](https://pypi.org/project/speedybot) diff --git a/contributing.md b/contributing.md new file mode 100644 index 0000000..88c75c4 --- /dev/null +++ b/contributing.md @@ -0,0 +1,13 @@ +## Contributing + +Contributions and better ways of doing things always welcome + +If you want to extend SpeedyBot or add an example, take a look at the codebase and feel free to make a PR + +## Wishlist + +- VSC Extension + +- Stable Tauri (crashes on M1) for no-fuss coding + +- Bulk send, bulk add to space, get all 1st messages diff --git a/docs/.vitepress/components/SendMsg.vue b/docs/.vitepress/components/SendMsg.vue index da01ebe..a73120c 100644 --- a/docs/.vitepress/components/SendMsg.vue +++ b/docs/.vitepress/components/SendMsg.vue @@ -10,6 +10,7 @@ @@ -57,6 +58,12 @@ const targetRoom = ref(""); const showToken = ref(true); const props = defineProps({ + skipRoomConfig: { + type: Boolean, + default() { + return true; + }, + }, msg: { type: Object, }, diff --git a/docs/.vitepress/components/SpeedyCardEditor.vue b/docs/.vitepress/components/SpeedyCardEditor.vue index 4071236..fbf143a 100644 --- a/docs/.vitepress/components/SpeedyCardEditor.vue +++ b/docs/.vitepress/components/SpeedyCardEditor.vue @@ -8,20 +8,20 @@ > - + - + - - + + diff --git a/docs/.vitepress/components/token_handler.vue b/docs/.vitepress/components/token_handler.vue index 74e3aee..5899ca6 100644 --- a/docs/.vitepress/components/token_handler.vue +++ b/docs/.vitepress/components/token_handler.vue @@ -1,6 +1,33 @@ + + +import { ref } from "vue"; import { Refresh } from "@element-plus/icons-vue"; import { useCustomStore } from "./../util/store"; +import { computed, watch } from "vue"; +// import { ElLoading } from "element-plus"; const store = useCustomStore(); - +const label = ref("⭐️"); const emit = defineEmits(); const checkToken = async (tokenCandidate: string) => { if (tokenCandidate.length > 5) { @@ -76,7 +112,33 @@ const checkToken = async (tokenCandidate: string) => { } }; +const watchFilters = computed(() => ({ + roomFiltersSort: store.state.roomFilters.sortBy, + roomFiltersType: store.state.roomFilters.type, + deepSearch: store.state.deepSearch, +})); + +watch(watchFilters, async (newValues, oldValues) => { + if (store.state.token) { + await store.validateToken(store.state.token); + } +}); + +const handleChange = (val: string[]) => { + if (val) { + label.value = "🌟"; + } else { + label.value = "⭐️"; + } +}; + const props = defineProps({ + skipRoomConfig: { + type: Boolean, + default() { + return false; + }, + }, showInfo: { type: Boolean, default() { diff --git a/docs/.vitepress/components/webhooks.vue b/docs/.vitepress/components/webhooks.vue index af508fe..e3d67a6 100644 --- a/docs/.vitepress/components/webhooks.vue +++ b/docs/.vitepress/components/webhooks.vue @@ -91,7 +91,7 @@ const store = useCustomStore(); const showWebhooksForm = ref(false); const webhooksForm = ref({ url: "", - secret: null, + secret: "", }); const webhooksList = ref< @@ -151,7 +151,7 @@ const submit = async () => { const createWebhook = async () => { try { - await store.Bot.Setup(url, secret); + await store.Bot.Setup(url, secret ?? undefined); ElMessage({ type: "success", message: "Webhook created 🎉", @@ -180,31 +180,21 @@ watch( () => store.state.tokenValid, async (v) => { if (v === true) { - const loading = ElLoading.service({ - lock: true, - text: "Loading", - background: "rgba(0, 0, 0, 0.7)", - }); await webhooksFetch(); - loading.close(); } } ); onMounted(async () => { if (store.state.tokenValid) { - const loading = ElLoading.service({ - lock: true, - text: "Loading", - background: "rgba(0, 0, 0, 0.7)", - }); - try { await webhooksFetch(); } catch (e) { - loading.close(); + ElMessage({ + type: "error", + message: "Error fetching websockets " + e, + }); } - loading.close(); } }); diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 14e83a5..2a061b9 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -1,4 +1,5 @@ import { defineConfig } from "vitepress"; +import { version } from "./../../package.json"; // https://vitepress.dev/reference/site-config export default defineConfig({ @@ -6,6 +7,7 @@ export default defineConfig({ title: "SpeedyBot", description: "Rich conversation agents, the speedy and easy way", themeConfig: { + logo: "./..//sb_logo.svg", footer: { message: `MIT License ${new Date().getFullYear()}`, // this'll be statically updated everytime redeploy }, @@ -70,8 +72,22 @@ export default defineConfig({ }, { text: "📇 SpeedyCard", link: "/speedycard" }, { text: "🔧 Garage", link: "/garage" }, - { text: "📚 Reference", link: "/../api-docs/modules" }, + // { text: "📚 Reference", link: "/../api-docs/modules" }, { text: "🐍 Python Version", link: "https://pypi.org/project/speedybot" }, + { + text: `v${version}`, + items: [ + { + text: "Release Notes", + link: "https://github.com/valgaze/speedybot/releases", + }, + { + text: "Contributing", + link: "https://github.com/valgaze/speedybot/blob/main/CONTRIBUTING.md", + }, + ], + }, + // { text: "🏡 Home", link: "/" }, ], diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css index 0ab5e4d..31a6c9e 100644 --- a/docs/.vitepress/theme/style.css +++ b/docs/.vitepress/theme/style.css @@ -172,3 +172,23 @@ .excerpt-gradient-top { display: none !important; } + +html.dark img.logo { + filter: invert(1.5); +} + +/* html.dark .VPImage.image-src { + filter: invert(0.75); +} */ + +.VPImage.image-src:hover { + filter: contrast(200%); +} + +.image-bg { + background: linear-gradient( + 25deg, + #ffd1a4 0%, + #fff9c4 100% + ) !important; /* hack :( */ +} diff --git a/docs/.vitepress/util/store.ts b/docs/.vitepress/util/store.ts index 2996664..4ec514c 100644 --- a/docs/.vitepress/util/store.ts +++ b/docs/.vitepress/util/store.ts @@ -1,7 +1,9 @@ -import { inject, provide, InjectionKey, reactive, ref } from "vue"; +import { inject, provide, InjectionKey, reactive, ref, nextTick } from "vue"; import { SpeedyBot } from "./../../../src/speedybot"; +import { RoomConfig } from "../../../src"; import { ElLoading } from "element-plus"; -import { Webhook } from "../../../src"; +import { Room_Details, Webhook } from "../../../src"; +import { de, el, tr } from "element-plus/es/locale/index.mjs"; interface UserData { username: string; @@ -15,6 +17,8 @@ interface Store { webhooks: Webhook[]; tokenValid: null | boolean; userData: UserData; + deepSearch: boolean; + roomFilters: Partial; } const BotInst = new SpeedyBot() as SpeedyBot; @@ -29,18 +33,32 @@ const store: Store = reactive({ type: "", emails: [], }, + deepSearch: false, + roomFilters: {}, }); -async function getRecentRooms(): Promise< - { type: string; title: string; id: string }[] -> { - const list = await BotInst.getRecentRooms(); +async function getRooms( + config?: { full?: boolean } & Partial +): Promise<{ type: string; title: string; id: string }[]> { + const { full, ...options } = config || {}; + const list = full + ? await BotInst.getAllRooms(options) + : await BotInst.getRecentRooms(); return list; } -async function setRecentRooms() { - const list = await BotInst.getRecentRooms(); - store.roomList = list; +function setRooms( + rooms: { + type: string; + title: string; + id: string; + }[] +) { + store.roomList = rooms; +} + +function setSearchlevel(deep: boolean) { + store.deepSearch = deep; } function setToken(newToken: string) { @@ -62,22 +80,28 @@ async function validateToken(tokenCandidate: string): Promise { const isValid = await BotInst.getSelf(tokenCandidate.trim()); // trim bc lots of people have newlines/spaces if (isValid.id) { store.tokenValid = true; - if (store.tokenValid) { - store.token = tokenCandidate; - store.userData.username = isValid.displayName; - store.userData.type = isValid.type; - store.userData.emails = isValid.emails; - BotInst.setToken(tokenCandidate); - - // Get a headstart on rooms list - await setRecentRooms(); - } - } else { - store.tokenValid = false; + store.token = tokenCandidate; + store.userData.username = isValid.displayName; + store.userData.type = isValid.type; + store.userData.emails = isValid.emails; + BotInst.setToken(tokenCandidate); + nextTick(async () => { + const rooms = await getRooms( + store.deepSearch + ? { full: true, ...store.roomFilters } + : { full: false, ...store.roomFilters } + ); + setRooms(rooms); + nextTick(async () => { + loading.close(); + }); + }); } - loading.close(); } catch (_) { - loading.close(); + console.log(_); + nextTick(() => { + loading.close(); + }); store.tokenValid = false; return false; } @@ -111,12 +135,14 @@ function cycle(index?: number) { export const storeHelper = { Bot: BotInst, state: store, - getRecentRooms, - setRecentRooms, + getRooms, + setRooms, + // setRecentRooms, setToken, addWebhook, validateToken, cycle, + setSearchlevel, }; const storeSymbol: InjectionKey = Symbol("customStore"); diff --git a/docs/api-docs/README.md b/docs/api-docs/README.md index acc9f13..2d28099 100644 --- a/docs/api-docs/README.md +++ b/docs/api-docs/README.md @@ -13,7 +13,7 @@ speedybot / [Exports](modules.md) -tl;dr: SpeedyBot helps you efficiently design, deploy, and secure rich conversation systems +tl;dr: SpeedyBot helps you efficiently design, deploy, and secure rich conversation systems-- go from zero to a bot in seconds **[here](https://speedybot.js.org/new)** ## Setup @@ -23,7 +23,7 @@ npm install speedybot ## Speedy & Easy -- SpeedyBot offers a buttery-smooth developer experience to keep you building your bots rather than scouring the docs. It's written in typescript + built-in type hints with autocomplete, has zero external dependencies, supports ESM + CommonJS, provides lots of other DX goodness that makes building bots a breeze like local development with live-reload (see **[here for details](https://github.com/valgaze/speedybot/blob/v2/examples/speedybot-starter/settings/bot.ts)**). +- SpeedyBot offers a buttery-smooth developer experience to keep you building your bots rather than scouring the docs. It's written in typescript + built-in type hints with autocomplete, **has zero external dependencies**, supports ESM + CommonJS, provides lots of other DX goodness like live-reload on code changes that makes building bots speedy and easy (see **[here for details](https://speedybot.js.org/new)**). - SpeedyBot shrinks away all the complexity and makes it a breeze to handle user input regardless of the source/modality-- text, file uploads, form submission from SpeedyCards, etc @@ -31,97 +31,93 @@ npm install speedybot ## SpeedyBot basics -You can see fleshed-out examples at **[https://speedybot.js.org/examples/](https://speedybot.js.org/examples/)** and see how SpeedyBot has you covered for crafting bots that can do it all-- securely integrate w/ LLMs + content management systems, **[process file-uploads](https://speedybot.js.org/patterns.md#handle-file-uploads)**, **[segment content based on user data + behavior](https://speedybot.js.org/patterns.md#restrict-emails)**, create + manage **[SpeedyCards](https://speedybot.js.org/speedycard)**, ask for a user's location in a privacy-respecting way and lots more. +You can get a bot up and running fast by grabbing one of the batteries-included samples at **[https://speedybot.js.org/examples](https://speedybot.js.org/examples/)** and see how SpeedyBot has you covered for crafting bots that can do it all-- **[securely integrate w/ LLMs + content management systems](https://speedybot.js.org/examples/voiceflow/README)**, **[process file-uploads](https://speedybot.js.org/patterns.md#handle-file-uploads)**, **[segment content based on user data + behavior](https://speedybot.js.org/patterns.md#restrict-emails)**, create + manage **[SpeedyCards](https://speedybot.js.org/speedycard)**, **[ask for a user's location in a privacy-respecting way](https://speedybot.js.org/examples/location/README)** and lots more. -### Auto-binding +## The basics -As a convenience, SpeedyBot's "magic" $ parameter will auto-bind to the incoming message and give you access to all kinds of useful features +- SpeedyBot streamlines the creation of conversation systems, making it easy to deploy and manage bots. When your SpeedyBot receives an event from a user (such as a message, card, or file upload), it processes the event through a sequence of steps, similar to how a car moves through a carwash. -```js -const Bot = new SpeedyBot(); +- Each step is just a function which **must** return either $.next to proceed to the next step or $.end to terminate the chain. Each step can be synchronous or asynchronous depending on what you need to do -// You get an incoming messsage -Bot.addStep(async ($) => { - await $.send("Hello the originating person/room"); - await $.reply("Reply to the originating person/room"); +- A step can do **whatever** you want (ex send the user a message or a **[SpeedyCard](https://speedybot.js.org/speedycard)**, call an API to interact with some external system, or do nothing at all) + +- Whatever you're up to in a step, however, try not to take too long to do it because you probably don't want to keep your user waiting - // The same as the following - await Bot.sendTo($.author.email, "my message"); +Here's a starter `bot.ts`: - const parentMessageID = $.id; - await Bot.replyTo(parentMessageID, $.author.email, "my great reply message"); +```ts +import { SpeedyBot } from "speedybot"; +const Bot = new SpeedyBot(); + +Bot.addStep(async ($) => { + await $.send("Step 1"); + if ($.text === "hi") { + await $.reply(`Hi there ${$.author.name}!`); + } return $.next; }); -``` -There's also a lot more you can do +Bot.addStep(($) => { + $.ctx.scribbledData = "someData_" + Math.random(); + return $.next; +}); - +Bot.addStep(async ($) => { + await $.send("Step 2"); + const card = $.card() + .addTitle("My great card!") + .addText(`The random scribbled data is ${$.ctx.scribbledData}`) + .addTable([ + ["Label", "Data 1"], + ["Label 2", "Data 2"], + ["Label 3", "Data 3"], + ]); + await $.send(card); // send a card, not just text + return $.next; +}); -## SpeedyCards +Bot.addStep(async ($) => { + await $.send("Step 3"); + return $.end; // <--- Stops the train! +}); -SpeedyCards make it (yep) speedy and easy to build **[Adaptive Cards](https://adaptivecards.io)** where you can easily collect structured data from users and add colors, "chips", formatting and other visual embellishments. +Bot.addStep(async ($) => { + await $.send("Step 4 (we never reach this!"); + return $.end; +}); +``` - + - +- The $ parameter provides a bunch of useful features, allowing you to reply to messages, send and check card data (see **[details on that](https://speedybot.js.org/patterns.html#simple-card-handler)**), and access information about the message and its author. -## LLM Token Streaming + -SpeedyBot makes it speedy & easy to build serverless bots for the LLM era. See the **[LLM steam example](https://speedybot.js.org/examples/llm-stream)** +- Important: Avoid excessive usage of steps. If you find yourself writing a lot of "handlers" or checks in your steps you might be making things harder than they need to be. For a natural language "conversation", for example, focus on capturing user utterances (`$.text`) in your steps and then all you need to do is transmit back and forth to an external service and keep your steps short and sweet and simple - +- Execution Order: Generally speaking, steps will fire in the order they are added to your `bot.ts`-- for convenience, there is a `Bot.insertStepToFront` step which will slip the supplied step to the front of the chain and also `Bot.addStepSequence` to add a list of steps all at once -## SpeedyBot "listener" +## Garage -You can use SpeedyBot to only send messages + cards and nothing more. But if you have data on those cards you want to capture or if you want to provide an automated conversation experience SpeedyBot takes of all the hassle. +SpeedyBot's docs are special-- they're interactive and you can do things with them. From the Patterns docs you can grab **[code snippets](https://speedybot.js.org/patterns)** and throw them right into your bot. Inside the visaul **[SpeedyBot Garage](https://speedybot.js.org/garage)** experience you can register webhooks and design + preview + send **[SpeedyCards](https://speedybot.js.org/speedycard)** -Ex. Here is a minimal handler that will echo back information if a user transmits data via text, file, and adaptive card. Write "show card" to display a card. You can chain multiple addSteps if you need to, but in this era you probably don't need/want to be doing much logic in code. + -See full example applications here: **[https://speedybot.js.org/examples](https://speedybot.js.org/examples)** +## SpeedyCards -```ts -import { SpeedyBot } from "speedybot"; +SpeedyCards make it speedy and easy to build **[Adaptive Cards](https://adaptivecards.io)** where you can easily collect structured data from users and add colors, "chips", formatting and other visual embellishments. -const Bot = new SpeedyBot(); -Bot.addStep(async ($) => { - // handle text - if ($.text) { - await $.send(`You said "${$.text}`); - - if ($.text.toLowerCase() === "showcard") { - const card = $.card() - .addTitle("Capture data") - .addTextarea("Submit data") - .addPickerDropdown(["option 1", "option 2", "option 3", "option 4"]); - await $.send(card); - } - } + - // file handler - if ($.file) { - const { name, extension, contentType } = $.file; - await $.send( - `You uploaded "${name}", a *.${extension} file [${contentType}]` - ); - // Fetch raw bytes (which you can pass onto other systems) - // const TheData = await $.file.getData(); // do something w/ the contents/bytes - } + - // form/card submissions - if ($.data) { - const dataSnippet = $.buildDataSnippet($.data); - await $.send(`This data was submitted:`); - await $.send(dataSnippet); - } +## LLM Token Streaming - return $.next; -}); +SpeedyBot makes it speedy & easy to build serverless bots for the LLM era. See the **[LLM steam example](https://speedybot.js.org/examples/llm-stream)** -export default Bot; -``` + ## 🐍 Speedybot-Python -If you want to build bots with Python rather than Typescript, you can check out [🐍Speedybot-Python🐍](https://pypi.org/project/speedybot) +If you want to build bots with Python rather than Typescript, you can also check out [🐍Speedybot-Python🐍](https://pypi.org/project/speedybot) diff --git a/docs/api-docs/classes/SpeedyBot.md b/docs/api-docs/classes/SpeedyBot.md index a50a94f..bc87e7a 100644 --- a/docs/api-docs/classes/SpeedyBot.md +++ b/docs/api-docs/classes/SpeedyBot.md @@ -49,7 +49,6 @@ - [insertStepToFront](SpeedyBot.md#insertsteptofront) - [onCamera](SpeedyBot.md#oncamera) - [onReject](SpeedyBot.md#onreject) -- [peekFile](SpeedyBot.md#peekfile) - [pickRandom](SpeedyBot.md#pickrandom) - [rando](SpeedyBot.md#rando) - [regex](SpeedyBot.md#regex) @@ -85,7 +84,7 @@ #### Defined in -[speedybot.ts:53](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L53) +[speedybot.ts:55](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L55) ## Methods @@ -93,6 +92,8 @@ ▸ **Setup**(`url`, `secret`): `Promise`<[`Webhook`, `Webhook`]\> +Create firehose and attachmentActions webhooks + #### Parameters | Name | Type | @@ -106,7 +107,7 @@ #### Defined in -[speedybot.ts:926](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L926) +[speedybot.ts:934](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L934) ___ @@ -127,7 +128,7 @@ ___ #### Defined in -[speedybot.ts:67](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L67) +[speedybot.ts:69](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L69) ___ @@ -147,7 +148,7 @@ ___ #### Defined in -[speedybot.ts:71](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L71) +[speedybot.ts:73](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L73) ___ @@ -190,7 +191,7 @@ Bot.addStep(async ($) => { #### Defined in -[speedybot.ts:152](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L152) +[speedybot.ts:154](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L154) ___ @@ -216,7 +217,7 @@ ___ #### Defined in -[speedybot.ts:156](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L156) +[speedybot.ts:158](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L158) ___ @@ -238,7 +239,7 @@ ___ #### Defined in -[speedybot.ts:1410](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1410) +[speedybot.ts:1427](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1427) ___ @@ -258,7 +259,7 @@ ___ #### Defined in -[speedybot.ts:245](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L245) +[speedybot.ts:247](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L247) ___ @@ -306,7 +307,7 @@ CultureBot.contains(["hi", "hey"], #### Defined in -[speedybot.ts:710](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L710) +[speedybot.ts:712](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L712) ___ @@ -326,7 +327,7 @@ ___ #### Defined in -[speedybot.ts:1018](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1018) +[speedybot.ts:1026](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1026) ___ @@ -350,7 +351,7 @@ If a match is found, the provided middleware function is executed. #### Defined in -[speedybot.ts:221](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L221) +[speedybot.ts:223](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L223) ___ @@ -387,7 +388,7 @@ The converted object. #### Defined in -[speedybot.ts:1402](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1402) +[speedybot.ts:1419](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1419) ___ @@ -412,7 +413,7 @@ ___ #### Defined in -[speedybot.ts:1002](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1002) +[speedybot.ts:1010](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1010) ___ @@ -432,7 +433,7 @@ ___ #### Defined in -[speedybot.ts:857](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L857) +[speedybot.ts:859](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L859) ___ @@ -452,7 +453,7 @@ ___ #### Defined in -[speedybot.ts:870](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L870) +[speedybot.ts:872](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L872) ___ @@ -472,7 +473,7 @@ ___ #### Defined in -[speedybot.ts:842](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L842) +[speedybot.ts:844](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L844) ___ @@ -496,7 +497,7 @@ Edit a message #### Defined in -[speedybot.ts:792](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L792) +[speedybot.ts:794](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L794) ___ @@ -517,7 +518,7 @@ ___ #### Defined in -[speedybot.ts:775](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L775) +[speedybot.ts:777](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L777) ___ @@ -541,7 +542,7 @@ If there is a match, the provided middleware function is executed. #### Defined in -[speedybot.ts:203](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L203) +[speedybot.ts:205](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L205) ___ @@ -568,7 +569,7 @@ ___ #### Defined in -[speedybot.ts:1292](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1292) +[speedybot.ts:1300](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1300) ___ @@ -584,7 +585,7 @@ Return abbreviated array of webhook data #### Defined in -[speedybot.ts:905](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L905) +[speedybot.ts:907](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L907) ___ @@ -592,6 +593,8 @@ ___ ▸ **fuzzyMatch**(`candidate`, `options`): `boolean` +Utility to traverse Link headers for pagination, built-in back-off + #### Parameters | Name | Type | @@ -605,7 +608,7 @@ ___ #### Defined in -[speedybot.ts:1378](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1378) +[speedybot.ts:1395](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1395) ___ @@ -619,7 +622,7 @@ ___ #### Defined in -[speedybot.ts:1132](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1132) +[speedybot.ts:1140](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1140) ___ @@ -641,7 +644,7 @@ ___ #### Defined in -[speedybot.ts:1236](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1236) +[speedybot.ts:1244](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1244) ___ @@ -661,7 +664,7 @@ ___ #### Defined in -[speedybot.ts:1069](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1069) +[speedybot.ts:1077](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1077) ___ @@ -681,7 +684,7 @@ ___ #### Defined in -[speedybot.ts:935](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L935) +[speedybot.ts:943](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L943) ___ @@ -701,7 +704,7 @@ ___ #### Defined in -[speedybot.ts:1083](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1083) +[speedybot.ts:1091](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1091) ___ @@ -721,7 +724,7 @@ ___ #### Defined in -[speedybot.ts:75](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L75) +[speedybot.ts:77](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L77) ___ @@ -741,7 +744,7 @@ ___ #### Defined in -[speedybot.ts:1024](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1024) +[speedybot.ts:1032](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1032) ___ @@ -755,7 +758,7 @@ ___ #### Defined in -[speedybot.ts:105](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L105) +[speedybot.ts:107](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L107) ___ @@ -771,7 +774,7 @@ Return array of full webhook data #### Defined in -[speedybot.ts:887](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L887) +[speedybot.ts:889](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L889) ___ @@ -791,7 +794,7 @@ ___ #### Defined in -[speedybot.ts:113](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L113) +[speedybot.ts:115](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L115) ___ @@ -816,7 +819,7 @@ For use w/ vision + text prompting systems #### Defined in -[speedybot.ts:183](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L183) +[speedybot.ts:185](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L185) ___ @@ -836,27 +839,7 @@ ___ #### Defined in -[speedybot.ts:239](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L239) - -___ - -### peekFile - -▸ **peekFile**(`url`): `Promise`<`Omit`<`SpeedyFile`, ``"data"``\>\> - -#### Parameters - -| Name | Type | -| :------ | :------ | -| `url` | `string` | - -#### Returns - -`Promise`<`Omit`<`SpeedyFile`, ``"data"``\>\> - -#### Defined in - -[speedybot.ts:1310](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1310) +[speedybot.ts:241](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L241) ___ @@ -882,7 +865,7 @@ ___ #### Defined in -[speedybot.ts:120](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L120) +[speedybot.ts:122](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L122) ▸ **pickRandom**<`P`\>(`min`, `max`): `number` @@ -905,7 +888,7 @@ ___ #### Defined in -[speedybot.ts:121](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L121) +[speedybot.ts:123](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L123) ▸ **pickRandom**<`P`\>(`listOrMin`, `max?`): `number` \| `P` @@ -928,7 +911,7 @@ ___ #### Defined in -[speedybot.ts:122](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L122) +[speedybot.ts:124](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L124) ___ @@ -944,7 +927,7 @@ Generate a random string of 11 characters (letters + numbers) #### Defined in -[speedybot.ts:1139](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1139) +[speedybot.ts:1147](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1147) ___ @@ -965,7 +948,7 @@ ___ #### Defined in -[speedybot.ts:160](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L160) +[speedybot.ts:162](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L162) ___ @@ -987,7 +970,7 @@ ___ #### Defined in -[speedybot.ts:812](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L812) +[speedybot.ts:814](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L814) ___ @@ -1015,7 +998,7 @@ import #### Defined in -[speedybot.ts:260](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L260) +[speedybot.ts:262](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L262) ___ @@ -1052,7 +1035,7 @@ $bot.sendFileTo('target@email.com', myData, 'json') #### Defined in -[speedybot.ts:1180](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1180) +[speedybot.ts:1188](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1188) ___ @@ -1087,7 +1070,7 @@ Bot.sendTo({toPersonId: 'xxxyyyzzz', '**here is a message**') #### Defined in -[speedybot.ts:624](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L624) +[speedybot.ts:626](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L626) ___ @@ -1107,7 +1090,7 @@ ___ #### Defined in -[speedybot.ts:109](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L109) +[speedybot.ts:111](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L111) ___ @@ -1129,7 +1112,7 @@ Sets the token to transact with APIs (needed to send messages, receive webhooks, #### Defined in -[speedybot.ts:100](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L100) +[speedybot.ts:102](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L102) ___ @@ -1152,7 +1135,7 @@ ___ #### Defined in -[speedybot.ts:764](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L764) +[speedybot.ts:766](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L766) ___ @@ -1173,7 +1156,7 @@ ___ #### Defined in -[speedybot.ts:782](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L782) +[speedybot.ts:784](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L784) ___ @@ -1193,7 +1176,7 @@ ___ #### Defined in -[speedybot.ts:667](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L667) +[speedybot.ts:669](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L669) ___ @@ -1207,4 +1190,4 @@ ___ #### Defined in -[speedybot.ts:1038](https://github.com/valgaze/speedybot/blob/4524beb/src/speedybot.ts#L1038) +[speedybot.ts:1046](https://github.com/valgaze/speedybot/blob/4280279/src/speedybot.ts#L1046) diff --git a/docs/api-docs/classes/SpeedyCard.md b/docs/api-docs/classes/SpeedyCard.md index 6c73628..fb9d0d3 100644 --- a/docs/api-docs/classes/SpeedyCard.md +++ b/docs/api-docs/classes/SpeedyCard.md @@ -59,7 +59,7 @@ You can add "pickers" for date, time, select (and multi-select) #### Defined in -[cards.ts:281](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L281) +[cards.ts:281](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L281) ## Properties @@ -75,7 +75,7 @@ You can add "pickers" for date, time, select (and multi-select) #### Defined in -[cards.ts:217](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L217) +[cards.ts:217](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L217) ## Methods @@ -95,7 +95,7 @@ You can add "pickers" for date, time, select (and multi-select) #### Defined in -[cards.ts:748](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L748) +[cards.ts:748](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L748) ___ @@ -119,7 +119,7 @@ ___ #### Defined in -[cards.ts:521](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L521) +[cards.ts:521](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L521) ___ @@ -141,7 +141,7 @@ ___ #### Defined in -[cards.ts:763](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L763) +[cards.ts:763](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L763) ___ @@ -162,7 +162,7 @@ ___ #### Defined in -[cards.ts:315](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L315) +[cards.ts:315](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L315) ___ @@ -183,7 +183,7 @@ ___ #### Defined in -[cards.ts:322](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L322) +[cards.ts:322](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L322) ___ @@ -203,7 +203,7 @@ ___ #### Defined in -[cards.ts:755](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L755) +[cards.ts:755](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L755) ___ @@ -224,7 +224,7 @@ ___ #### Defined in -[cards.ts:455](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L455) +[cards.ts:455](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L455) ___ @@ -248,7 +248,7 @@ ___ #### Defined in -[cards.ts:358](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L358) +[cards.ts:358](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L358) ___ @@ -269,7 +269,7 @@ ___ #### Defined in -[cards.ts:388](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L388) +[cards.ts:388](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L388) ___ @@ -290,7 +290,7 @@ ___ #### Defined in -[cards.ts:392](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L392) +[cards.ts:392](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L392) ___ @@ -311,7 +311,7 @@ ___ #### Defined in -[cards.ts:612](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L612) +[cards.ts:612](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L612) ___ @@ -332,7 +332,7 @@ ___ #### Defined in -[cards.ts:660](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L660) +[cards.ts:660](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L660) ___ @@ -353,7 +353,7 @@ ___ #### Defined in -[cards.ts:575](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L575) +[cards.ts:575](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L575) ___ @@ -374,7 +374,7 @@ ___ #### Defined in -[cards.ts:672](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L672) +[cards.ts:672](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L672) ___ @@ -395,7 +395,7 @@ ___ #### Defined in -[cards.ts:602](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L602) +[cards.ts:602](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L602) ___ @@ -416,7 +416,7 @@ ___ #### Defined in -[cards.ts:561](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L561) +[cards.ts:561](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L561) ___ @@ -436,7 +436,7 @@ ___ #### Defined in -[cards.ts:288](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L288) +[cards.ts:288](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L288) ___ @@ -457,7 +457,7 @@ ___ #### Defined in -[cards.ts:293](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L293) +[cards.ts:293](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L293) ___ @@ -484,7 +484,7 @@ ___ #### Defined in -[cards.ts:406](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L406) +[cards.ts:406](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L406) ___ @@ -505,7 +505,7 @@ ___ #### Defined in -[cards.ts:685](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L685) +[cards.ts:685](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L685) ___ @@ -526,7 +526,7 @@ ___ #### Defined in -[cards.ts:698](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L698) +[cards.ts:698](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L698) ___ @@ -546,7 +546,7 @@ ___ #### Defined in -[cards.ts:283](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L283) +[cards.ts:283](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L283) ___ @@ -566,7 +566,7 @@ ___ #### Defined in -[cards.ts:723](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L723) +[cards.ts:723](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L723) ___ @@ -580,7 +580,7 @@ ___ #### Defined in -[cards.ts:817](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L817) +[cards.ts:817](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L817) ___ @@ -594,7 +594,7 @@ ___ #### Defined in -[cards.ts:263](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L263) +[cards.ts:263](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L263) ___ @@ -614,7 +614,7 @@ ___ #### Defined in -[cards.ts:712](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L712) +[cards.ts:712](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L712) ___ @@ -634,7 +634,7 @@ ___ #### Defined in -[cards.ts:717](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L717) +[cards.ts:717](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L717) ___ @@ -655,4 +655,4 @@ ___ #### Defined in -[cards.ts:779](https://github.com/valgaze/speedybot/blob/4524beb/src/cards.ts#L779) +[cards.ts:779](https://github.com/valgaze/speedybot/blob/4280279/src/cards.ts#L779) diff --git a/docs/api-docs/modules.md b/docs/api-docs/modules.md index 61ee4fe..eab1c80 100644 --- a/docs/api-docs/modules.md +++ b/docs/api-docs/modules.md @@ -27,4 +27,4 @@ #### Defined in -[types.ts:122](https://github.com/valgaze/speedybot/blob/4524beb/src/types.ts#L122) +[types.ts:122](https://github.com/valgaze/speedybot/blob/4280279/src/types.ts#L122) diff --git a/docs/examples/lambda/README.md b/docs/examples/lambda/README.md index b92a842..6554454 100644 --- a/docs/examples/lambda/README.md +++ b/docs/examples/lambda/README.md @@ -1,10 +1,10 @@ # [QUICKSTART] λ Deploy your bot to a "serverless" AWS Lambda Function -- This example uses the **[Serverless Stack (SST)](https://serverless-stack.com/)** toolchain for provisioning, deployment of infrastructure. +- This example uses the **[Serverless Stack (SST)](https://ion.sst.dev/docs)** toolchain for provisioning, deployment of infrastructure and makes it possible to express your infrastructure needs as spec/code -- SST is built on top of a version **[AWS Cloud Development Kit (cdk)](https://aws.amazon.com/cdk/)** and makes it possible to express your infrastructure needs as spec/code. SST is definitely not required, but is the quickest route to a serverless deployment. +- SpeedyBot has been built with serverless in mind from the beginning-- serverless infrastructure is "asleep" until you need it (ie when a user sends a message, card, or file). S -- SpeedyBot has been built with serverless in mind from the beginning-- serverless infrastructure is "asleep" until you need it. Start-up times are generally fast enough to interact with the chat client withot timing out. Check out the **[Worker sample](https://speedybot.js.org/examples/worker/README)** for a fast-loading V8 Isolate without the overhead of a container +- Start-up times are generally fast enough to interact with the chat client without timing out. Check out the **[Worker sample](https://speedybot.js.org/examples/worker/README)** for a fast-loading V8 Isolate without the overhead of a container ## 1) Fetch repo & install dependencies @@ -23,7 +23,7 @@ Note: The actual code of the agent located in **packages/functions/src/settings/ - If you don't have a bot, create one and save the token from here: **[https://developer.webex.com/my-apps/new/bot](https://developer.webex.com/my-apps/new/bot)** -- Create a `.env` file like **[.env.example](./.env.example)** +- Create a `.env` file like **[.env.example](https://github.com/valgaze/speedybot/blob/v2/examples/lambda/.env.example)** ```sh WEBHOOK_SECRET=__REPLACE__ME__ diff --git a/docs/examples/llm-stream/README.md b/docs/examples/llm-stream/README.md index ca82761..224434f 100644 --- a/docs/examples/llm-stream/README.md +++ b/docs/examples/llm-stream/README.md @@ -40,7 +40,7 @@ You can set your `BOT_TOKEN` by running this script in the project directory:
Set token by hand -Copy the file **[.env.example](.env.example)** as `.env` in the root of your project and save your access token under the `BOT_TOKEN` field, ex +Copy the file **[.env.example](https://github.com/valgaze/speedybot/blob/v2/examples/llm-stream/.env.example)** as `.env` in the root of your project and save your access token under the `BOT_TOKEN` field, ex ``` BOT_TOKEN=__REPLACE__ME__ diff --git a/docs/examples/standard-server/README.md b/docs/examples/standard-server/README.md index 281ccce..e0359ab 100644 --- a/docs/examples/standard-server/README.md +++ b/docs/examples/standard-server/README.md @@ -18,7 +18,7 @@ You can set your `BOT_TOKEN` by running this script in the project directory:
Set token by hand -Copy the file **[.env.example](.env.example)** as `.env` in the root of your project and save your access token under the `BOT_TOKEN` field, ex +Copy the file **[.env.example](https://github.com/valgaze/speedybot/blob/v2/examples/standard-server/.env.example)** as `.env` in the root of your project and save your access token under the `BOT_TOKEN` field, ex ``` BOT_TOKEN=__REPLACE__ME__ diff --git a/docs/index.md b/docs/index.md index ca9c649..740d4c0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,9 +5,9 @@ hero: name: "SpeedyBot" text: "Rich conversation systems, the speedy and easy way" # tagline: Efficiently design, deploy, and secure rich conversation systems in enterprises and large teams - # image: - # src: ./assets/bongo.png - # alt: SpeedyBot + image: + src: ./sb_logo.svg + alt: SpeedyBot actions: - theme: brand text: 🚀 Get Started diff --git a/docs/new.md b/docs/new.md index 3289a01..925203a 100644 --- a/docs/new.md +++ b/docs/new.md @@ -1,4 +1,4 @@ -# "I'm new here" 🐣 +# 🐣 "I'm new here" tl;dr: SpeedyBot helps you efficiently design, deploy, and secure rich conversation systems-- especially in enterprises and large teams with complex requirements @@ -30,7 +30,7 @@ The flow to get a token will look roughly like this: Once you've got your token, pop it into the box below to validate it & review your bot's details - + ::: details Is this safe?? @@ -58,7 +58,7 @@ SpeedyBot does **NOT** log/persist or do anything (except what you tell it to do ## Step II: Send a Test Message with Your Access Token -- Let's test out your bot access token by sending a **[SpeedyCard](./speedycard.md)** to you as a direct message (tap the 🎲 to shuffle through some examples as inspiration or write your own) +- Let's test out your bot access token. You can do this by sending yourself a SpeedyCard in a direct message. Feel free to tap the 🎲 for some examples or craft your own code with the editor @@ -153,8 +153,10 @@ However you set up your system, make sure to run `node -v` in your terminal to v padding: 10px; "/> -Note: If you really want to speedy things up try it with **[Bun](https://bun.sh)** and install with +Note: If you really want to speed things up, try it with **[Bun](https://bun.sh)** and install with the following command: + `curl -fsSL https://bun.sh/install | bash` + ::: Now send a message to your bot and you'll see a welcome screen with buttons and cards: @@ -194,3 +196,33 @@ const store = useCustomStore() const type = ref(1) + + diff --git a/docs/patterns.md b/docs/patterns.md index 9d6847b..4ec33c8 100644 --- a/docs/patterns.md +++ b/docs/patterns.md @@ -49,7 +49,7 @@ When you're just starting, SpeedyBot runs your bot directly and securely from yo ## The basics -- SpeedyBot simplifies the process of creating interactive conversations and makes it easy to deploy and manage bots. Anytime your SpeedyBot receives an event from a user (a message, card, file upload, etc) it operates through a series of "steps." +- SpeedyBot streamlines the creation of conversation systems, making it easy to deploy and manage bots. When your SpeedyBot receives an event from a user (such as a message, card, or file upload), it processes the event through a sequence of steps, similar to how a car moves through a carwash. - Each step is just a function which **must** return either $.next to proceed to the next step or $.end to terminate the chain. Each step can be synchronous or asynchronous depending on what you need to do diff --git a/docs/sb_logo.svg b/docs/sb_logo.svg new file mode 100644 index 0000000..9614c59 --- /dev/null +++ b/docs/sb_logo.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/lambda/README.md b/examples/lambda/README.md index c1e054e..3097ab6 100644 --- a/examples/lambda/README.md +++ b/examples/lambda/README.md @@ -1,10 +1,10 @@ # [QUICKSTART] λ Deploy your bot to a "serverless" AWS Lambda Function -- This example uses the **[Serverless Stack (SST)](https://serverless-stack.com/)** toolchain for provisioning, deployment of infrastructure. +- This example uses the **[Serverless Stack (SST)](https://ion.sst.dev/docs)** toolchain for provisioning, deployment of infrastructure and makes it possible to express your infrastructure needs as spec/code -- SST is built on top of a version **[AWS Cloud Development Kit (cdk)](https://aws.amazon.com/cdk/)** and makes it possible to express your infrastructure needs as spec/code. SST is definitely not required, but is the quickest route to a serverless deployment. +- SpeedyBot has been built with serverless in mind from the beginning-- serverless infrastructure is "asleep" until you need it (ie when a user sends a message, card, or file). S -- SpeedyBot has been built with serverless in mind from the beginning-- serverless infrastructure is "asleep" until you need it. Start-up times are generally fast enough to interact with the chat client withot timing out. Check out the **[Worker sample](https://speedybot.js.org/examples/worker/README)** for a fast-loading V8 Isolate without the overhead of a container +- Start-up times are generally fast enough to interact with the chat client without timing out. Check out the **[Worker sample](https://speedybot.js.org/examples/worker/README)** for a fast-loading V8 Isolate without the overhead of a container ## 1) Fetch repo & install dependencies diff --git a/examples/llm-stream/README.md b/examples/llm-stream/README.md index 6d1cc76..004776c 100644 --- a/examples/llm-stream/README.md +++ b/examples/llm-stream/README.md @@ -40,7 +40,7 @@ You can set your `BOT_TOKEN` by running this script in the project directory:
Set token by hand -Copy the file **[.env.example](.env.example)** as `.env` in the root of your project and save your access token under the `BOT_TOKEN` field, ex +Copy the file **[.env.example](./.env.example)** as `.env` in the root of your project and save your access token under the `BOT_TOKEN` field, ex ``` BOT_TOKEN=__REPLACE__ME__ diff --git a/examples/llm-stream/package.json b/examples/llm-stream/package.json index e52ea4f..2f84ecc 100644 --- a/examples/llm-stream/package.json +++ b/examples/llm-stream/package.json @@ -3,14 +3,18 @@ "version": "1.0.0", "description": "", "scripts": { - "bot:dev": "tsx watch settings/launch", + "bot:on": "tsx util/launch", "serve": "npm run bot:dev", - "start": "npm run bot:dev", "dev": "npm run bot:dev", + "bot:debug": "npx -y envinfo@7.11.0", + "bot:serve": "npm run bot:dev", + "bot:dev": "tsx watch util/launch", + "bot:reset": "tsx util/cli reset", "bot:setup": "tsx util/cli setup", - "bot:debug": "npx envinfo@7.11.0", - "bot:addsecret": "tsx util/cli addsecret", - "bot:help": "tsx util/cli help" + "bot:token": "npm run bot:setup", + "bot:help": "tsx util/cli help", + "help": "npm run bot:help", + "bot:addsecret": "tsx util/cli addsecret" }, "keywords": [], "author": "", @@ -21,12 +25,11 @@ }, "devDependencies": { "@types/express": "^4.17.21", - "@babel/runtime-corejs2": "^7.20.1", "@types/node": "^16.18.3", "cross-fetch": "^3.1.5", "dotenv": "^16.0.3", "tsx": "^4.7.0", "typescript": "^3.8.3", - "webex": "^2.31.0" + "ws": "^8.17.0" } } diff --git a/examples/llm-stream/util/cli.ts b/examples/llm-stream/util/cli.ts index cf2281a..8e1cdd2 100644 --- a/examples/llm-stream/util/cli.ts +++ b/examples/llm-stream/util/cli.ts @@ -1,11 +1,10 @@ // #!/usr/bin/env node +import * as dotenv from "dotenv"; +import { resolve } from "path"; import * as fs from "fs/promises"; import * as readline from "readline"; -import { resetDevices } from "./utils"; -import { resolve } from "path"; -import * as dotenv from "dotenv"; - import { botTokenKey, logoRoll } from "speedybot"; +import { LocalSockets } from "./websockets"; // Expects .env to get token on BOT_TOKEN dotenv.config({ path: resolve(__dirname, "..", ".env") }); @@ -46,7 +45,9 @@ async function resetBot(token) { "Enter your token, [Usage: npm run bot:reset ]" ); } - await resetDevices(finalToken); + + const websockets = new LocalSockets(finalToken); + await websockets.resetDevices(); console.log("Reset attempted"); } diff --git a/examples/llm-stream/util/index.ts b/examples/llm-stream/util/index.ts index 81f89c9..9c865ed 100644 --- a/examples/llm-stream/util/index.ts +++ b/examples/llm-stream/util/index.ts @@ -1,56 +1,6 @@ -import { SpeedyBot, logoRoll } from "speedybot"; -import { Websocket } from "./utils"; import { resolve } from "path"; -export const websocketLauncher = async ( - BotRef: SpeedyBot, - cb?: (data?: { email: string; name?: string }) => any -) => { - const token = BotRef.getToken(); - if (!token) { - throw new Error( - `SpeedyBot must have token specified before launching websockets, set with Bot.setToken()` - ); - } - - const inst = new Websocket(token); - try { - await inst.start(); - - inst.on("message", (websocketEvent: any) => { - BotRef.runMiddleware(websocketEvent); - }); - - inst.on("submit", (websocketSubmitEvent: any) => { - BotRef.runMiddleware(websocketSubmitEvent); - }); - - const data = await BotRef.getSelf(); - const { displayName } = data; - const [email] = data.emails; - - if (!cb) { - announceWebsockets(email, displayName); - } else { - return cb({ email, name: displayName }); - } - } catch (e) { - throw e; - } -}; -export const announceWebsockets = (email: string, name = "Your bot") => { - const isColorSupported = process.stdout.isTTY; - console.log(logoRoll()); - if (isColorSupported) { - const WEBSOCKETS_READY = `\x1b[1m\x1b[7m\x1b[32m 🌐 CONNECTED \x1b[0m\x1b[32m Websockets active, listening...\x1b[0m`; - process.stdout.write(WEBSOCKETS_READY + "\n"); - } else { - console.log("Websockets Registered. Listening..."); - } - console.log(`You can reach ${name} here: ${email}`); -}; - -export const announceExit = (name = "Your bot") => { +export const announceExit = (name?: string) => { const isColorSupported = process.stdout.isTTY; if (isColorSupported) { const BOT_DISCONNECTED = `\n\x1b[1m\x1b[7m\x1b[31m 🤖 DISCONNECTED \x1b[0m\x1b[31m Bot is now offline. \x1b[0m`; @@ -60,14 +10,15 @@ export const announceExit = (name = "Your bot") => { } console.log( ` -Your bot is now "off" - -You can turn your bot back on by entering the following commands: - -cd ${resolve(__dirname, "..")} -npm run dev - -If you want to deploy your bot to a persistent server or serverless function, see here: https://speedybot.js.org/examples -` + ${name ? name : "Your bot"} is now "off" + + You can turn your bot back on by entering the following commands: + + cd ${resolve(__dirname, "..")} + npm run dev + + If you want to deploy your bot to a persistent server or serverless function, see here: + https://speedybot.js.org/examples + ` ); }; diff --git a/examples/llm-stream/util/launch.ts b/examples/llm-stream/util/launch.ts new file mode 100644 index 0000000..1ea152f --- /dev/null +++ b/examples/llm-stream/util/launch.ts @@ -0,0 +1,13 @@ +import "cross-fetch/polyfill"; +import { config } from "dotenv"; +import { resolve } from "path"; +import { announceExit } from "./index"; +process.on("exit", announceExit); + +config({ path: resolve(__dirname, "..", ".env") }); + +import { SpeedySockets } from "./websockets"; +import Bot from "./../settings/bot"; + +Bot.setToken(process.env.BOT_TOKEN as string); +SpeedySockets(Bot, { force: false, debug: false }).catch((e) => console.log(e)); diff --git a/examples/llm-stream/util/websockets.ts b/examples/llm-stream/util/websockets.ts new file mode 100644 index 0000000..9c917b7 --- /dev/null +++ b/examples/llm-stream/util/websockets.ts @@ -0,0 +1,658 @@ +// Author: @valgaze +// Websockets are super useful but painful to use sometimes +// use bun or install Websocket with: +// $ npm install ws +import WebSocket from "ws"; // optional + +import { + type AA_Envelope, + type File_Details, + type MessageEnvelope, + type Message_Details, + type Submit_Details, + type SelfData, + SpeedyBot, +} from "speedybot"; + +import { logoRoll } from "speedybot"; + +// all the things that can go wrong :( +enum ErrorType { + HTTP_REQUEST_FAILED = "HTTP_REQUEST_FAILED", + WEBSOCKET_ERROR = "WEBSOCKET_ERROR", + INVALID_TOKEN = "INVALID_TOKEN", // 401 + EXCESSIVE_DEVICE = "EXCESSIVE_DEVICE", + UNKNOWN_ERROR = "UNKNOWN_ERROR", + FORBIDDEN_ERROR = "ERROR_FORBIDDEN", +} + +export type AbbeviatedDevice = { + url: string; + webSocketUrl: string; + services: unknown; + deviceType: string; + name: string; + model: string; + localizedModel: string; + systemName: string; + systemVersion: string; + capabilities: unknown; + features: unknown; + creationTime: string; + modificationTime: string; + deviceSettings: unknown; + deviceSettingsString: string; + showSupportText: boolean; + reportingSiteUrl: string; + reportingSiteDesc: string; + isDeviceManaged: boolean; + trainSiteNames: unknown[]; + clientSecurityPolicy: string; + intranetInactivityCheckUrl: string; + serviceHostMap: unknown; + blockExternalCommunications: boolean; + desktopFileShareControl: string; + mobileFileShareControl: string; + webFileShareControl: string; + botFileShareControl: string; + whiteboardFileShareControl: string; + clientMessagingGiphy: string; + clientMessagingLinkPreview: string; + ecmEnabledForAllUsers: boolean; + ecmSupportedStorageProviders: string[]; + defaultEcmMicrosoftCloud: string; + ecmMicrosoftTenant: string; + ecmScreenCaptureFeatureAllowed: boolean; + ecmWhiteboardFileDataAllowed: boolean; + callingBehavior: string; + onPremisePairingEnabled: boolean; + peopleInsightsEnabled: boolean; + allowSelfSignedCertificate: boolean; + webexCrossLaunch: boolean; + webexAppHubEnabled: boolean; + embeddedAppsEnabled: boolean; + settings: unknown; + selfSignupOrg: boolean; + userId: string; + orgId: string; + orgName: string; +}; + +export type Events = "text" | "card"; + +export type Data = { + [key: string]: any; +}; +export type BaseEnvelope = { + id: string; + name: string; + targetUrl: string; + resource: string; + event: string; + orgId: string; + createdBy: string; + appId: string; + ownedBy: string; + status: string; + created: Date; + actorId: string; + data: Data; +}; +export type MessagePayload = { + id: string; + timestamp: string | number; + data: { + eventType: + | "status.start_typing" // for first-press situations + | "conversation.activity" + | "conversation.highlight"; + activity?: { + id: string; + verb: "cardAction" | "post" | "acknowledge" | "update" | "share"; + actor: { + id: string; // email + objectType: string; + displayName: string; + orgId: string; + emailAddress: string; + entryUUID: string; + type: string; + }; + target: { + id: string; + objectType: string; + url: string; + published: string; + participants: { + items: any[]; + }; + activities: { + items: any[]; + }; + deletedActivityIds: any[]; + tags: string[]; + globalId: string; + }; + }; + }; +}; +export type SocketConfig = { debug: boolean; force?: boolean }; + +/** + * config: + * debug: show logs (noisy) + * force: force a new websocket connection each time (might cause excessive device registration) + */ +export class LocalSockets { + private submitFcn!: (AAEnv: AA_Envelope) => Promise | void; + onSubmit(cb: (AAEnv: AA_Envelope) => Promise | void) { + this.submitFcn = cb; + } + + private msgFcn!: (MsgEnv: MessageEnvelope) => Promise | void; + onText(cb: (MsgEnv: MessageEnvelope) => Promise | void) { + this.msgFcn = cb; + } + + private ws!: WebSocket; + constructor( + private _token: string, + private config: SocketConfig = { + debug: false, + force: false, + } + ) { + this.root = { + DEVICES_URL: "https://wdm-a.wbx2.com/wdm/api/v1/devices", + DEVICE_DATA: { + deviceName: "SpeedyBot-websockets", + deviceType: "DESKTOP", + localizedModel: "SpeedyBot", + model: "SpeedyBot", + name: this.config.force + ? `speedy-webex-${Math.random().toString(36).slice(2, 7)}` + : "speedybot-webex-reusable-websocket", + systemName: "SpeedyBot", + systemVersion: "1.0", + }, + }; + } + + private root: { + DEVICES_URL: string; + DEVICE_DATA: { + deviceName: string; + deviceType: string; + localizedModel: string; + model: string; + name: string; + systemName: string; + systemVersion: string; + }; + }; + + public log(...payload: any): void { + if (this.config.debug) + console.log.apply(console, [ + "[Speedy-Debug]", + ...(payload as [any?, ...any[]]), + ]); + } + + async start(): Promise { + this.log(`Getting device info...`); + this.log(this.root.DEVICE_DATA.name); + let device = await this.getDeviceInfo(); + if (!device || this.config.force) { + this.log( + `${ + this.config.force + ? "Force new device creation..." + : "Empty device refetching..." + }` + ); + device = await this.createDevice(); + this.log(`Device set`); + } + + if (this.ws) { + this.log(`Attempting socket disconnect`); + await this.disconnect(); + } + + if (device && "webSocketUrl" in device) { + this.log(`Registering websockets with + ${device.webSocketUrl}`); + this.log(`Device name: ${device.name}`); + await this.registerWebsockets(device.webSocketUrl); + this.log(`✅ websockets success`); + return true; + } else { + this.log(`🛑 websockets failure`); + return false; + } + } + + private buildUUID() { + return Math.random().toString(36).slice(2); + } + + handleApplicationError(error: any, errorType: ErrorType, message?: string) { + switch (errorType) { + case ErrorType.HTTP_REQUEST_FAILED: + console.error("HTTP request failed:", message, error); + break; + case ErrorType.WEBSOCKET_ERROR: + console.error("WebSocket error:", message, error); + break; + case ErrorType.INVALID_TOKEN: + console.error("Invalid token error:", message, error); + break; + case ErrorType.EXCESSIVE_DEVICE: + console.error("Excessive device registration error:", message, error); + break; + default: + console.error("Unknown error:", message, error); + break; + } + } + + private async createDevice(): Promise { + try { + const response = await fetch(this.root.DEVICES_URL, { + method: "POST", + headers: { + Authorization: `Bearer ${this._token}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(this.root.DEVICE_DATA), + }); + + if (!response.ok) { + if (response.status === 429 || response.status === 403) { + /** + * + * + { + message: "User has excessive device registrations", + errors: [ + { + description: "User has excessive device registrations", + } + ], + trackingId: "xxxxx", +} + * + */ + + throw new Error(ErrorType.EXCESSIVE_DEVICE); + } else { + throw new Error(ErrorType.UNKNOWN_ERROR); + } + } + const device = (await response.json()) as AbbeviatedDevice; + return device; + } catch (error: unknown) { + if (typeof error === "object" && error && "message" in error) { + if (error.message === ErrorType.EXCESSIVE_DEVICE) { + this.handleApplicationError( + error, + ErrorType.EXCESSIVE_DEVICE, + "WebSocket connection error" + ); + } else if (error.message === ErrorType.FORBIDDEN_ERROR) { + this.handleApplicationError( + error, + ErrorType.FORBIDDEN_ERROR, + "403 forbidden" + ); + } else { + this.handleApplicationError( + error, + ErrorType.UNKNOWN_ERROR, + "Unknown error on creation" + ); + } + } + } + } + + private async getDeviceInfo(): Promise { + try { + const response = await fetch(this.root.DEVICES_URL, { + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + + if (!response.ok && response.status === 401) { + throw new Error(ErrorType.INVALID_TOKEN); + } + + const data = (await response.json()) as + | { devices: AbbeviatedDevice[] } + | { + message: string; + errors: { description: string }[]; + trackingId: string; + }; + if ("devices" in data) { + this.log(`Total devices: ${data.devices.length}`); + const device = data.devices.find( + (device: any) => device.name === this.root.DEVICE_DATA.name + ); + return device; + } + } catch (error) { + if (typeof error === "object" && error && "message" in error) { + this.handleApplicationError( + error, + ErrorType.INVALID_TOKEN, + `[❌ SpeedyBot] Token invalid-- double check the token is correct or you can regenerate a new one here: +https://developer.webex.com/my-apps + +` + ); + } + } + } + + public async resetDevices() { + type Device = { + url: string; + webSocketUrl: string; + services: unknown; + }; + + try { + const deviceListResponse = await fetch( + "https://wdm-a.wbx2.com/wdm/api/v1/devices", + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + + if (!deviceListResponse.ok) { + if (deviceListResponse.status === 401) { + this.log(`Reset devices invalid token`); + throw new Error(ErrorType.INVALID_TOKEN); + } + throw new Error(ErrorType.HTTP_REQUEST_FAILED); + } + + const { devices = [] }: { devices: Device[] } = + (await deviceListResponse.json()) as { devices: Device[] }; + + for (const device of devices) { + const { url } = device; + if (url) { + const deleteResponse = await fetch(url, { + method: "DELETE", + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + + if (!deleteResponse.ok) { + throw new Error(ErrorType.HTTP_REQUEST_FAILED); + } + } + } + + return true; + } catch (error) { + if (error instanceof Error) { + if (error.message === ErrorType.HTTP_REQUEST_FAILED) { + this.handleApplicationError( + error, + ErrorType.HTTP_REQUEST_FAILED, + "Failed to reset devices" + ); + } else if (error.message === ErrorType.INVALID_TOKEN) { + this.handleApplicationError( + error, + ErrorType.INVALID_TOKEN, + `[❌ SpeedyBot] Token invalid-- double check the token is correct or you can regenerate a new one here: +https://developer.webex.com/my-apps + + ` + ); + } else { + this.handleApplicationError( + error, + ErrorType.UNKNOWN_ERROR, + "Unknown error while resetting devices" + ); + } + } + return false; + } + } + + public registerWebsockets(webSocketUrl: string) { + this.ws = new WebSocket(webSocketUrl); + this.ws.on("open", async () => { + this.log("🎸 Websocket open"); + const msg = { + id: this.buildUUID(), + type: "authorization", + data: { + token: `Bearer ${this._token}`, + }, + }; + this.ws.send(JSON.stringify(msg)); + }); + + this.ws.on("message", async (message: string) => { + try { + const msg = JSON.parse(message); + this.log(`📬 raw message received ${JSON.stringify(msg)}\n`); + await this.processMessage(msg); + } catch (error: unknown) { + if (typeof error === "object" && error && "message" in error) { + this.handleApplicationError( + error, + ErrorType.WEBSOCKET_ERROR, + "WebSocket error on message" + ); + } + } + }); + + this.ws.on("error", (error) => { + this.handleApplicationError( + error, + ErrorType.WEBSOCKET_ERROR, + "WebSocket connection error" + ); + }); + } + + public disconnect() { + if (this.ws) { + return this.ws.close(); + } + } + + private async checkEmail(email: string) { + const emailRes = await fetch("https://webexapis.com/v1/people/me", { + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + const { emails } = (await emailRes.json()) as SelfData; + const [myEmail] = emails; + return email !== myEmail; + } + + private async fetchMessagePayload(id: string): Promise { + const messageId = id.includes("-") + ? Buffer.from(`ciscospark://us/MESSAGE/${id}`).toString("base64") + : id; + + const response = await fetch( + `https://webexapis.com/v1/messages/${messageId}`, + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + const data = (await response.json()) as Message_Details; + return data; + } + + private async fetchCardPayload(id: string): Promise { + const attachmentActionId = id.includes("-") + ? Buffer.from(`ciscospark://us/ATTACHMENT_ACTION/${id}`).toString( + "base64" + ) + : id; + const response = await fetch( + `https://webexapis.com/v1/attachment/actions/${attachmentActionId}`, + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + const data = (await response.json()) as Promise; + return data; + } + + async processMessage(msg: MessagePayload): Promise { + if ( + msg.data.eventType === "conversation.activity" && + "activity" in msg.data && + msg.data.activity + ) { + const { id, verb, actor } = msg.data.activity; + const { emailAddress } = actor; + const proceed = await this.checkEmail(emailAddress); + if (!proceed) return false; // filter out mesages from agent + + // text [post] or file [share] message + if (verb === "post" || verb === "share") { + if (this.msgFcn) { + const payload = await this.fetchMessagePayload(id); + this.log(`[${verb}]`, id, payload); + const env = this.buildText(payload); + await this.msgFcn(env); + } + } + + // if adaptive card/attachmentAction submission [cardAction] + if (verb === "cardAction") { + if (this.submitFcn) { + const payload = await this.fetchCardPayload(id); + this.log("[cardAction]", payload); + const env = this.buildCard(payload); + await this.submitFcn(env); + } + } + } + + return true; + } + + setToken(token: string) { + this._token = token; + } + + getToken(): string { + return this._token; + } + + private buildText(payload: Message_Details | File_Details): MessageEnvelope { + return { + id: "__websocket_id", + name: "__websocket_name", + targetUrl: "__websocket_targetUrl", + resource: "messages", + event: "created", + orgId: "__websocket_orgId", + createdBy: "__websocket_createdBy", + appId: "__websocket_appId", + ownedBy: "creator", + status: "active", + created: new Date().toISOString(), + actorId: "__websocket_actorId", + data: payload, + }; + } + + private buildCard(payload: Submit_Details): AA_Envelope { + return { + id: "__websocket_id", + name: "__websocket_name", + targetUrl: "__websocket_targetUrl", + resource: "attachmentActions", + event: "created", + orgId: "__websocket_orgId", + createdBy: "__websocket_createdBy", + appId: "__websocket_appId", + ownedBy: "creator", + status: "active", + created: new Date().toISOString(), + actorId: "__websocket_actorId", + data: payload, + }; + } +} + +export const announceWebsockets = (email: string, name = "Your bot") => { + const isColorSupported = process.stdout.isTTY; + console.log(logoRoll()); + if (isColorSupported) { + const WEBSOCKETS_READY = `\x1b[1m\x1b[7m\x1b[32m 🌐 CONNECTED \x1b[0m\x1b[32m Websockets active, listening...\x1b[0m`; + process.stdout.write(WEBSOCKETS_READY + "\n"); + } else { + console.log("Websockets Registered. Listening..."); + } + console.log(`You can reach ${name} here: ${email}`); +}; + +/** + * Helper to surround SpeedyBot instance with websockets + * + */ +export async function SpeedySockets( + BotRef: SpeedyBot, + config: SocketConfig = { + debug: false, + force: false, + }, + cb?: (data?: { email: string; name?: string }) => any +): Promise { + try { + const token = BotRef.getToken(); + if (!token) { + throw new Error("No token provided (try Bot.setToken('__REPLACE__ME__')"); + } + const inst = new LocalSockets(token, config); + + inst.onSubmit(async (payload) => { + BotRef.runMiddleware(payload); + }); + + inst.onText((payload) => { + BotRef.runMiddleware(payload); + }); + + await inst.start(); + const data = await BotRef.getSelf(); + const { displayName } = data; + const [email] = data.emails; + + if (!cb) { + announceWebsockets(email, displayName); + } else { + return cb({ email, name: displayName }); + } + } catch (e) { + console.log(e); + throw e; + } +} diff --git a/examples/location/settings/location.ts b/examples/location/settings/location.ts index d80caf3..376ab2b 100644 --- a/examples/location/settings/location.ts +++ b/examples/location/settings/location.ts @@ -5,7 +5,7 @@ export async function locationHandler(bot: typeof Bot, roomId: string, locationD const locationCard = Bot.card() .addTitle(`Good ${locationData.tod}`) .addSubtitle( - `Note: this timezone + location data is not stored/collected/sold and is not hyper-accurate. It's accurate enough to understand if its dark/light outside whenever a user is located` + `Note: this timezone + location data is not stored/collected/sold and is not hyper-accurate. It's accurate enough to understand if its dark/light outside wherever a user is located` ) .addTable([ ['Country', locationData.country], diff --git a/examples/speedybot-starter-legacy/.env.example b/examples/speedybot-starter-legacy/.env.example new file mode 100644 index 0000000..62e2abc --- /dev/null +++ b/examples/speedybot-starter-legacy/.env.example @@ -0,0 +1,7 @@ +BOT_TOKEN=__REPLACE__ME__ + +# $ npm run bot:setup to write token to above + +# OR: +# Save this file as .env with: $ cp .env.example .env +# Replace BOT_TOKEN with your Bot Access token (if you don't have one get one here: https://developer.webex.com/my-apps/new/bot \ No newline at end of file diff --git a/examples/speedybot-starter-legacy/.gitignore b/examples/speedybot-starter-legacy/.gitignore new file mode 100644 index 0000000..a30356d --- /dev/null +++ b/examples/speedybot-starter-legacy/.gitignore @@ -0,0 +1,3 @@ +.DS_STORE +.env +node_modules \ No newline at end of file diff --git a/examples/speedybot-starter-legacy/README.md b/examples/speedybot-starter-legacy/README.md new file mode 100644 index 0000000..9cb8224 --- /dev/null +++ b/examples/speedybot-starter-legacy/README.md @@ -0,0 +1,76 @@ +## Speedybot Starter + +## 1) Clone repo & install dependencies + +``` +git clone https://github.com/valgaze/speedybot +cd examples/speedybot-starter +npm install +``` + +## 2) Set your bot access token + +- Make a new bot and note its access token from here: **[https://developer.webex.com/my-apps/new/bot](https://developer.webex.com/my-apps/new/bot)** + +You can set your `BOT_TOKEN` by running this script in the project directory: + +`npm run bot:setup ` + +
Set token by hand +Copy the file **[.env.example](.env.example)** as `.env` in the root of your project and save your access token under the `BOT_TOKEN` field, ex + +``` +BOT_TOKEN=__REPLACE__ME__ +``` + +
+ +## 3) Boot it up! + +- Start up your agent + +Note: By default your agent will communicate using websockets, so you won't need to worry about details like deployment or webhooks. Later down the line if you need to deploy your agent on a traditional server or ephemeral/serverless function infrastructure **[see the examples](https://speedybot.js.org/examples)** + +``` +npm run bot:dev +``` + +## NPM Run Scripts + +All you'll probably need are `npm run bot:dev` + maybe `npm run bot:reset` + +| Script | Description | +| ----------------------- | ---------------------------------------------- | +| `npm run bot:on` | Launches the SpeedyBot | +| `npm run serve` | Alias for npm run bot:dev | +| `npm run dev` | Alias for npm run bot:dev | +| `npm run bot:debug` | Displays environment information for debugging | +| `npm run bot:dev` | Launches the bot in development mode | +| `npm run bot:reset` | Resets the bot's configuration | +| `npm run bot:setup` | Sets up the bot for the first time | +| `npm run bot:token` | Alias for npm run bot:setup | +| `npm run bot:help` | Displays help information for the bot | +| `npm run help` | Alias for npm run bot:help | +| `npm run bot:addsecret` | Adds a secret to the bot's configuration | + +
Getting errors? + +If you see an error like `npm: command not found` you probably need to install node or compatible runtime (like **[bun](https://bun.sh)** or **[deno](https://deno.com)**) onto your system. + +There are many ways to do this, but two easy ways: + +Option 1. Download + install Node from the official site: **[https://nodejs.org/en/download](https://nodejs.org/en/download)** + +Option 2. Download with **[Volta](https://docs.volta.sh/guide/)** in the terminal + +```sh +curl https://get.volta.sh | bash + +volta install node +``` + +However you set up your system, make sure to run `node -v` in your terminal to verify node is correctly installed and you can take advantage of its rich ecoysten + +
+ +If you see an error that reads somnething like `Forbidden: User has excessive device registrations` you can run `npm run bot:reset`, wait a few minutes and try again diff --git a/examples/speedybot-starter-legacy/package.json b/examples/speedybot-starter-legacy/package.json new file mode 100644 index 0000000..6c1f338 --- /dev/null +++ b/examples/speedybot-starter-legacy/package.json @@ -0,0 +1,44 @@ +{ + "name": "speedybot-starter", + "version": "2.0.0", + "description": "The speedy and easy way to build rich bots + conversation experiences", + "main": "index.ts", + "scripts": { + "bot:on": "tsx settings/launch", + "serve": "npm run bot:dev", + "dev": "npm run bot:dev", + "bot:debug": "npx -y envinfo@7.11.0", + "bot:serve": "npm run bot:dev", + "bot:dev": "tsx watch settings/launch", + "bot:reset": "tsx util/cli reset", + "bot:setup": "tsx util/cli setup", + "bot:token": "npm run bot:setup", + "bot:help": "tsx util/cli help", + "help": "npm run bot:help", + "bot:addsecret": "tsx util/cli addsecret" + }, + "keywords": [ + "bot", + "scaffold", + "continerless", + "speedybot", + "serverless" + ], + "author": "valgaze@gmail.com", + "license": "MIT", + "devDependencies": { + "@babel/runtime-corejs2": "^7.20.1", + "@types/node": "^16.18.3", + "cross-fetch": "^3.1.5", + "dotenv": "^16.0.3", + "tsx": "^4.7.0", + "typescript": "^3.8.3", + "webex": "^2.31.0" + }, + "dependencies": { + "speedybot": "^2.0.0" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/examples/speedybot-starter-legacy/settings/bot.ts b/examples/speedybot-starter-legacy/settings/bot.ts new file mode 100644 index 0000000..5d8d58d --- /dev/null +++ b/examples/speedybot-starter-legacy/settings/bot.ts @@ -0,0 +1,718 @@ +import { SpeedyBot, SpeedyCard, SurveyQuestion } from "speedybot"; + +const Bot = new SpeedyBot(); + +Bot.addStep(async ($) => { + // handle text + if ($.text) { + if ($.text.toLowerCase() === "showcard") { + const card = $.card() + .addTitle("Capture data") + .addTextarea("Submit data") + .addPickerDropdown(["option 1", "option 2", "option 3", "option 4"]); + await $.send(card); + } + } + + // file handler + if ($.file) { + const { name, extension, contentType } = $.file; + await $.send( + `You uploaded "${name}", a *.${extension} file [${contentType}]` + ); + // Fetch raw bytes (which you can pass onto other systems) + // const TheData = await $.file.getData(); // do something w/ the contents/bytes + } + + // adaptive card/form submissions + if ($.data && !$.data.showCard && !$.data.randomSpeedyBot) { + const dataSnippet = $.buildDataSnippet($.data); + await $.send(`This data was submitted:`); + await $.send(dataSnippet); + } + + return $.next; +}); + +Bot.addStep(async ($) => { + if ($.data && $.data.randomSpeedyBot) { + const randomImage = `https://raw.githubusercontent.com/valgaze/speedybot-utils/main/assets/memes/logo${$.pickRandom( + 1, + 33 + )}.jpeg`; + + await $.send( + $.card() + .addHeader("\u{1F916} SpeedyBot") + .addImage(randomImage, { + targetURL: "https://speedybot.js.org", + size: "ExtraLarge", + }) + .addButton("🤖 Show another SpeedyBot", "randomSpeedyBot") + ); + return $.end; + } + return $.next; +}); + +// ## File upload handler +Bot.addStep(async ($) => { + if ($.file) { + const { name, extension, contentType } = $.file; + await $.send( + `You uploaded "${name}", a *.${extension} file [${contentType}]` + ); + // Fetch raw bytes (which you can send to database or send to external system) + // const TheData = await $.file.getData(); // do something w/ the contents/bytes + } + return $.next; +}); + +// ## "ping/pong", run logic on inputs +Bot.addStep(async ($) => { + if ($.text) { + const lowered = $.text.toLowerCase(); + if (lowered === "ping") { + await $.send("pong"); + return $.end; + } else if (lowered === "pong") { + await $.send("ping"); + return $.end; + } + } + return $.next; // pass through to rest of steps +}); + +// ## "show-cards, show adaptive cards +Bot.addStep(async ($) => { + if ($.text) { + const lowered = $.text.toLowerCase(); + if (lowered === "show-cards") { + await $.send( + "SpeedyCards make it easy to send rich, interactive cards to the user" + ); + const { value } = Bot.pickRandom(cardChoices); + const card = cardHash[value].addSubcard( + $.card() + .addLink( + `https://speedybot.js.org/speedycard?card=${value}`, + "See the source for this card" + ) + .addText("Pick a new card") + .addPickerDropdown(cardChoices, "showCard"), + "Learn more" + ); + await $.send(card); + return $.end; + } + } + return $.next; // pass through to rest of steps +}); + +// ## "files", show file capabilities (not upload file-- different idea-- but sending data to the user as a file) +Bot.addStep(async ($) => { + if ($.text && $.text.toLowerCase() === "files") { + await $.send( + `You can of course upload files but SpeedyBot also provides handy features to send data to the user as files` + ); + + // send a *.json file + const fileData = $.debug(); + await $.sendFile(fileData, "json"); + + // Send HTML w/ dynamic data + await $.sendFile( + makeHTML(`Here's your generated file, ${$.author.name}`, fileData), + "html" + ); + return $.end; + } else { + return $.next; + } +}); + +// ## "kitchensink", show everything +Bot.addStep(async ($) => { + $.author; + if ($.text && ["kitchen", "kitchensink"].includes($.text)) { + await $.clearScreen(); + await $.send(`## Kitchen Sink`); + + await $.thread([ + $.card({ + title: `This is a 'thread'`, + subTitle: "You can have many entries after the 1st", + chips: [ + { + title: "Go Again 🔄", + value: "kitchensink", + }, + ], + }) + .addText("Pick an entry from the list to preview a SpeedyCard") + .addPickerDropdown(cardChoices, "showCard"), + "thread item 1", + "thread item 2", + "thread item 3", + "thread item 4", + "thread item 5", + ]); + + await $.send(`-----------`); + await $.send($.buildDMLink("speedybot@webex.bot", "🤖 Talk to SpeedyBot")); + await $.send(`-----------`); + + await $.send(`## Files`); + + // Send data as a *.json file + await $.send(`Send data to user (here as *.json or *.html)`); + const fileData = $.debug(); + await $.sendFile(fileData, "json"); + await $.sendFile( + makeHTML(`Here's your generated file, ${$.author.name}`, fileData), + "html" + ); + return $.end; + } + return $.next; +}); + +// ## Main greeting +Bot.addStep(async ($) => { + if ($.text && !$.file) { + const utterances = [ + `Heya how's it going $[name]?`, + `Hi there, $[name]!`, + `Hiya $[name]!`, + `What's new $[name]?`, + `Helllooo $[name]!`, + ]; + const template = { + name: $.author.name, + }; + await $.send($.fillTemplate(utterances, template)); + + const randomImage = `https://raw.githubusercontent.com/valgaze/speedybot-utils/main/assets/memes/logo${$.pickRandom( + 1, + 33 + )}.jpeg`; + + const introCard = $.card() + .addHeader("🤖 SpeedyBot") + .addImage(randomImage, { + targetURL: "https://speedybot.js.org", + size: "ExtraLarge", + }) + .addChips([ + { title: "SpeedyCards 🌠", value: "show-cards" }, + { title: "ping 🏓", value: "ping" }, + { title: "🏓 pong", value: "pong" }, + { title: "🗂 files", value: "files" }, + { title: "🗂 Everything (warning: fast)", value: "kitchensink" }, + ]) + .addButton("🤖 random", "randomSpeedyBot") + .addSubcard( + $.card() + .addTitle("SpeedyCards") + .addText( + "**SpeedyCards** make it easy to build cards that deliver information in a visually attractive way or craft or cards with interactive forms that will let you capture structured data submitted from users" + ) + .addText("Pick a new card template") + .addPickerDropdown(cardChoices, "showCard"), + "See More " + ); + await $.send(introCard); + return $.next; + } + return $.next; +}); + +// ## Card utilities +// SpeedyCard form submissions, check for $.data, can add generics for type assurance + +// handle card picks from dropdown, attach preview, this can happen from multiple cards + locations +Bot.addStep>(async ($) => { + type CardKey = keyof typeof cardHash; + const isCardKey = (key: CardKey | undefined): key is CardKey => { + return key !== undefined && key in cardHash; + }; + + if ($.data && isCardKey($.data.showCard)) { + const card = cardHash[$.data.showCard].addSubcard( + $.card() + .addLink( + `https://speedybot.js.org/speedycard?card=${$.data.showCard}`, + "See the source for this card" + ) + .addText("Pick a new card") + .addPickerDropdown(cardChoices, "showCard"), + "Learn more" + ); + await $.send(card); + } + + return $.next; +}); + +// ## ex. pass data/flags between steps during runs +Bot.addStep(($) => { + $.ctx.isDev = true; // set to true on debug mode to trace incoming messages + return $.next; +}); + +// ## read flags +Bot.addStep(async ($) => { + // if ($.ctx.isDev) { + // await $.send($.buildDataSnippet($.debug())); + // } + return $.next; +}); + +// short-hand for exact match +Bot.exact("$clear", async ($) => { + await $.clearScreen(); + return $.end; +}); + +// ## Don't leave users hanging +Bot.captureError(async (payload) => { + const { roomId } = payload; + if (roomId) + await Bot.sendTo(roomId, `Whoops, there was a problem: ${payload.message}`); +}); +// export the Bot +export default Bot; + +// Bunch of cards +export const cardChoices = [ + { title: "Text Formatting 📄", value: "format-card" }, + { title: "Tabular Data 🐸", value: "table-card" }, + { title: "Survey 📝", value: "survey" }, + { title: "Acai 🍇", value: "acai" }, + { title: "Appcard 💳", value: "appcard" }, + { title: "Appcard RTL ⬅️", value: "appcard-rtl" }, + { title: "Red Danger 🔴", value: "red-danger" }, + { title: "Green Success ✅", value: "green-success" }, + { title: "Yellow Warning ⚠️", value: "yellow-warning" }, + { title: "Banner Yellow 🟡", value: "banner-yellow" }, + { title: "Confirm ✔️", value: "confirm" }, + { title: "Image 🖼️", value: "image" }, + { title: "Old Survey", value: "old-survey" }, +]; + +export const cardHash: { [key: string]: SpeedyCard } = { + survey: Bot.card().survey([ + { + type: "text", + question: "What is the name of your company?", + id: "company_name", + }, + { + type: "text", + question: "Describe the service performed by the vendor.", + id: "service_type", + }, + { + type: "picker-date", + question: "When was the service provided?", + id: "service_date", + }, + { + type: "single-select", + question: "How would you rate the quality of service?", + choices: ["Excellent", "Good", "Average", "Poor", "Very poor"], + id: "service_quality", + }, + { + type: "multi-select", + question: "What were the highlights of the service?", + choices: [ + "Communication", + "Punctuality", + "Time to Resolution", + "Friendliness", + "Cost", + ], + id: "service_highlights", + }, + { + type: "single-select", + question: "Would you consider using our services again in the future?", + choices: [ + "Definitely", + "Probably", + "Not sure", + "Probably not", + "Definitely not", + ], + id: "future_use", + }, + { + type: "textarea", + question: + "Please provide any other comments or suggestions for improvement.", + id: "other_comments", + }, + { + type: "picker-time", + question: "What time of day is preferable for future contact?", + id: "preferred_contact_time", + }, + { + type: "picker-dropdown", + question: "Preferred method of communication for future updates?", + choices: ["Email", "Phone", "Text"], + id: "communication_method", + }, + ]), + "format-card": Bot.card() + .addHeader("🌟 Formatted Card 🌟") + .addTitle("SpeedyCards can fit a lot of text + visual formatting") + .addText("You do lots of fun things with text", { size: "Large" }) + .addText("You can change colors", { size: "Large", color: "green" }) + .addText("...also mess with alignment + sizes", { + size: "Stretch", + color: "red", + align: "Right", + }) + .addText("Change background colors", { + size: "Medium", + color: "red", + backgroundColor: "blue", + }) + .addText("Change background + foreground", { + size: "Medium", + align: "Right", + color: "green", + backgroundColor: "yellow", + }) + .addText("Align in the middle", { + size: "Medium", + align: "Center", + backgroundColor: "red", + }) + .addText("More fun like other colors + images", { + size: "Large", + color: "red", + backgroundColor: "yellow", + }) + .addText( + "By the way, text blocks support simple markdown like **bolding**, *italics*, and even **[links](https://speedybot.js.org/new)**" + ) + .addImage( + "https://raw.githubusercontent.com/valgaze/speedybot-utils/main/assets/memes/logo4.jpeg", + { align: "Center" } + ), + appcard: Bot.appCard( + "Design News", + "https://raw.githubusercontent.com/valgaze/speedybot-mini/deploy/docs/assets/figma_logo.png" + ) + .addText( + "Tap the button to learn about new plugins + integration options", + { color: "red", backgroundColor: "blue" } + ) + .addLinkButton("https://www.figma.com/community/plugins", "🚀 Let's go"), + "appcard-rtl": Bot.appCard( + "ڈیزائن پر اپ ڈیٹ", + "https://raw.githubusercontent.com/valgaze/speedybot-mini/deploy/docs/assets/figma_logo.png", + { rtl: true } + ) + .addText( + "نئے پلگ ان + انضمام کے اختیارات کے بارے میں جاننے کے لیے بٹن کو تھپتھپائیں۔", + { color: "red", backgroundColor: "blue", align: "Right" } + ) + .addLinkButton("https://www.figma.com/community/plugins", "اورجانیے 🚀"), + acai: Bot.card() + .addTitle("AcaiTruck 🍇🚚 - The Bowl-istic Adventure Catering") + .addSubtitle("Customize Your Acai Bowl Experience!") + .addText( + "Welcome to our Acai Bowl Food Truck catering service. Let's make your event delicious!" + ) + .addPickerDropdown(["Select Bowl Size", "Mini", "Midi", "Grande"]) + .addPickerDropdown(["Number of People", "1-10", "11-25", "26-50", "50+"]) + .addTextInput("Anything else we should know?") + .addText("Choose toppings for the bar:") + .addMultiSelect([ + "Granola", + "Peanut Butter", + "Coconut", + "Goji Berries", + "Chia Seeds", + "Almonds", + "Cashews", + "Honey", + "Cacao Nibs", + "Strawberries", + "Blueberries", + "Almond Butter", + ]) + .addText("Additional Catering Essentials:") + .addMultiSelect([ + "Utensils", + "Napkins", + "To-Go Covers", + "Fruit Juice", + "Smoothie Bar", + "Event Staff", + "Custom Branding", + ]) + .addText("Any special requests or dietary preferences?") + .addTextarea("Special Requests or Dietary Preferences") + .setSubmitButtonTitle("Book AcaiTruck 🚀"), + "red-danger": Bot.card() + .addTitle("🚨 DANGER 🚨") + .addText("Attention, this is a very severe and important warning") + .setBackgroundImage( + "data:image/png;base64,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" + ), + "green-success": Bot.card() + .addTitle("🏆 You did it! 🏆") + .addText("Whatever you did, good at job at doing it") + .setBackgroundImage( + "data:image/png;base64,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" + ), + "yellow-warning": Bot.card() + .addTitle("⚠️ You're about to do it! ⚠️") + .addText("Whatever you're about to do, give it a think") + .setBackgroundImage( + "data:image/png;base64,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" + ), + "banner-yellow": Bot.card() + .addTitle("🏝️ SpeedyBot") + .setBackgroundImage( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAmCAYAAACsyDmTAAAMbWlDQ1BJQ0MgUHJvZmlsZQAASImVVwdYU8kWnluSkJDQAghICb0jUgNICaEFkF4EGyEJJJQYE4KKvSwquHYRxYquiii2lWYBsSuLYu+LBRVlXdTFhsqbkICu+8r3zvfNvX/OnPlPuTO59wCg+YErkeShWgDkiwukCeHBjDFp6QzSU4AAIiADZ+DF5ckkrLi4aABl8P53eXcDWkO56qzg+uf8fxUdvkDGAwAZB3EmX8bLh7gZAHwDTyItAICo0FtOKZAo8ByIdaUwQIhXK3C2Eu9S4EwlPjpgk5TAhvgyAGpULleaDYDGPahnFPKyIY/GZ4hdxXyRGABNJ4gDeEIuH2JF7E75+ZMUuBxiO2gvgRjGA5iZ33Fm/40/c4ify80ewsq8BkQtRCST5HGn/Z+l+d+Snycf9GEDB1UojUhQ5A9reCt3UpQCUyHuFmfGxCpqDfEHEV9ZdwBQilAekay0R415MjasH9CH2JXPDYmC2BjiMHFeTLRKn5klCuNADHcLOlVUwEmC2ADiRQJZaKLKZot0UoLKF1qbJWWzVPpzXOmAX4WvB/LcZJaK/41QwFHxYxpFwqRUiCkQWxWKUmIg1oDYRZabGKWyGVUkZMcM2kjlCYr4rSBOEIjDg5X8WGGWNCxBZV+SLxvMF9siFHFiVPhggTApQlkf7BSPOxA/zAW7LBCzkgd5BLIx0YO58AUhocrcsecCcXKiiueDpCA4QbkWp0jy4lT2uIUgL1yht4DYQ1aYqFqLpxTAzankx7MkBXFJyjjxohxuZJwyHnw5iAZsEAIYQA5HJpgEcoCorbuuG/5SzoQBLpCCbCCAJ1SpGVyROjAjhtdEUAT+gEgAZEPrggdmBaAQ6r8MaZVXZ5A1MFs4sCIXPIU4H0SBPPhbPrBKPOQtBTyBGtE/vHPh4MF48+BQzP97/aD2m4YFNdEqjXzQI0Nz0JIYSgwhRhDDiPa4ER6A++HR8BoEhxvOxH0G8/hmT3hKaCc8IlwndBBuTxTNk/4Q5WjQAfnDVLXI/L4WuA3k9MSDcX/IDplxfdwIOOMe0A8LD4SePaGWrYpbURXGD9x/y+C7p6GyI7uSUfIwchDZ7seVGg4ankMsilp/Xx9lrJlD9WYPzfzon/1d9fnwHvWjJbYIO4SdxU5g57GjWB1gYE1YPdaKHVPgod31ZGB3DXpLGIgnF/KI/uGPq/KpqKTMtdq1y/Wzcq5AMLVAcfDYkyTTpKJsYQGDBd8OAgZHzHNxYri5urkBoHjXKP++3sYPvEMQ/dZvuvm/A+Df1N/ff+SbLrIJgAPe8Pg3fNPZMQHQVgfgXANPLi1U6nDFhQD/JTThSTMEpsAS2MF83IAX8ANBIBREgliQBNLABFhlIdznUjAFzABzQTEoBcvBGrAebAbbwC6wFxwEdeAoOAHOgIvgMrgO7sLd0wlegh7wDvQhCEJCaAgdMUTMEGvEEXFDmEgAEopEIwlIGpKBZCNiRI7MQOYjpchKZD2yFalCDiANyAnkPNKO3EYeIl3IG+QTiqFUVBc1QW3QESgTZaFRaBI6Hs1GJ6NF6AJ0KVqOVqJ70Fr0BHoRvY52oC/RXgxg6pg+Zo45Y0yMjcVi6VgWJsVmYSVYGVaJ1WCN8DlfxTqwbuwjTsTpOAN3hjs4Ak/GefhkfBa+BF+P78Jr8VP4Vfwh3oN/JdAIxgRHgi+BQxhDyCZMIRQTygg7CIcJp+FZ6iS8IxKJ+kRbojc8i2nEHOJ04hLiRuI+YjOxnfiY2EsikQxJjiR/UiyJSyogFZPWkfaQmkhXSJ2kD2rqamZqbmphaulqYrV5amVqu9WOq11Re6bWR9YiW5N9ybFkPnkaeRl5O7mRfIncSe6jaFNsKf6UJEoOZS6lnFJDOU25R3mrrq5uoe6jHq8uUp+jXq6+X/2c+kP1j1QdqgOVTR1HlVOXUndSm6m3qW9pNJoNLYiWTiugLaVV0U7SHtA+aNA1XDQ4GnyN2RoVGrUaVzReaZI1rTVZmhM0izTLNA9pXtLs1iJr2Wixtbhas7QqtBq0bmr1atO1R2rHaudrL9HerX1e+7kOScdGJ1SHr7NAZ5vOSZ3HdIxuSWfTefT59O300/ROXaKurS5HN0e3VHevbptuj56Onodeit5UvQq9Y3od+pi+jT5HP09/mf5B/Rv6n4aZDGMNEwxbPKxm2JVh7w2GGwQZCAxKDPYZXDf4ZMgwDDXMNVxhWGd43wg3cjCKN5pitMnotFH3cN3hfsN5w0uGHxx+xxg1djBOMJ5uvM241bjXxNQk3ERiss7kpEm3qb5pkGmO6WrT46ZdZnSzADOR2WqzJrMXDD0Gi5HHKGecYvSYG5tHmMvNt5q3mfdZ2FokW8yz2Gdx35JiybTMslxt2WLZY2VmNdpqhlW11R1rsjXTWmi91vqs9XsbW5tUm4U2dTbPbQ1sObZFttW29+xodoF2k+0q7a7ZE+2Z9rn2G+0vO6AOng5ChwqHS46oo5ejyHGjY7sTwcnHSexU6XTTmerMci50rnZ+6KLvEu0yz6XO5dUIqxHpI1aMODviq6una57rdte7I3VGRo6cN7Jx5Bs3BzeeW4XbNXeae5j7bPd699cejh4Cj00etzzpnqM9F3q2eH7x8vaSetV4dXlbeWd4b/C+ydRlxjGXMM/5EHyCfWb7HPX56OvlW+B70PdPP2e/XL/dfs9H2Y4SjNo+6rG/hT/Xf6t/RwAjICNgS0BHoHkgN7Ay8FGQZRA/aEfQM5Y9K4e1h/Uq2DVYGnw4+D3blz2T3RyChYSHlIS0heqEJoeuD30QZhGWHVYd1hPuGT49vDmCEBEVsSLiJseEw+NUcXoivSNnRp6KokYlRq2PehTtEC2NbhyNjo4cvWr0vRjrGHFMXSyI5cSuir0fZxs3Oe5IPDE+Lr4i/mnCyIQZCWcT6YkTE3cnvksKTlqWdDfZLlme3JKimTIupSrlfWpI6srUjjEjxswcczHNKE2UVp9OSk9J35HeOzZ07JqxneM8xxWPuzHedvzU8ecnGE3Im3BsouZE7sRDGYSM1IzdGZ+5sdxKbm8mJ3NDZg+PzVvLe8kP4q/mdwn8BSsFz7L8s1ZmPc/2z16V3SUMFJYJu0Vs0XrR65yInM0573Njc3fm9uel5u3LV8vPyG8Q64hzxacmmU6aOqld4igplnRM9p28ZnKPNEq6Q4bIxsvqC3ThR32r3E7+k/xhYUBhReGHKSlTDk3Vniqe2jrNYdriac+Kwop+mY5P501vmWE+Y+6MhzNZM7fOQmZlzmqZbTl7wezOOeFzds2lzM2d+9s813kr5/01P3V+4wKTBXMWPP4p/KfqYo1iafHNhX4LNy/CF4kWtS12X7xu8dcSfsmFUtfSstLPS3hLLvw88ufyn/uXZi1tW+a1bNNy4nLx8hsrAlfsWqm9smjl41WjV9WuZqwuWf3Xmolrzpd5lG1eS1krX9tRHl1ev85q3fJ1n9cL11+vCK7Yt8F4w+IN7zfyN17ZFLSpZrPJ5tLNn7aIttzaGr61ttKmsmwbcVvhtqfbU7af/YX5S9UOox2lO77sFO/s2JWw61SVd1XVbuPdy6rRanl1155xey7vDdlbX+Ncs3Wf/r7S/WC/fP+LAxkHbhyMOthyiHmo5lfrXzccph8uqUVqp9X21AnrOurT6tsbIhtaGv0aDx9xObLzqPnRimN6x5YdpxxfcLy/qaipt1nS3H0i+8Tjloktd0+OOXntVPypttNRp8+dCTtz8izrbNM5/3NHz/ueb7jAvFB30etibatn6+HfPH873ObVVnvJ+1L9ZZ/Lje2j2o9fCbxy4mrI1TPXONcuXo+53n4j+catm+Nudtzi33p+O+/26zuFd/ruzrlHuFdyX+t+2QPjB5W/2/++r8Or49jDkIetjxIf3X3Me/zyiezJ584FT2lPy56ZPat67vb8aFdY1+UXY190vpS87Osu/kP7jw2v7F79+mfQn609Y3o6X0tf979Z8tbw7c6/PP5q6Y3rffAu/13f+5IPhh92fWR+PPsp9dOzvimfSZ/Lv9h/afwa9fVef35/v4Qr5Q58CmBwoFlZALzZCQAtDQA67NsoY5W94IAgyv51AIH/hJX94oB4AVADv9/ju+HXzU0A9m+H7Rfk14S9ahwNgCQfgLq7Dw2VyLLc3ZRcVNinEB7097+FPRtpFQBflvf391X293/ZBoOFvWOzWNmDKoQIe4YtnC+Z+Zng34iyP/0uxx/vQBGBB/jx/i/zoZDc6xYYDgAAAIplWElmTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAACQAAAAAQAAAJAAAAABAAOShgAHAAAAEgAAAHigAgAEAAAAAQAAACSgAwAEAAAAAQAAACYAAAAAQVNDSUkAAABTY3JlZW5zaG90JS99ZAAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAdRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDYuMC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+Mzg8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MzY8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpVc2VyQ29tbWVudD5TY3JlZW5zaG90PC9leGlmOlVzZXJDb21tZW50PgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KFcjjjAAAABxpRE9UAAAAAgAAAAAAAAATAAAAKAAAABMAAAATAAAAcerJp6AAAAA9SURBVFgJ7NKxFQAABANR9raicdSMcK3itGm8n+R0bTy69CFoQyEACoUUIgHK3ZBCJEC5G1KIBCh3QyR0AAAA//++LyCxAAAAOklEQVTt0rEVAAAEA1H2tqJx1IxwreK0abyf5HRtPLr0IWhDIQAKhRQiAcrdkEIkQLkbUogEKHdDJHT6I3s1kBzd4gAAAABJRU5ErkJggg==" + ), + confirm: Bot.card() + .addTitle("Do you want to proceed") + .addButton("❌ Cancel", "shouldProceed", { data: false }) + .addButton("✅ OK", "shouldProceed", { data: true }), + "table-card": Bot.card() + .addTitle( + "Ribbit! Check out the hop-tastic details below from FrogBot industries" + ) + .addTable([ + ["Frog Species", "Population"], + ["Green Tree Frog", "2,500"], + ["Red-eyed Tree Frog", "1,800"], + ["Poison Dart Frog", "700"], + ["Fire-bellied Toad", "1,200"], + ]) + .addLinkButton( + "http://allaboutfrogs.org/froglnd.shtml", + "🐸 Explore Frogs" + ), + image: Bot.card() + .addTitle("Images") + .addSubtitle("Cards can have images too") + .addText("Small") + .addImage( + "https://raw.githubusercontent.com/valgaze/speedybot-utils/main/assets/memes/logo4.jpeg", + { size: "Small" } + ) + .addText("Medium") + .addImage( + "https://raw.githubusercontent.com/valgaze/speedybot-utils/main/assets/memes/logo4.jpeg", + { size: "Medium" } + ) + .addText("Large") + .addImage( + "https://raw.githubusercontent.com/valgaze/speedybot-utils/main/assets/memes/logo4.jpeg", + { size: "Large" } + ) + .addText("ExtraLarge") + .addImage( + "https://raw.githubusercontent.com/valgaze/speedybot-utils/main/assets/memes/logo4.jpeg", + { size: "ExtraLarge" } + ) + .addText("Stretch") + .addImage( + "https://raw.githubusercontent.com/valgaze/speedybot-utils/main/assets/memes/logo4.jpeg", + { size: "Stretch" } + ) + .addText("TIP: Images can be links too", { color: "Attention" }) + .addImage( + "https://raw.githubusercontent.com/valgaze/speedybot-utils/main/assets/memes/logo4.jpeg", + { + targetURL: "https://speedybot.js.org", + size: "ExtraLarge", + } + ), + "old-survey": Bot.card() + .addTitle("Business Improvement Survey 📈") + .addSubtitle("Help Us Enhance Our Business Operations!") + .addText( + "Your insights are crucial for our continuous improvement. Please take a moment to complete this survey." + ) + .addText("1. Company Name:") + .addTextInput("Enter Your Company's Name") + .addText("2. Your Position/Role:") + .addTextInput("Enter Your Position/Role") + .addText("3. Please select your department:") + .addPickerDropdown( + ["Select Department"].concat([ + "Sales", + "Marketing", + "Customer Support", + "Finance", + "Product Development", + ]) + ) + .addText( + "4. On a scale of 1-5, how satisfied are you with our products/services? (1 being very dissatisfied, 5 being very satisfied)" + ) + .addSingleSelect([ + "1 (Very Dissatisfied)", + "2", + "3", + "4", + "5 (Very Satisfied)", + ]) + .addText( + "5. What aspects of our products/services do you appreciate the most?" + ) + .addTextarea( + "Please share what you appreciate the most about our offerings." + ) + .addText( + "6. Are there any specific areas where you believe we can improve?" + ) + .addTextarea( + "Please provide details on areas where we can enhance our products/services." + ) + .addText( + "7. How likely are you to recommend our company to others? (1 being highly unlikely, 5 being highly likely)" + ) + .addSingleSelect([ + "1 (Highly Unlikely)", + "2", + "3", + "4", + "5 (Highly Likely)", + ]) + .addText("8. Any additional comments or suggestions?") + .addTextarea( + "Feel free to share any additional comments or suggestions you may have." + ) + .setSubmitButtonTitle("Submit Survey"), +}; + +export const makeHTML = (prefix: string, trigger: any) => { + return ` + + + ${prefix} + + +
+ +
+
+
+${JSON.stringify(trigger, null, 2)}
+          
+ + `; +}; + +Bot.exact("$survey", async ($) => { + const companyNameQuestion: SurveyQuestion = { + type: "text", + question: "What is the name of your company?", + id: "company_name", + }; + + const serviceTypeQuestion: SurveyQuestion = { + type: "text", + question: "Describe the service performed by the vendor.", + id: "service_type", + }; + + const serviceDateQuestion: SurveyQuestion = { + type: "picker-date", + question: "When was the service provided?", + id: "service_date", + }; + + const serviceQualityQuestion: SurveyQuestion = { + type: "single-select", + question: "How would you rate the quality of service?", + choices: ["Excellent", "Good", "Average", "Poor", "Very poor"], + id: "service_quality", + }; + + const highlightsQuestion: SurveyQuestion = { + type: "multi-select", + question: "What were the highlights of the service?", + choices: [ + "Communication", + "Punctuality", + "Time to Resolution", + "Friendliness", + "Cost", + ], + id: "service_highlights", + }; + + const futureUseQuestion: SurveyQuestion = { + type: "single-select", + question: "Would you consider using our services again in the future?", + choices: [ + "Definitely", + "Probably", + "Not sure", + "Probably not", + "Definitely not", + ], + id: "future_use", + }; + + const otherCommentsQuestion: SurveyQuestion = { + type: "textarea", + question: + "Please provide any other comments or suggestions for improvement.", + id: "other_comments", + }; + + const preferredContactTimeQuestion: SurveyQuestion = { + type: "picker-time", + question: "What time of day is preferable for future contact?", + id: "preferred_contact_time", + }; + + const communicationMethodQuestion: SurveyQuestion = { + type: "picker-dropdown", + question: "Preferred method of communication for future updates?", + choices: ["Email", "Phone", "Text"], + id: "communication_method", + }; + + const surveyCard = $.card().survey([ + companyNameQuestion, + serviceTypeQuestion, + serviceDateQuestion, + serviceQualityQuestion, + highlightsQuestion, + futureUseQuestion, + otherCommentsQuestion, + preferredContactTimeQuestion, + communicationMethodQuestion, + ]); + + await $.send(surveyCard); + return $.end; +}); + +// "ping"/"pong" +Bot.addStep(async ($) => { + if ($.text) { + const lower = $.text.toLowerCase(); + if (lower === "pong") { + await $.send("ping"); + } else if (lower === "ping") { + await $.send("pong"); + } + } + return $.next; +}); diff --git a/examples/speedybot-starter/settings/launch.ts b/examples/speedybot-starter-legacy/settings/launch.ts similarity index 100% rename from examples/speedybot-starter/settings/launch.ts rename to examples/speedybot-starter-legacy/settings/launch.ts diff --git a/examples/speedybot-starter-legacy/tsconfig.json b/examples/speedybot-starter-legacy/tsconfig.json new file mode 100644 index 0000000..7a2427c --- /dev/null +++ b/examples/speedybot-starter-legacy/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "declaration": true, + "resolveJsonModule": true, + "module": "commonjs", + "target": "ES2016", + "noImplicitAny": false, + "moduleResolution": "node", + "removeComments": true, + "sourceMap": true, + "skipLibCheck": true, + "strict": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": false, + "noUnusedLocals": true, + "outDir": "dist", + "baseUrl": ".", + "forceConsistentCasingInFileNames": true, + "paths": { + "*": ["node_modules/*"] + } + }, + "include": ["util/**/*", "package.json"], + "exclude": ["node_modules", "dist", "@vitest"] +} diff --git a/examples/speedybot-starter-legacy/util/cli.ts b/examples/speedybot-starter-legacy/util/cli.ts new file mode 100644 index 0000000..cf2281a --- /dev/null +++ b/examples/speedybot-starter-legacy/util/cli.ts @@ -0,0 +1,144 @@ +// #!/usr/bin/env node +import * as fs from "fs/promises"; +import * as readline from "readline"; +import { resetDevices } from "./utils"; +import { resolve } from "path"; +import * as dotenv from "dotenv"; + +import { botTokenKey, logoRoll } from "speedybot"; + +// Expects .env to get token on BOT_TOKEN +dotenv.config({ path: resolve(__dirname, "..", ".env") }); + +async function writeEnvFile(envObject, append = true) { + try { + const envContents = Object.entries(envObject) + .map(([key, value]) => `${key}=${value}`) + .join("\n"); + const flag = append ? "a" : "w"; // Use "a" for append, "w" for write (overwrite) + await fs.writeFile(".env", append ? `\n${envContents}` : envContents, { + flag, + }); + } catch (error) { + console.error("Error writing to .env:", error); + process.exit(1); + } +} + +async function promptUser(msg) { + return new Promise((resolve) => { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + rl.question(`${msg}: `, (answer) => { + rl.close(); + resolve(answer); + }); + }); +} + +async function resetBot(token) { + let finalToken = token || process.env[botTokenKey]; + if (!finalToken) { + finalToken = await promptUser( + "Enter your token, [Usage: npm run bot:reset ]" + ); + } + await resetDevices(finalToken); + console.log("Reset attempted"); +} + +async function writeToken(token) { + let finalToken = token; + if (!token) { + finalToken = await promptUser( + `Enter your token, [Usage: npm run bot:setup ]` + ); + } + // destructively overwrites .env as BOT_TOKEN=xxxxxxxx + const envObject = { [botTokenKey]: finalToken }; + await writeEnvFile(envObject, false); + console.log( + `[✅ SpeedyBot] .env written to ${resolve(__dirname, "..", ".env")} ` + ); +} + +/** + * + * @param keyValue: keyName=TheValue + */ +async function writeSecret(keyValue: string) { + if (!keyValue || (keyValue && !keyValue.includes("="))) { + console.log(`❌[ERROR] You need to add a secret, ex`); + console.log(` + npm run bot:addsecret SECRETNAME=secret12345678 + `); + process.exit(1); + } + // appends .env as key=value + const [key, value] = keyValue.split("="); + const envObject = { [key]: value }; + await writeEnvFile(envObject, true); + console.log( + `[✅ SpeedyBot] .env written to ${resolve(__dirname, "..", ".env")} ` + ); +} +async function run(command, ...args) { + switch (command) { + case "reset": + await resetBot(args[0]); + break; + case "setup": + await writeToken(args[0]); + break; + case "addsecret": + await writeSecret(args[0]); + break; + case "help": + console.log(await logoRoll()); + console.log("Project Path:", process.cwd()); + console.log(` +Usage: + $ npm run bot:debug + $ npm run bot:dev + $ npm run bot:on + $ npm run bot:reset + $ npm run bot:setup + $ npm run bot:addsecret MYKEY=THE_VALUE + +Commands: + 1. Debug Command: + $ npm run bot:debug + Display debug information about your system + + 2. Development Command: + $ npm run bot:dev + Start your bot locally (using websockets) with live-reload on code-changes + + 3. Online Command: + $ npm run bot:on + "Turn on" your bot locally (over websockets) but without live-reload on code-changes, CTRL-C to exit + + 4. Reset Command: + $ npm run bot:reset + Reset any devices, useful for rate limit situations + + 5. Setup Command: + $ npm run bot:setup + Overwrite (delete all other values) in .env file with BOT_TOKEN= + + 6. Add Secret + $ npm run bot:addsecret MYKEY=THE_VALUE + Append an .env file with MYKEY=THE_VALUE +`); + break; + default: + console.error(`Unknown command: ${command}`); + break; + } +} + +const [, , command, ...args] = process.argv; +run(command, ...args); diff --git a/examples/speedybot-starter-legacy/util/index.ts b/examples/speedybot-starter-legacy/util/index.ts new file mode 100644 index 0000000..576ce05 --- /dev/null +++ b/examples/speedybot-starter-legacy/util/index.ts @@ -0,0 +1,74 @@ +import { SpeedyBot, logoRoll } from "speedybot"; +import { Websocket } from "./utils"; +import { resolve } from "path"; +export const websocketLauncher = async ( + BotRef: SpeedyBot, + cb?: (data?: { email: string; name?: string }) => any +) => { + const token = BotRef.getToken(); + if (!token) { + throw new Error( + `SpeedyBot must have token specified before launching websockets, set with Bot.setToken()` + ); + } + + const inst = new Websocket(token); + try { + await inst.start(); + + inst.on("message", (websocketEvent: any) => { + BotRef.runMiddleware(websocketEvent); + }); + + inst.on("submit", (websocketSubmitEvent: any) => { + BotRef.runMiddleware(websocketSubmitEvent); + }); + + const data = await BotRef.getSelf(); + const { displayName } = data; + const [email] = data.emails; + + if (!cb) { + announceWebsockets(email, displayName); + } else { + return cb({ email, name: displayName }); + } + } catch (e) { + throw e; + } +}; + +export const announceWebsockets = (email: string, name = "Your bot") => { + const isColorSupported = process.stdout.isTTY; + console.log(logoRoll()); + if (isColorSupported) { + const WEBSOCKETS_READY = `\x1b[1m\x1b[7m\x1b[32m 🌐 CONNECTED \x1b[0m\x1b[32m Websockets active, listening...\x1b[0m`; + process.stdout.write(WEBSOCKETS_READY + "\n"); + } else { + console.log("Websockets Registered. Listening..."); + } + console.log(`You can reach ${name} here: ${email}`); +}; + +export const announceExit = (name = "Your bot") => { + const isColorSupported = process.stdout.isTTY; + if (isColorSupported) { + const BOT_DISCONNECTED = `\n\x1b[1m\x1b[7m\x1b[31m 🤖 DISCONNECTED \x1b[0m\x1b[31m Bot is now offline. \x1b[0m`; + process.stdout.write(BOT_DISCONNECTED + "\n"); + } else { + console.log("Bot is now offline."); + } + console.log( + ` +Your bot is now "off" + +You can turn your bot back on by entering the following commands: + +cd ${resolve(__dirname, "..")} +npm run dev + +If you want to deploy your bot to a persistent server or serverless function, see here: +https://speedybot.js.org/examples +` + ); +}; diff --git a/examples/llm-stream/util/utils.ts b/examples/speedybot-starter-legacy/util/utils.ts similarity index 100% rename from examples/llm-stream/util/utils.ts rename to examples/speedybot-starter-legacy/util/utils.ts diff --git a/examples/speedybot-starter/package.json b/examples/speedybot-starter/package.json index 6c1f338..de7635b 100644 --- a/examples/speedybot-starter/package.json +++ b/examples/speedybot-starter/package.json @@ -4,12 +4,12 @@ "description": "The speedy and easy way to build rich bots + conversation experiences", "main": "index.ts", "scripts": { - "bot:on": "tsx settings/launch", + "bot:on": "tsx util/launch", "serve": "npm run bot:dev", "dev": "npm run bot:dev", "bot:debug": "npx -y envinfo@7.11.0", "bot:serve": "npm run bot:dev", - "bot:dev": "tsx watch settings/launch", + "bot:dev": "tsx watch util/launch", "bot:reset": "tsx util/cli reset", "bot:setup": "tsx util/cli setup", "bot:token": "npm run bot:setup", @@ -27,13 +27,12 @@ "author": "valgaze@gmail.com", "license": "MIT", "devDependencies": { - "@babel/runtime-corejs2": "^7.20.1", "@types/node": "^16.18.3", "cross-fetch": "^3.1.5", "dotenv": "^16.0.3", "tsx": "^4.7.0", "typescript": "^3.8.3", - "webex": "^2.31.0" + "ws": "^8.17.0" }, "dependencies": { "speedybot": "^2.0.0" diff --git a/examples/speedybot-starter/util/cli.ts b/examples/speedybot-starter/util/cli.ts index cf2281a..8e1cdd2 100644 --- a/examples/speedybot-starter/util/cli.ts +++ b/examples/speedybot-starter/util/cli.ts @@ -1,11 +1,10 @@ // #!/usr/bin/env node +import * as dotenv from "dotenv"; +import { resolve } from "path"; import * as fs from "fs/promises"; import * as readline from "readline"; -import { resetDevices } from "./utils"; -import { resolve } from "path"; -import * as dotenv from "dotenv"; - import { botTokenKey, logoRoll } from "speedybot"; +import { LocalSockets } from "./websockets"; // Expects .env to get token on BOT_TOKEN dotenv.config({ path: resolve(__dirname, "..", ".env") }); @@ -46,7 +45,9 @@ async function resetBot(token) { "Enter your token, [Usage: npm run bot:reset ]" ); } - await resetDevices(finalToken); + + const websockets = new LocalSockets(finalToken); + await websockets.resetDevices(); console.log("Reset attempted"); } diff --git a/examples/speedybot-starter/util/index.ts b/examples/speedybot-starter/util/index.ts index 576ce05..9c865ed 100644 --- a/examples/speedybot-starter/util/index.ts +++ b/examples/speedybot-starter/util/index.ts @@ -1,56 +1,6 @@ -import { SpeedyBot, logoRoll } from "speedybot"; -import { Websocket } from "./utils"; import { resolve } from "path"; -export const websocketLauncher = async ( - BotRef: SpeedyBot, - cb?: (data?: { email: string; name?: string }) => any -) => { - const token = BotRef.getToken(); - if (!token) { - throw new Error( - `SpeedyBot must have token specified before launching websockets, set with Bot.setToken()` - ); - } - - const inst = new Websocket(token); - try { - await inst.start(); - - inst.on("message", (websocketEvent: any) => { - BotRef.runMiddleware(websocketEvent); - }); - - inst.on("submit", (websocketSubmitEvent: any) => { - BotRef.runMiddleware(websocketSubmitEvent); - }); - - const data = await BotRef.getSelf(); - const { displayName } = data; - const [email] = data.emails; - - if (!cb) { - announceWebsockets(email, displayName); - } else { - return cb({ email, name: displayName }); - } - } catch (e) { - throw e; - } -}; -export const announceWebsockets = (email: string, name = "Your bot") => { - const isColorSupported = process.stdout.isTTY; - console.log(logoRoll()); - if (isColorSupported) { - const WEBSOCKETS_READY = `\x1b[1m\x1b[7m\x1b[32m 🌐 CONNECTED \x1b[0m\x1b[32m Websockets active, listening...\x1b[0m`; - process.stdout.write(WEBSOCKETS_READY + "\n"); - } else { - console.log("Websockets Registered. Listening..."); - } - console.log(`You can reach ${name} here: ${email}`); -}; - -export const announceExit = (name = "Your bot") => { +export const announceExit = (name?: string) => { const isColorSupported = process.stdout.isTTY; if (isColorSupported) { const BOT_DISCONNECTED = `\n\x1b[1m\x1b[7m\x1b[31m 🤖 DISCONNECTED \x1b[0m\x1b[31m Bot is now offline. \x1b[0m`; @@ -60,15 +10,15 @@ export const announceExit = (name = "Your bot") => { } console.log( ` -Your bot is now "off" - -You can turn your bot back on by entering the following commands: - -cd ${resolve(__dirname, "..")} -npm run dev - -If you want to deploy your bot to a persistent server or serverless function, see here: -https://speedybot.js.org/examples -` + ${name ? name : "Your bot"} is now "off" + + You can turn your bot back on by entering the following commands: + + cd ${resolve(__dirname, "..")} + npm run dev + + If you want to deploy your bot to a persistent server or serverless function, see here: + https://speedybot.js.org/examples + ` ); }; diff --git a/examples/speedybot-starter/util/launch.ts b/examples/speedybot-starter/util/launch.ts new file mode 100644 index 0000000..1ea152f --- /dev/null +++ b/examples/speedybot-starter/util/launch.ts @@ -0,0 +1,13 @@ +import "cross-fetch/polyfill"; +import { config } from "dotenv"; +import { resolve } from "path"; +import { announceExit } from "./index"; +process.on("exit", announceExit); + +config({ path: resolve(__dirname, "..", ".env") }); + +import { SpeedySockets } from "./websockets"; +import Bot from "./../settings/bot"; + +Bot.setToken(process.env.BOT_TOKEN as string); +SpeedySockets(Bot, { force: false, debug: false }).catch((e) => console.log(e)); diff --git a/examples/speedybot-starter/util/utils.ts b/examples/speedybot-starter/util/utils.ts deleted file mode 100644 index 579d5e9..0000000 --- a/examples/speedybot-starter/util/utils.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { init } from "webex"; - -export class Websocket { - public webexRef!: StubbedWebEx; - public me: any; - public listeners: Listeners = {}; - constructor(public token: string) {} - on(eventName: Events, handler: Function) { - this.listeners[eventName] = handler; - } - - async getSelf() { - const { id } = await this.webexRef.people.get("me"); - this.me = id; - } - - async init() { - const config = { - credentials: { - access_token: this.token, - }, - }; - try { - this.webexRef = await init(config); - } catch (e) { - throw e; - } - } - - async start() { - try { - await this.init(); - await Promise.all([ - this.getSelf(), - this.webexRef.messages.listen(), - this.webexRef.attachmentActions.listen(), - ]); - - // messages - this.webexRef.messages.on("created", (event: any) => { - if (event.data.personId !== this.me) { - this.onMessage({ ...event, targetUrl: "websocket" }); - } - }); - - this.webexRef.attachmentActions.on("created", (event: any) => { - this.onSubmit({ ...event, targetUrl: "websocket" }); - }); - } catch (e) { - throw e; - } - } - - onMessage(event: any) { - if (this.listeners.message) { - this.listeners.message(event); - } - } - - onSubmit(event: any) { - if (this.listeners.submit) { - this.listeners.submit(event); - } - } - - async stop() { - await this.webexRef.internal.device.unregister(); - await this.webexRef.messages.stopListening(); - } - - async resetDevices() { - return resetDevices(this.token); - } -} - -export const resetDevices = async (token: string) => { - type Device = { - url: string; - webSocketUrl: string; - services: unknown; - }; - // Get devices - const deviceList: Response = await fetch( - "https://wdm-a.wbx2.com/wdm/api/v1/devices", - { - headers: { - Authorization: `Bearer ${token}`, - }, - } - ); - - if (!deviceList.ok) { - if (deviceList.status === 401) { - console.log( - `[❌ SpeedyBot] Token invalid-- double check the token is correct or you can regenerate a new one here: https://developer.webex.com/my-apps - ` - ); - process.exit(1); - } - } - const { devices = [] }: { devices: Device[] } = await deviceList.json(); - - for (const device of devices) { - const { url } = device; - if (url) { - await fetch(url, { - method: "DELETE", - headers: { - Authorization: `Bearer ${token}`, - }, - }); - } - } - return true; -}; -export type Listeners = { - [key: string]: Function; -}; - -export type AbbreviatedEvent = { - data: { - personId: string; - }; -}; - -export type EventCb = (evt: AbbreviatedEvent) => any; -export type StubbedWebEx = { - internal: { - services: { waitForService(...args): Promise }; - device: { unregister(...args): Promise }; - }; - request(...args): void; - people: { - get(id: string): Promise<{ id: string }>; - }; - messages: { - stopListening(): Promise; - listen(): Promise; - on(event: string, callback: EventCb): any; - }; - attachmentActions: { - listen(): Promise; - on(event: string, callback: EventCb): any; - }; -}; -export type Events = "message" | "submit" | "file" | "camera"; diff --git a/examples/speedybot-starter/util/websockets.ts b/examples/speedybot-starter/util/websockets.ts new file mode 100644 index 0000000..9c917b7 --- /dev/null +++ b/examples/speedybot-starter/util/websockets.ts @@ -0,0 +1,658 @@ +// Author: @valgaze +// Websockets are super useful but painful to use sometimes +// use bun or install Websocket with: +// $ npm install ws +import WebSocket from "ws"; // optional + +import { + type AA_Envelope, + type File_Details, + type MessageEnvelope, + type Message_Details, + type Submit_Details, + type SelfData, + SpeedyBot, +} from "speedybot"; + +import { logoRoll } from "speedybot"; + +// all the things that can go wrong :( +enum ErrorType { + HTTP_REQUEST_FAILED = "HTTP_REQUEST_FAILED", + WEBSOCKET_ERROR = "WEBSOCKET_ERROR", + INVALID_TOKEN = "INVALID_TOKEN", // 401 + EXCESSIVE_DEVICE = "EXCESSIVE_DEVICE", + UNKNOWN_ERROR = "UNKNOWN_ERROR", + FORBIDDEN_ERROR = "ERROR_FORBIDDEN", +} + +export type AbbeviatedDevice = { + url: string; + webSocketUrl: string; + services: unknown; + deviceType: string; + name: string; + model: string; + localizedModel: string; + systemName: string; + systemVersion: string; + capabilities: unknown; + features: unknown; + creationTime: string; + modificationTime: string; + deviceSettings: unknown; + deviceSettingsString: string; + showSupportText: boolean; + reportingSiteUrl: string; + reportingSiteDesc: string; + isDeviceManaged: boolean; + trainSiteNames: unknown[]; + clientSecurityPolicy: string; + intranetInactivityCheckUrl: string; + serviceHostMap: unknown; + blockExternalCommunications: boolean; + desktopFileShareControl: string; + mobileFileShareControl: string; + webFileShareControl: string; + botFileShareControl: string; + whiteboardFileShareControl: string; + clientMessagingGiphy: string; + clientMessagingLinkPreview: string; + ecmEnabledForAllUsers: boolean; + ecmSupportedStorageProviders: string[]; + defaultEcmMicrosoftCloud: string; + ecmMicrosoftTenant: string; + ecmScreenCaptureFeatureAllowed: boolean; + ecmWhiteboardFileDataAllowed: boolean; + callingBehavior: string; + onPremisePairingEnabled: boolean; + peopleInsightsEnabled: boolean; + allowSelfSignedCertificate: boolean; + webexCrossLaunch: boolean; + webexAppHubEnabled: boolean; + embeddedAppsEnabled: boolean; + settings: unknown; + selfSignupOrg: boolean; + userId: string; + orgId: string; + orgName: string; +}; + +export type Events = "text" | "card"; + +export type Data = { + [key: string]: any; +}; +export type BaseEnvelope = { + id: string; + name: string; + targetUrl: string; + resource: string; + event: string; + orgId: string; + createdBy: string; + appId: string; + ownedBy: string; + status: string; + created: Date; + actorId: string; + data: Data; +}; +export type MessagePayload = { + id: string; + timestamp: string | number; + data: { + eventType: + | "status.start_typing" // for first-press situations + | "conversation.activity" + | "conversation.highlight"; + activity?: { + id: string; + verb: "cardAction" | "post" | "acknowledge" | "update" | "share"; + actor: { + id: string; // email + objectType: string; + displayName: string; + orgId: string; + emailAddress: string; + entryUUID: string; + type: string; + }; + target: { + id: string; + objectType: string; + url: string; + published: string; + participants: { + items: any[]; + }; + activities: { + items: any[]; + }; + deletedActivityIds: any[]; + tags: string[]; + globalId: string; + }; + }; + }; +}; +export type SocketConfig = { debug: boolean; force?: boolean }; + +/** + * config: + * debug: show logs (noisy) + * force: force a new websocket connection each time (might cause excessive device registration) + */ +export class LocalSockets { + private submitFcn!: (AAEnv: AA_Envelope) => Promise | void; + onSubmit(cb: (AAEnv: AA_Envelope) => Promise | void) { + this.submitFcn = cb; + } + + private msgFcn!: (MsgEnv: MessageEnvelope) => Promise | void; + onText(cb: (MsgEnv: MessageEnvelope) => Promise | void) { + this.msgFcn = cb; + } + + private ws!: WebSocket; + constructor( + private _token: string, + private config: SocketConfig = { + debug: false, + force: false, + } + ) { + this.root = { + DEVICES_URL: "https://wdm-a.wbx2.com/wdm/api/v1/devices", + DEVICE_DATA: { + deviceName: "SpeedyBot-websockets", + deviceType: "DESKTOP", + localizedModel: "SpeedyBot", + model: "SpeedyBot", + name: this.config.force + ? `speedy-webex-${Math.random().toString(36).slice(2, 7)}` + : "speedybot-webex-reusable-websocket", + systemName: "SpeedyBot", + systemVersion: "1.0", + }, + }; + } + + private root: { + DEVICES_URL: string; + DEVICE_DATA: { + deviceName: string; + deviceType: string; + localizedModel: string; + model: string; + name: string; + systemName: string; + systemVersion: string; + }; + }; + + public log(...payload: any): void { + if (this.config.debug) + console.log.apply(console, [ + "[Speedy-Debug]", + ...(payload as [any?, ...any[]]), + ]); + } + + async start(): Promise { + this.log(`Getting device info...`); + this.log(this.root.DEVICE_DATA.name); + let device = await this.getDeviceInfo(); + if (!device || this.config.force) { + this.log( + `${ + this.config.force + ? "Force new device creation..." + : "Empty device refetching..." + }` + ); + device = await this.createDevice(); + this.log(`Device set`); + } + + if (this.ws) { + this.log(`Attempting socket disconnect`); + await this.disconnect(); + } + + if (device && "webSocketUrl" in device) { + this.log(`Registering websockets with + ${device.webSocketUrl}`); + this.log(`Device name: ${device.name}`); + await this.registerWebsockets(device.webSocketUrl); + this.log(`✅ websockets success`); + return true; + } else { + this.log(`🛑 websockets failure`); + return false; + } + } + + private buildUUID() { + return Math.random().toString(36).slice(2); + } + + handleApplicationError(error: any, errorType: ErrorType, message?: string) { + switch (errorType) { + case ErrorType.HTTP_REQUEST_FAILED: + console.error("HTTP request failed:", message, error); + break; + case ErrorType.WEBSOCKET_ERROR: + console.error("WebSocket error:", message, error); + break; + case ErrorType.INVALID_TOKEN: + console.error("Invalid token error:", message, error); + break; + case ErrorType.EXCESSIVE_DEVICE: + console.error("Excessive device registration error:", message, error); + break; + default: + console.error("Unknown error:", message, error); + break; + } + } + + private async createDevice(): Promise { + try { + const response = await fetch(this.root.DEVICES_URL, { + method: "POST", + headers: { + Authorization: `Bearer ${this._token}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(this.root.DEVICE_DATA), + }); + + if (!response.ok) { + if (response.status === 429 || response.status === 403) { + /** + * + * + { + message: "User has excessive device registrations", + errors: [ + { + description: "User has excessive device registrations", + } + ], + trackingId: "xxxxx", +} + * + */ + + throw new Error(ErrorType.EXCESSIVE_DEVICE); + } else { + throw new Error(ErrorType.UNKNOWN_ERROR); + } + } + const device = (await response.json()) as AbbeviatedDevice; + return device; + } catch (error: unknown) { + if (typeof error === "object" && error && "message" in error) { + if (error.message === ErrorType.EXCESSIVE_DEVICE) { + this.handleApplicationError( + error, + ErrorType.EXCESSIVE_DEVICE, + "WebSocket connection error" + ); + } else if (error.message === ErrorType.FORBIDDEN_ERROR) { + this.handleApplicationError( + error, + ErrorType.FORBIDDEN_ERROR, + "403 forbidden" + ); + } else { + this.handleApplicationError( + error, + ErrorType.UNKNOWN_ERROR, + "Unknown error on creation" + ); + } + } + } + } + + private async getDeviceInfo(): Promise { + try { + const response = await fetch(this.root.DEVICES_URL, { + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + + if (!response.ok && response.status === 401) { + throw new Error(ErrorType.INVALID_TOKEN); + } + + const data = (await response.json()) as + | { devices: AbbeviatedDevice[] } + | { + message: string; + errors: { description: string }[]; + trackingId: string; + }; + if ("devices" in data) { + this.log(`Total devices: ${data.devices.length}`); + const device = data.devices.find( + (device: any) => device.name === this.root.DEVICE_DATA.name + ); + return device; + } + } catch (error) { + if (typeof error === "object" && error && "message" in error) { + this.handleApplicationError( + error, + ErrorType.INVALID_TOKEN, + `[❌ SpeedyBot] Token invalid-- double check the token is correct or you can regenerate a new one here: +https://developer.webex.com/my-apps + +` + ); + } + } + } + + public async resetDevices() { + type Device = { + url: string; + webSocketUrl: string; + services: unknown; + }; + + try { + const deviceListResponse = await fetch( + "https://wdm-a.wbx2.com/wdm/api/v1/devices", + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + + if (!deviceListResponse.ok) { + if (deviceListResponse.status === 401) { + this.log(`Reset devices invalid token`); + throw new Error(ErrorType.INVALID_TOKEN); + } + throw new Error(ErrorType.HTTP_REQUEST_FAILED); + } + + const { devices = [] }: { devices: Device[] } = + (await deviceListResponse.json()) as { devices: Device[] }; + + for (const device of devices) { + const { url } = device; + if (url) { + const deleteResponse = await fetch(url, { + method: "DELETE", + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + + if (!deleteResponse.ok) { + throw new Error(ErrorType.HTTP_REQUEST_FAILED); + } + } + } + + return true; + } catch (error) { + if (error instanceof Error) { + if (error.message === ErrorType.HTTP_REQUEST_FAILED) { + this.handleApplicationError( + error, + ErrorType.HTTP_REQUEST_FAILED, + "Failed to reset devices" + ); + } else if (error.message === ErrorType.INVALID_TOKEN) { + this.handleApplicationError( + error, + ErrorType.INVALID_TOKEN, + `[❌ SpeedyBot] Token invalid-- double check the token is correct or you can regenerate a new one here: +https://developer.webex.com/my-apps + + ` + ); + } else { + this.handleApplicationError( + error, + ErrorType.UNKNOWN_ERROR, + "Unknown error while resetting devices" + ); + } + } + return false; + } + } + + public registerWebsockets(webSocketUrl: string) { + this.ws = new WebSocket(webSocketUrl); + this.ws.on("open", async () => { + this.log("🎸 Websocket open"); + const msg = { + id: this.buildUUID(), + type: "authorization", + data: { + token: `Bearer ${this._token}`, + }, + }; + this.ws.send(JSON.stringify(msg)); + }); + + this.ws.on("message", async (message: string) => { + try { + const msg = JSON.parse(message); + this.log(`📬 raw message received ${JSON.stringify(msg)}\n`); + await this.processMessage(msg); + } catch (error: unknown) { + if (typeof error === "object" && error && "message" in error) { + this.handleApplicationError( + error, + ErrorType.WEBSOCKET_ERROR, + "WebSocket error on message" + ); + } + } + }); + + this.ws.on("error", (error) => { + this.handleApplicationError( + error, + ErrorType.WEBSOCKET_ERROR, + "WebSocket connection error" + ); + }); + } + + public disconnect() { + if (this.ws) { + return this.ws.close(); + } + } + + private async checkEmail(email: string) { + const emailRes = await fetch("https://webexapis.com/v1/people/me", { + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + const { emails } = (await emailRes.json()) as SelfData; + const [myEmail] = emails; + return email !== myEmail; + } + + private async fetchMessagePayload(id: string): Promise { + const messageId = id.includes("-") + ? Buffer.from(`ciscospark://us/MESSAGE/${id}`).toString("base64") + : id; + + const response = await fetch( + `https://webexapis.com/v1/messages/${messageId}`, + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + const data = (await response.json()) as Message_Details; + return data; + } + + private async fetchCardPayload(id: string): Promise { + const attachmentActionId = id.includes("-") + ? Buffer.from(`ciscospark://us/ATTACHMENT_ACTION/${id}`).toString( + "base64" + ) + : id; + const response = await fetch( + `https://webexapis.com/v1/attachment/actions/${attachmentActionId}`, + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + const data = (await response.json()) as Promise; + return data; + } + + async processMessage(msg: MessagePayload): Promise { + if ( + msg.data.eventType === "conversation.activity" && + "activity" in msg.data && + msg.data.activity + ) { + const { id, verb, actor } = msg.data.activity; + const { emailAddress } = actor; + const proceed = await this.checkEmail(emailAddress); + if (!proceed) return false; // filter out mesages from agent + + // text [post] or file [share] message + if (verb === "post" || verb === "share") { + if (this.msgFcn) { + const payload = await this.fetchMessagePayload(id); + this.log(`[${verb}]`, id, payload); + const env = this.buildText(payload); + await this.msgFcn(env); + } + } + + // if adaptive card/attachmentAction submission [cardAction] + if (verb === "cardAction") { + if (this.submitFcn) { + const payload = await this.fetchCardPayload(id); + this.log("[cardAction]", payload); + const env = this.buildCard(payload); + await this.submitFcn(env); + } + } + } + + return true; + } + + setToken(token: string) { + this._token = token; + } + + getToken(): string { + return this._token; + } + + private buildText(payload: Message_Details | File_Details): MessageEnvelope { + return { + id: "__websocket_id", + name: "__websocket_name", + targetUrl: "__websocket_targetUrl", + resource: "messages", + event: "created", + orgId: "__websocket_orgId", + createdBy: "__websocket_createdBy", + appId: "__websocket_appId", + ownedBy: "creator", + status: "active", + created: new Date().toISOString(), + actorId: "__websocket_actorId", + data: payload, + }; + } + + private buildCard(payload: Submit_Details): AA_Envelope { + return { + id: "__websocket_id", + name: "__websocket_name", + targetUrl: "__websocket_targetUrl", + resource: "attachmentActions", + event: "created", + orgId: "__websocket_orgId", + createdBy: "__websocket_createdBy", + appId: "__websocket_appId", + ownedBy: "creator", + status: "active", + created: new Date().toISOString(), + actorId: "__websocket_actorId", + data: payload, + }; + } +} + +export const announceWebsockets = (email: string, name = "Your bot") => { + const isColorSupported = process.stdout.isTTY; + console.log(logoRoll()); + if (isColorSupported) { + const WEBSOCKETS_READY = `\x1b[1m\x1b[7m\x1b[32m 🌐 CONNECTED \x1b[0m\x1b[32m Websockets active, listening...\x1b[0m`; + process.stdout.write(WEBSOCKETS_READY + "\n"); + } else { + console.log("Websockets Registered. Listening..."); + } + console.log(`You can reach ${name} here: ${email}`); +}; + +/** + * Helper to surround SpeedyBot instance with websockets + * + */ +export async function SpeedySockets( + BotRef: SpeedyBot, + config: SocketConfig = { + debug: false, + force: false, + }, + cb?: (data?: { email: string; name?: string }) => any +): Promise { + try { + const token = BotRef.getToken(); + if (!token) { + throw new Error("No token provided (try Bot.setToken('__REPLACE__ME__')"); + } + const inst = new LocalSockets(token, config); + + inst.onSubmit(async (payload) => { + BotRef.runMiddleware(payload); + }); + + inst.onText((payload) => { + BotRef.runMiddleware(payload); + }); + + await inst.start(); + const data = await BotRef.getSelf(); + const { displayName } = data; + const [email] = data.emails; + + if (!cb) { + announceWebsockets(email, displayName); + } else { + return cb({ email, name: displayName }); + } + } catch (e) { + console.log(e); + throw e; + } +} diff --git a/examples/voiceflow-kb/package.json b/examples/voiceflow-kb/package.json index 515e270..d2c05d1 100644 --- a/examples/voiceflow-kb/package.json +++ b/examples/voiceflow-kb/package.json @@ -4,12 +4,12 @@ "description": "The speedy and easy way to build rich bots + conversation experiences", "main": "index.ts", "scripts": { - "bot:on": "tsx settings/launch", + "bot:on": "tsx util/launch", "serve": "npm run bot:dev", "dev": "npm run bot:dev", "bot:debug": "npx -y envinfo@7.11.0", "bot:serve": "npm run bot:dev", - "bot:dev": "tsx watch settings/launch", + "bot:dev": "tsx watch util/launch", "bot:reset": "tsx util/cli reset", "bot:setup": "tsx util/cli setup", "bot:token": "npm run bot:setup", @@ -31,13 +31,12 @@ "author": "valgaze@gmail.com", "license": "MIT", "devDependencies": { - "@babel/runtime-corejs2": "^7.20.1", "@types/node": "^16.18.3", "cross-fetch": "^3.1.5", "dotenv": "^16.0.3", "tsx": "^4.7.0", "typescript": "^3.8.3", - "webex": "^2.31.0" + "ws": "^8.17.0" }, "dependencies": { "speedybot": "^2.0.0" diff --git a/examples/voiceflow-kb/util/cli.ts b/examples/voiceflow-kb/util/cli.ts index cf2281a..8e1cdd2 100644 --- a/examples/voiceflow-kb/util/cli.ts +++ b/examples/voiceflow-kb/util/cli.ts @@ -1,11 +1,10 @@ // #!/usr/bin/env node +import * as dotenv from "dotenv"; +import { resolve } from "path"; import * as fs from "fs/promises"; import * as readline from "readline"; -import { resetDevices } from "./utils"; -import { resolve } from "path"; -import * as dotenv from "dotenv"; - import { botTokenKey, logoRoll } from "speedybot"; +import { LocalSockets } from "./websockets"; // Expects .env to get token on BOT_TOKEN dotenv.config({ path: resolve(__dirname, "..", ".env") }); @@ -46,7 +45,9 @@ async function resetBot(token) { "Enter your token, [Usage: npm run bot:reset ]" ); } - await resetDevices(finalToken); + + const websockets = new LocalSockets(finalToken); + await websockets.resetDevices(); console.log("Reset attempted"); } diff --git a/examples/voiceflow-kb/util/index.ts b/examples/voiceflow-kb/util/index.ts index e515718..9c865ed 100644 --- a/examples/voiceflow-kb/util/index.ts +++ b/examples/voiceflow-kb/util/index.ts @@ -1,56 +1,6 @@ -import { SpeedyBot, logoRoll } from "speedybot"; -import { Websocket } from "./utils"; import { resolve } from "path"; -export const websocketLauncher = async ( - BotRef: SpeedyBot, - cb?: (data?: { email: string; name?: string }) => any -) => { - const token = BotRef.getToken(); - if (!token) { - throw new Error( - `SpeedyBot must have token specified before launching websockets, set with Bot.setToken()` - ); - } - - const inst = new Websocket(token); - try { - await inst.start(); - - inst.on("message", (websocketEvent: any) => { - BotRef.runMiddleware(websocketEvent); - }); - - inst.on("submit", (websocketSubmitEvent: any) => { - BotRef.runMiddleware(websocketSubmitEvent); - }); - - const data = await BotRef.getSelf(); - const { displayName } = data; - const [email] = data.emails; - - if (!cb) { - announceWebsockets(email, displayName); - } else { - return cb({ email, name: displayName }); - } - } catch (e) { - throw e; - } -}; -export const announceWebsockets = (email: string, name = "Your bot") => { - const isColorSupported = process.stdout.isTTY; - console.log(logoRoll()); - if (isColorSupported) { - const WEBSOCKETS_READY = `\x1b[1m\x1b[7m\x1b[32m 🌐 CONNECTED \x1b[0m\x1b[32m Websockets active, listening...\x1b[0m`; - process.stdout.write(WEBSOCKETS_READY + "\n"); - } else { - console.log("Websockets Registered. Listening..."); - } - console.log(`You can reach ${name} here: ${email}`); -}; - -export const announceExit = (name = "Your bot") => { +export const announceExit = (name?: string) => { const isColorSupported = process.stdout.isTTY; if (isColorSupported) { const BOT_DISCONNECTED = `\n\x1b[1m\x1b[7m\x1b[31m 🤖 DISCONNECTED \x1b[0m\x1b[31m Bot is now offline. \x1b[0m`; @@ -60,14 +10,15 @@ export const announceExit = (name = "Your bot") => { } console.log( ` -Your bot is now "off" - -You can turn your bot back on by entering the following commands: - -cd ${resolve(__dirname, "..")} -npm run dev - -If you want to deploy your bot to a persistent server or serverless function, see here: -https://speedybot.js.org/examples` + ${name ? name : "Your bot"} is now "off" + + You can turn your bot back on by entering the following commands: + + cd ${resolve(__dirname, "..")} + npm run dev + + If you want to deploy your bot to a persistent server or serverless function, see here: + https://speedybot.js.org/examples + ` ); }; diff --git a/examples/voiceflow-kb/settings/launch.ts b/examples/voiceflow-kb/util/launch.ts similarity index 56% rename from examples/voiceflow-kb/settings/launch.ts rename to examples/voiceflow-kb/util/launch.ts index 7cf5ab6..74bbaf2 100644 --- a/examples/voiceflow-kb/settings/launch.ts +++ b/examples/voiceflow-kb/util/launch.ts @@ -1,13 +1,8 @@ -// npm i cross-fetch dotenv import "cross-fetch/polyfill"; import { config } from "dotenv"; import { resolve } from "path"; -config({ path: resolve(__dirname, "..", ".env") }); -import { announceExit, websocketLauncher } from "../util"; -import Bot from "./bot"; +import { announceExit } from "./index"; process.on("exit", announceExit); - -// Assert these are available on process.env yadda-yadda, otherwise would have to `process.env.BOT_TOKEN as string` declare global { namespace NodeJS { interface ProcessEnv { @@ -16,10 +11,12 @@ declare global { } } } +config({ path: resolve(__dirname, "..", ".env") }); + +import { SpeedySockets } from "./websockets"; +import Bot from "./../settings/bot"; -// Add secrets Bot.setToken(process.env.BOT_TOKEN as string); Bot.addSecret("VOICEFLOW_API_KEY", process.env.VOICEFLOW_API_KEY); -// Pass in your SpeedyBot -websocketLauncher(Bot).catch((e) => console.log("##", e)); +SpeedySockets(Bot, { force: false, debug: false }).catch((e) => console.log(e)); diff --git a/examples/voiceflow-kb/util/utils.ts b/examples/voiceflow-kb/util/utils.ts deleted file mode 100644 index 579d5e9..0000000 --- a/examples/voiceflow-kb/util/utils.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { init } from "webex"; - -export class Websocket { - public webexRef!: StubbedWebEx; - public me: any; - public listeners: Listeners = {}; - constructor(public token: string) {} - on(eventName: Events, handler: Function) { - this.listeners[eventName] = handler; - } - - async getSelf() { - const { id } = await this.webexRef.people.get("me"); - this.me = id; - } - - async init() { - const config = { - credentials: { - access_token: this.token, - }, - }; - try { - this.webexRef = await init(config); - } catch (e) { - throw e; - } - } - - async start() { - try { - await this.init(); - await Promise.all([ - this.getSelf(), - this.webexRef.messages.listen(), - this.webexRef.attachmentActions.listen(), - ]); - - // messages - this.webexRef.messages.on("created", (event: any) => { - if (event.data.personId !== this.me) { - this.onMessage({ ...event, targetUrl: "websocket" }); - } - }); - - this.webexRef.attachmentActions.on("created", (event: any) => { - this.onSubmit({ ...event, targetUrl: "websocket" }); - }); - } catch (e) { - throw e; - } - } - - onMessage(event: any) { - if (this.listeners.message) { - this.listeners.message(event); - } - } - - onSubmit(event: any) { - if (this.listeners.submit) { - this.listeners.submit(event); - } - } - - async stop() { - await this.webexRef.internal.device.unregister(); - await this.webexRef.messages.stopListening(); - } - - async resetDevices() { - return resetDevices(this.token); - } -} - -export const resetDevices = async (token: string) => { - type Device = { - url: string; - webSocketUrl: string; - services: unknown; - }; - // Get devices - const deviceList: Response = await fetch( - "https://wdm-a.wbx2.com/wdm/api/v1/devices", - { - headers: { - Authorization: `Bearer ${token}`, - }, - } - ); - - if (!deviceList.ok) { - if (deviceList.status === 401) { - console.log( - `[❌ SpeedyBot] Token invalid-- double check the token is correct or you can regenerate a new one here: https://developer.webex.com/my-apps - ` - ); - process.exit(1); - } - } - const { devices = [] }: { devices: Device[] } = await deviceList.json(); - - for (const device of devices) { - const { url } = device; - if (url) { - await fetch(url, { - method: "DELETE", - headers: { - Authorization: `Bearer ${token}`, - }, - }); - } - } - return true; -}; -export type Listeners = { - [key: string]: Function; -}; - -export type AbbreviatedEvent = { - data: { - personId: string; - }; -}; - -export type EventCb = (evt: AbbreviatedEvent) => any; -export type StubbedWebEx = { - internal: { - services: { waitForService(...args): Promise }; - device: { unregister(...args): Promise }; - }; - request(...args): void; - people: { - get(id: string): Promise<{ id: string }>; - }; - messages: { - stopListening(): Promise; - listen(): Promise; - on(event: string, callback: EventCb): any; - }; - attachmentActions: { - listen(): Promise; - on(event: string, callback: EventCb): any; - }; -}; -export type Events = "message" | "submit" | "file" | "camera"; diff --git a/examples/voiceflow-kb/util/websockets.ts b/examples/voiceflow-kb/util/websockets.ts new file mode 100644 index 0000000..9c917b7 --- /dev/null +++ b/examples/voiceflow-kb/util/websockets.ts @@ -0,0 +1,658 @@ +// Author: @valgaze +// Websockets are super useful but painful to use sometimes +// use bun or install Websocket with: +// $ npm install ws +import WebSocket from "ws"; // optional + +import { + type AA_Envelope, + type File_Details, + type MessageEnvelope, + type Message_Details, + type Submit_Details, + type SelfData, + SpeedyBot, +} from "speedybot"; + +import { logoRoll } from "speedybot"; + +// all the things that can go wrong :( +enum ErrorType { + HTTP_REQUEST_FAILED = "HTTP_REQUEST_FAILED", + WEBSOCKET_ERROR = "WEBSOCKET_ERROR", + INVALID_TOKEN = "INVALID_TOKEN", // 401 + EXCESSIVE_DEVICE = "EXCESSIVE_DEVICE", + UNKNOWN_ERROR = "UNKNOWN_ERROR", + FORBIDDEN_ERROR = "ERROR_FORBIDDEN", +} + +export type AbbeviatedDevice = { + url: string; + webSocketUrl: string; + services: unknown; + deviceType: string; + name: string; + model: string; + localizedModel: string; + systemName: string; + systemVersion: string; + capabilities: unknown; + features: unknown; + creationTime: string; + modificationTime: string; + deviceSettings: unknown; + deviceSettingsString: string; + showSupportText: boolean; + reportingSiteUrl: string; + reportingSiteDesc: string; + isDeviceManaged: boolean; + trainSiteNames: unknown[]; + clientSecurityPolicy: string; + intranetInactivityCheckUrl: string; + serviceHostMap: unknown; + blockExternalCommunications: boolean; + desktopFileShareControl: string; + mobileFileShareControl: string; + webFileShareControl: string; + botFileShareControl: string; + whiteboardFileShareControl: string; + clientMessagingGiphy: string; + clientMessagingLinkPreview: string; + ecmEnabledForAllUsers: boolean; + ecmSupportedStorageProviders: string[]; + defaultEcmMicrosoftCloud: string; + ecmMicrosoftTenant: string; + ecmScreenCaptureFeatureAllowed: boolean; + ecmWhiteboardFileDataAllowed: boolean; + callingBehavior: string; + onPremisePairingEnabled: boolean; + peopleInsightsEnabled: boolean; + allowSelfSignedCertificate: boolean; + webexCrossLaunch: boolean; + webexAppHubEnabled: boolean; + embeddedAppsEnabled: boolean; + settings: unknown; + selfSignupOrg: boolean; + userId: string; + orgId: string; + orgName: string; +}; + +export type Events = "text" | "card"; + +export type Data = { + [key: string]: any; +}; +export type BaseEnvelope = { + id: string; + name: string; + targetUrl: string; + resource: string; + event: string; + orgId: string; + createdBy: string; + appId: string; + ownedBy: string; + status: string; + created: Date; + actorId: string; + data: Data; +}; +export type MessagePayload = { + id: string; + timestamp: string | number; + data: { + eventType: + | "status.start_typing" // for first-press situations + | "conversation.activity" + | "conversation.highlight"; + activity?: { + id: string; + verb: "cardAction" | "post" | "acknowledge" | "update" | "share"; + actor: { + id: string; // email + objectType: string; + displayName: string; + orgId: string; + emailAddress: string; + entryUUID: string; + type: string; + }; + target: { + id: string; + objectType: string; + url: string; + published: string; + participants: { + items: any[]; + }; + activities: { + items: any[]; + }; + deletedActivityIds: any[]; + tags: string[]; + globalId: string; + }; + }; + }; +}; +export type SocketConfig = { debug: boolean; force?: boolean }; + +/** + * config: + * debug: show logs (noisy) + * force: force a new websocket connection each time (might cause excessive device registration) + */ +export class LocalSockets { + private submitFcn!: (AAEnv: AA_Envelope) => Promise | void; + onSubmit(cb: (AAEnv: AA_Envelope) => Promise | void) { + this.submitFcn = cb; + } + + private msgFcn!: (MsgEnv: MessageEnvelope) => Promise | void; + onText(cb: (MsgEnv: MessageEnvelope) => Promise | void) { + this.msgFcn = cb; + } + + private ws!: WebSocket; + constructor( + private _token: string, + private config: SocketConfig = { + debug: false, + force: false, + } + ) { + this.root = { + DEVICES_URL: "https://wdm-a.wbx2.com/wdm/api/v1/devices", + DEVICE_DATA: { + deviceName: "SpeedyBot-websockets", + deviceType: "DESKTOP", + localizedModel: "SpeedyBot", + model: "SpeedyBot", + name: this.config.force + ? `speedy-webex-${Math.random().toString(36).slice(2, 7)}` + : "speedybot-webex-reusable-websocket", + systemName: "SpeedyBot", + systemVersion: "1.0", + }, + }; + } + + private root: { + DEVICES_URL: string; + DEVICE_DATA: { + deviceName: string; + deviceType: string; + localizedModel: string; + model: string; + name: string; + systemName: string; + systemVersion: string; + }; + }; + + public log(...payload: any): void { + if (this.config.debug) + console.log.apply(console, [ + "[Speedy-Debug]", + ...(payload as [any?, ...any[]]), + ]); + } + + async start(): Promise { + this.log(`Getting device info...`); + this.log(this.root.DEVICE_DATA.name); + let device = await this.getDeviceInfo(); + if (!device || this.config.force) { + this.log( + `${ + this.config.force + ? "Force new device creation..." + : "Empty device refetching..." + }` + ); + device = await this.createDevice(); + this.log(`Device set`); + } + + if (this.ws) { + this.log(`Attempting socket disconnect`); + await this.disconnect(); + } + + if (device && "webSocketUrl" in device) { + this.log(`Registering websockets with + ${device.webSocketUrl}`); + this.log(`Device name: ${device.name}`); + await this.registerWebsockets(device.webSocketUrl); + this.log(`✅ websockets success`); + return true; + } else { + this.log(`🛑 websockets failure`); + return false; + } + } + + private buildUUID() { + return Math.random().toString(36).slice(2); + } + + handleApplicationError(error: any, errorType: ErrorType, message?: string) { + switch (errorType) { + case ErrorType.HTTP_REQUEST_FAILED: + console.error("HTTP request failed:", message, error); + break; + case ErrorType.WEBSOCKET_ERROR: + console.error("WebSocket error:", message, error); + break; + case ErrorType.INVALID_TOKEN: + console.error("Invalid token error:", message, error); + break; + case ErrorType.EXCESSIVE_DEVICE: + console.error("Excessive device registration error:", message, error); + break; + default: + console.error("Unknown error:", message, error); + break; + } + } + + private async createDevice(): Promise { + try { + const response = await fetch(this.root.DEVICES_URL, { + method: "POST", + headers: { + Authorization: `Bearer ${this._token}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(this.root.DEVICE_DATA), + }); + + if (!response.ok) { + if (response.status === 429 || response.status === 403) { + /** + * + * + { + message: "User has excessive device registrations", + errors: [ + { + description: "User has excessive device registrations", + } + ], + trackingId: "xxxxx", +} + * + */ + + throw new Error(ErrorType.EXCESSIVE_DEVICE); + } else { + throw new Error(ErrorType.UNKNOWN_ERROR); + } + } + const device = (await response.json()) as AbbeviatedDevice; + return device; + } catch (error: unknown) { + if (typeof error === "object" && error && "message" in error) { + if (error.message === ErrorType.EXCESSIVE_DEVICE) { + this.handleApplicationError( + error, + ErrorType.EXCESSIVE_DEVICE, + "WebSocket connection error" + ); + } else if (error.message === ErrorType.FORBIDDEN_ERROR) { + this.handleApplicationError( + error, + ErrorType.FORBIDDEN_ERROR, + "403 forbidden" + ); + } else { + this.handleApplicationError( + error, + ErrorType.UNKNOWN_ERROR, + "Unknown error on creation" + ); + } + } + } + } + + private async getDeviceInfo(): Promise { + try { + const response = await fetch(this.root.DEVICES_URL, { + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + + if (!response.ok && response.status === 401) { + throw new Error(ErrorType.INVALID_TOKEN); + } + + const data = (await response.json()) as + | { devices: AbbeviatedDevice[] } + | { + message: string; + errors: { description: string }[]; + trackingId: string; + }; + if ("devices" in data) { + this.log(`Total devices: ${data.devices.length}`); + const device = data.devices.find( + (device: any) => device.name === this.root.DEVICE_DATA.name + ); + return device; + } + } catch (error) { + if (typeof error === "object" && error && "message" in error) { + this.handleApplicationError( + error, + ErrorType.INVALID_TOKEN, + `[❌ SpeedyBot] Token invalid-- double check the token is correct or you can regenerate a new one here: +https://developer.webex.com/my-apps + +` + ); + } + } + } + + public async resetDevices() { + type Device = { + url: string; + webSocketUrl: string; + services: unknown; + }; + + try { + const deviceListResponse = await fetch( + "https://wdm-a.wbx2.com/wdm/api/v1/devices", + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + + if (!deviceListResponse.ok) { + if (deviceListResponse.status === 401) { + this.log(`Reset devices invalid token`); + throw new Error(ErrorType.INVALID_TOKEN); + } + throw new Error(ErrorType.HTTP_REQUEST_FAILED); + } + + const { devices = [] }: { devices: Device[] } = + (await deviceListResponse.json()) as { devices: Device[] }; + + for (const device of devices) { + const { url } = device; + if (url) { + const deleteResponse = await fetch(url, { + method: "DELETE", + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + + if (!deleteResponse.ok) { + throw new Error(ErrorType.HTTP_REQUEST_FAILED); + } + } + } + + return true; + } catch (error) { + if (error instanceof Error) { + if (error.message === ErrorType.HTTP_REQUEST_FAILED) { + this.handleApplicationError( + error, + ErrorType.HTTP_REQUEST_FAILED, + "Failed to reset devices" + ); + } else if (error.message === ErrorType.INVALID_TOKEN) { + this.handleApplicationError( + error, + ErrorType.INVALID_TOKEN, + `[❌ SpeedyBot] Token invalid-- double check the token is correct or you can regenerate a new one here: +https://developer.webex.com/my-apps + + ` + ); + } else { + this.handleApplicationError( + error, + ErrorType.UNKNOWN_ERROR, + "Unknown error while resetting devices" + ); + } + } + return false; + } + } + + public registerWebsockets(webSocketUrl: string) { + this.ws = new WebSocket(webSocketUrl); + this.ws.on("open", async () => { + this.log("🎸 Websocket open"); + const msg = { + id: this.buildUUID(), + type: "authorization", + data: { + token: `Bearer ${this._token}`, + }, + }; + this.ws.send(JSON.stringify(msg)); + }); + + this.ws.on("message", async (message: string) => { + try { + const msg = JSON.parse(message); + this.log(`📬 raw message received ${JSON.stringify(msg)}\n`); + await this.processMessage(msg); + } catch (error: unknown) { + if (typeof error === "object" && error && "message" in error) { + this.handleApplicationError( + error, + ErrorType.WEBSOCKET_ERROR, + "WebSocket error on message" + ); + } + } + }); + + this.ws.on("error", (error) => { + this.handleApplicationError( + error, + ErrorType.WEBSOCKET_ERROR, + "WebSocket connection error" + ); + }); + } + + public disconnect() { + if (this.ws) { + return this.ws.close(); + } + } + + private async checkEmail(email: string) { + const emailRes = await fetch("https://webexapis.com/v1/people/me", { + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + const { emails } = (await emailRes.json()) as SelfData; + const [myEmail] = emails; + return email !== myEmail; + } + + private async fetchMessagePayload(id: string): Promise { + const messageId = id.includes("-") + ? Buffer.from(`ciscospark://us/MESSAGE/${id}`).toString("base64") + : id; + + const response = await fetch( + `https://webexapis.com/v1/messages/${messageId}`, + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + const data = (await response.json()) as Message_Details; + return data; + } + + private async fetchCardPayload(id: string): Promise { + const attachmentActionId = id.includes("-") + ? Buffer.from(`ciscospark://us/ATTACHMENT_ACTION/${id}`).toString( + "base64" + ) + : id; + const response = await fetch( + `https://webexapis.com/v1/attachment/actions/${attachmentActionId}`, + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + const data = (await response.json()) as Promise; + return data; + } + + async processMessage(msg: MessagePayload): Promise { + if ( + msg.data.eventType === "conversation.activity" && + "activity" in msg.data && + msg.data.activity + ) { + const { id, verb, actor } = msg.data.activity; + const { emailAddress } = actor; + const proceed = await this.checkEmail(emailAddress); + if (!proceed) return false; // filter out mesages from agent + + // text [post] or file [share] message + if (verb === "post" || verb === "share") { + if (this.msgFcn) { + const payload = await this.fetchMessagePayload(id); + this.log(`[${verb}]`, id, payload); + const env = this.buildText(payload); + await this.msgFcn(env); + } + } + + // if adaptive card/attachmentAction submission [cardAction] + if (verb === "cardAction") { + if (this.submitFcn) { + const payload = await this.fetchCardPayload(id); + this.log("[cardAction]", payload); + const env = this.buildCard(payload); + await this.submitFcn(env); + } + } + } + + return true; + } + + setToken(token: string) { + this._token = token; + } + + getToken(): string { + return this._token; + } + + private buildText(payload: Message_Details | File_Details): MessageEnvelope { + return { + id: "__websocket_id", + name: "__websocket_name", + targetUrl: "__websocket_targetUrl", + resource: "messages", + event: "created", + orgId: "__websocket_orgId", + createdBy: "__websocket_createdBy", + appId: "__websocket_appId", + ownedBy: "creator", + status: "active", + created: new Date().toISOString(), + actorId: "__websocket_actorId", + data: payload, + }; + } + + private buildCard(payload: Submit_Details): AA_Envelope { + return { + id: "__websocket_id", + name: "__websocket_name", + targetUrl: "__websocket_targetUrl", + resource: "attachmentActions", + event: "created", + orgId: "__websocket_orgId", + createdBy: "__websocket_createdBy", + appId: "__websocket_appId", + ownedBy: "creator", + status: "active", + created: new Date().toISOString(), + actorId: "__websocket_actorId", + data: payload, + }; + } +} + +export const announceWebsockets = (email: string, name = "Your bot") => { + const isColorSupported = process.stdout.isTTY; + console.log(logoRoll()); + if (isColorSupported) { + const WEBSOCKETS_READY = `\x1b[1m\x1b[7m\x1b[32m 🌐 CONNECTED \x1b[0m\x1b[32m Websockets active, listening...\x1b[0m`; + process.stdout.write(WEBSOCKETS_READY + "\n"); + } else { + console.log("Websockets Registered. Listening..."); + } + console.log(`You can reach ${name} here: ${email}`); +}; + +/** + * Helper to surround SpeedyBot instance with websockets + * + */ +export async function SpeedySockets( + BotRef: SpeedyBot, + config: SocketConfig = { + debug: false, + force: false, + }, + cb?: (data?: { email: string; name?: string }) => any +): Promise { + try { + const token = BotRef.getToken(); + if (!token) { + throw new Error("No token provided (try Bot.setToken('__REPLACE__ME__')"); + } + const inst = new LocalSockets(token, config); + + inst.onSubmit(async (payload) => { + BotRef.runMiddleware(payload); + }); + + inst.onText((payload) => { + BotRef.runMiddleware(payload); + }); + + await inst.start(); + const data = await BotRef.getSelf(); + const { displayName } = data; + const [email] = data.emails; + + if (!cb) { + announceWebsockets(email, displayName); + } else { + return cb({ email, name: displayName }); + } + } catch (e) { + console.log(e); + throw e; + } +} diff --git a/examples/voiceflow/package.json b/examples/voiceflow/package.json index 515e270..d2c05d1 100644 --- a/examples/voiceflow/package.json +++ b/examples/voiceflow/package.json @@ -4,12 +4,12 @@ "description": "The speedy and easy way to build rich bots + conversation experiences", "main": "index.ts", "scripts": { - "bot:on": "tsx settings/launch", + "bot:on": "tsx util/launch", "serve": "npm run bot:dev", "dev": "npm run bot:dev", "bot:debug": "npx -y envinfo@7.11.0", "bot:serve": "npm run bot:dev", - "bot:dev": "tsx watch settings/launch", + "bot:dev": "tsx watch util/launch", "bot:reset": "tsx util/cli reset", "bot:setup": "tsx util/cli setup", "bot:token": "npm run bot:setup", @@ -31,13 +31,12 @@ "author": "valgaze@gmail.com", "license": "MIT", "devDependencies": { - "@babel/runtime-corejs2": "^7.20.1", "@types/node": "^16.18.3", "cross-fetch": "^3.1.5", "dotenv": "^16.0.3", "tsx": "^4.7.0", "typescript": "^3.8.3", - "webex": "^2.31.0" + "ws": "^8.17.0" }, "dependencies": { "speedybot": "^2.0.0" diff --git a/examples/voiceflow/util/cli.ts b/examples/voiceflow/util/cli.ts index cf2281a..8e1cdd2 100644 --- a/examples/voiceflow/util/cli.ts +++ b/examples/voiceflow/util/cli.ts @@ -1,11 +1,10 @@ // #!/usr/bin/env node +import * as dotenv from "dotenv"; +import { resolve } from "path"; import * as fs from "fs/promises"; import * as readline from "readline"; -import { resetDevices } from "./utils"; -import { resolve } from "path"; -import * as dotenv from "dotenv"; - import { botTokenKey, logoRoll } from "speedybot"; +import { LocalSockets } from "./websockets"; // Expects .env to get token on BOT_TOKEN dotenv.config({ path: resolve(__dirname, "..", ".env") }); @@ -46,7 +45,9 @@ async function resetBot(token) { "Enter your token, [Usage: npm run bot:reset ]" ); } - await resetDevices(finalToken); + + const websockets = new LocalSockets(finalToken); + await websockets.resetDevices(); console.log("Reset attempted"); } diff --git a/examples/voiceflow/util/index.ts b/examples/voiceflow/util/index.ts index e515718..9c865ed 100644 --- a/examples/voiceflow/util/index.ts +++ b/examples/voiceflow/util/index.ts @@ -1,56 +1,6 @@ -import { SpeedyBot, logoRoll } from "speedybot"; -import { Websocket } from "./utils"; import { resolve } from "path"; -export const websocketLauncher = async ( - BotRef: SpeedyBot, - cb?: (data?: { email: string; name?: string }) => any -) => { - const token = BotRef.getToken(); - if (!token) { - throw new Error( - `SpeedyBot must have token specified before launching websockets, set with Bot.setToken()` - ); - } - - const inst = new Websocket(token); - try { - await inst.start(); - - inst.on("message", (websocketEvent: any) => { - BotRef.runMiddleware(websocketEvent); - }); - - inst.on("submit", (websocketSubmitEvent: any) => { - BotRef.runMiddleware(websocketSubmitEvent); - }); - - const data = await BotRef.getSelf(); - const { displayName } = data; - const [email] = data.emails; - - if (!cb) { - announceWebsockets(email, displayName); - } else { - return cb({ email, name: displayName }); - } - } catch (e) { - throw e; - } -}; -export const announceWebsockets = (email: string, name = "Your bot") => { - const isColorSupported = process.stdout.isTTY; - console.log(logoRoll()); - if (isColorSupported) { - const WEBSOCKETS_READY = `\x1b[1m\x1b[7m\x1b[32m 🌐 CONNECTED \x1b[0m\x1b[32m Websockets active, listening...\x1b[0m`; - process.stdout.write(WEBSOCKETS_READY + "\n"); - } else { - console.log("Websockets Registered. Listening..."); - } - console.log(`You can reach ${name} here: ${email}`); -}; - -export const announceExit = (name = "Your bot") => { +export const announceExit = (name?: string) => { const isColorSupported = process.stdout.isTTY; if (isColorSupported) { const BOT_DISCONNECTED = `\n\x1b[1m\x1b[7m\x1b[31m 🤖 DISCONNECTED \x1b[0m\x1b[31m Bot is now offline. \x1b[0m`; @@ -60,14 +10,15 @@ export const announceExit = (name = "Your bot") => { } console.log( ` -Your bot is now "off" - -You can turn your bot back on by entering the following commands: - -cd ${resolve(__dirname, "..")} -npm run dev - -If you want to deploy your bot to a persistent server or serverless function, see here: -https://speedybot.js.org/examples` + ${name ? name : "Your bot"} is now "off" + + You can turn your bot back on by entering the following commands: + + cd ${resolve(__dirname, "..")} + npm run dev + + If you want to deploy your bot to a persistent server or serverless function, see here: + https://speedybot.js.org/examples + ` ); }; diff --git a/examples/voiceflow/settings/launch.ts b/examples/voiceflow/util/launch.ts similarity index 56% rename from examples/voiceflow/settings/launch.ts rename to examples/voiceflow/util/launch.ts index 7cf5ab6..74bbaf2 100644 --- a/examples/voiceflow/settings/launch.ts +++ b/examples/voiceflow/util/launch.ts @@ -1,13 +1,8 @@ -// npm i cross-fetch dotenv import "cross-fetch/polyfill"; import { config } from "dotenv"; import { resolve } from "path"; -config({ path: resolve(__dirname, "..", ".env") }); -import { announceExit, websocketLauncher } from "../util"; -import Bot from "./bot"; +import { announceExit } from "./index"; process.on("exit", announceExit); - -// Assert these are available on process.env yadda-yadda, otherwise would have to `process.env.BOT_TOKEN as string` declare global { namespace NodeJS { interface ProcessEnv { @@ -16,10 +11,12 @@ declare global { } } } +config({ path: resolve(__dirname, "..", ".env") }); + +import { SpeedySockets } from "./websockets"; +import Bot from "./../settings/bot"; -// Add secrets Bot.setToken(process.env.BOT_TOKEN as string); Bot.addSecret("VOICEFLOW_API_KEY", process.env.VOICEFLOW_API_KEY); -// Pass in your SpeedyBot -websocketLauncher(Bot).catch((e) => console.log("##", e)); +SpeedySockets(Bot, { force: false, debug: false }).catch((e) => console.log(e)); diff --git a/examples/voiceflow/util/utils.ts b/examples/voiceflow/util/utils.ts deleted file mode 100644 index 579d5e9..0000000 --- a/examples/voiceflow/util/utils.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { init } from "webex"; - -export class Websocket { - public webexRef!: StubbedWebEx; - public me: any; - public listeners: Listeners = {}; - constructor(public token: string) {} - on(eventName: Events, handler: Function) { - this.listeners[eventName] = handler; - } - - async getSelf() { - const { id } = await this.webexRef.people.get("me"); - this.me = id; - } - - async init() { - const config = { - credentials: { - access_token: this.token, - }, - }; - try { - this.webexRef = await init(config); - } catch (e) { - throw e; - } - } - - async start() { - try { - await this.init(); - await Promise.all([ - this.getSelf(), - this.webexRef.messages.listen(), - this.webexRef.attachmentActions.listen(), - ]); - - // messages - this.webexRef.messages.on("created", (event: any) => { - if (event.data.personId !== this.me) { - this.onMessage({ ...event, targetUrl: "websocket" }); - } - }); - - this.webexRef.attachmentActions.on("created", (event: any) => { - this.onSubmit({ ...event, targetUrl: "websocket" }); - }); - } catch (e) { - throw e; - } - } - - onMessage(event: any) { - if (this.listeners.message) { - this.listeners.message(event); - } - } - - onSubmit(event: any) { - if (this.listeners.submit) { - this.listeners.submit(event); - } - } - - async stop() { - await this.webexRef.internal.device.unregister(); - await this.webexRef.messages.stopListening(); - } - - async resetDevices() { - return resetDevices(this.token); - } -} - -export const resetDevices = async (token: string) => { - type Device = { - url: string; - webSocketUrl: string; - services: unknown; - }; - // Get devices - const deviceList: Response = await fetch( - "https://wdm-a.wbx2.com/wdm/api/v1/devices", - { - headers: { - Authorization: `Bearer ${token}`, - }, - } - ); - - if (!deviceList.ok) { - if (deviceList.status === 401) { - console.log( - `[❌ SpeedyBot] Token invalid-- double check the token is correct or you can regenerate a new one here: https://developer.webex.com/my-apps - ` - ); - process.exit(1); - } - } - const { devices = [] }: { devices: Device[] } = await deviceList.json(); - - for (const device of devices) { - const { url } = device; - if (url) { - await fetch(url, { - method: "DELETE", - headers: { - Authorization: `Bearer ${token}`, - }, - }); - } - } - return true; -}; -export type Listeners = { - [key: string]: Function; -}; - -export type AbbreviatedEvent = { - data: { - personId: string; - }; -}; - -export type EventCb = (evt: AbbreviatedEvent) => any; -export type StubbedWebEx = { - internal: { - services: { waitForService(...args): Promise }; - device: { unregister(...args): Promise }; - }; - request(...args): void; - people: { - get(id: string): Promise<{ id: string }>; - }; - messages: { - stopListening(): Promise; - listen(): Promise; - on(event: string, callback: EventCb): any; - }; - attachmentActions: { - listen(): Promise; - on(event: string, callback: EventCb): any; - }; -}; -export type Events = "message" | "submit" | "file" | "camera"; diff --git a/examples/voiceflow/util/websockets.ts b/examples/voiceflow/util/websockets.ts new file mode 100644 index 0000000..9c917b7 --- /dev/null +++ b/examples/voiceflow/util/websockets.ts @@ -0,0 +1,658 @@ +// Author: @valgaze +// Websockets are super useful but painful to use sometimes +// use bun or install Websocket with: +// $ npm install ws +import WebSocket from "ws"; // optional + +import { + type AA_Envelope, + type File_Details, + type MessageEnvelope, + type Message_Details, + type Submit_Details, + type SelfData, + SpeedyBot, +} from "speedybot"; + +import { logoRoll } from "speedybot"; + +// all the things that can go wrong :( +enum ErrorType { + HTTP_REQUEST_FAILED = "HTTP_REQUEST_FAILED", + WEBSOCKET_ERROR = "WEBSOCKET_ERROR", + INVALID_TOKEN = "INVALID_TOKEN", // 401 + EXCESSIVE_DEVICE = "EXCESSIVE_DEVICE", + UNKNOWN_ERROR = "UNKNOWN_ERROR", + FORBIDDEN_ERROR = "ERROR_FORBIDDEN", +} + +export type AbbeviatedDevice = { + url: string; + webSocketUrl: string; + services: unknown; + deviceType: string; + name: string; + model: string; + localizedModel: string; + systemName: string; + systemVersion: string; + capabilities: unknown; + features: unknown; + creationTime: string; + modificationTime: string; + deviceSettings: unknown; + deviceSettingsString: string; + showSupportText: boolean; + reportingSiteUrl: string; + reportingSiteDesc: string; + isDeviceManaged: boolean; + trainSiteNames: unknown[]; + clientSecurityPolicy: string; + intranetInactivityCheckUrl: string; + serviceHostMap: unknown; + blockExternalCommunications: boolean; + desktopFileShareControl: string; + mobileFileShareControl: string; + webFileShareControl: string; + botFileShareControl: string; + whiteboardFileShareControl: string; + clientMessagingGiphy: string; + clientMessagingLinkPreview: string; + ecmEnabledForAllUsers: boolean; + ecmSupportedStorageProviders: string[]; + defaultEcmMicrosoftCloud: string; + ecmMicrosoftTenant: string; + ecmScreenCaptureFeatureAllowed: boolean; + ecmWhiteboardFileDataAllowed: boolean; + callingBehavior: string; + onPremisePairingEnabled: boolean; + peopleInsightsEnabled: boolean; + allowSelfSignedCertificate: boolean; + webexCrossLaunch: boolean; + webexAppHubEnabled: boolean; + embeddedAppsEnabled: boolean; + settings: unknown; + selfSignupOrg: boolean; + userId: string; + orgId: string; + orgName: string; +}; + +export type Events = "text" | "card"; + +export type Data = { + [key: string]: any; +}; +export type BaseEnvelope = { + id: string; + name: string; + targetUrl: string; + resource: string; + event: string; + orgId: string; + createdBy: string; + appId: string; + ownedBy: string; + status: string; + created: Date; + actorId: string; + data: Data; +}; +export type MessagePayload = { + id: string; + timestamp: string | number; + data: { + eventType: + | "status.start_typing" // for first-press situations + | "conversation.activity" + | "conversation.highlight"; + activity?: { + id: string; + verb: "cardAction" | "post" | "acknowledge" | "update" | "share"; + actor: { + id: string; // email + objectType: string; + displayName: string; + orgId: string; + emailAddress: string; + entryUUID: string; + type: string; + }; + target: { + id: string; + objectType: string; + url: string; + published: string; + participants: { + items: any[]; + }; + activities: { + items: any[]; + }; + deletedActivityIds: any[]; + tags: string[]; + globalId: string; + }; + }; + }; +}; +export type SocketConfig = { debug: boolean; force?: boolean }; + +/** + * config: + * debug: show logs (noisy) + * force: force a new websocket connection each time (might cause excessive device registration) + */ +export class LocalSockets { + private submitFcn!: (AAEnv: AA_Envelope) => Promise | void; + onSubmit(cb: (AAEnv: AA_Envelope) => Promise | void) { + this.submitFcn = cb; + } + + private msgFcn!: (MsgEnv: MessageEnvelope) => Promise | void; + onText(cb: (MsgEnv: MessageEnvelope) => Promise | void) { + this.msgFcn = cb; + } + + private ws!: WebSocket; + constructor( + private _token: string, + private config: SocketConfig = { + debug: false, + force: false, + } + ) { + this.root = { + DEVICES_URL: "https://wdm-a.wbx2.com/wdm/api/v1/devices", + DEVICE_DATA: { + deviceName: "SpeedyBot-websockets", + deviceType: "DESKTOP", + localizedModel: "SpeedyBot", + model: "SpeedyBot", + name: this.config.force + ? `speedy-webex-${Math.random().toString(36).slice(2, 7)}` + : "speedybot-webex-reusable-websocket", + systemName: "SpeedyBot", + systemVersion: "1.0", + }, + }; + } + + private root: { + DEVICES_URL: string; + DEVICE_DATA: { + deviceName: string; + deviceType: string; + localizedModel: string; + model: string; + name: string; + systemName: string; + systemVersion: string; + }; + }; + + public log(...payload: any): void { + if (this.config.debug) + console.log.apply(console, [ + "[Speedy-Debug]", + ...(payload as [any?, ...any[]]), + ]); + } + + async start(): Promise { + this.log(`Getting device info...`); + this.log(this.root.DEVICE_DATA.name); + let device = await this.getDeviceInfo(); + if (!device || this.config.force) { + this.log( + `${ + this.config.force + ? "Force new device creation..." + : "Empty device refetching..." + }` + ); + device = await this.createDevice(); + this.log(`Device set`); + } + + if (this.ws) { + this.log(`Attempting socket disconnect`); + await this.disconnect(); + } + + if (device && "webSocketUrl" in device) { + this.log(`Registering websockets with + ${device.webSocketUrl}`); + this.log(`Device name: ${device.name}`); + await this.registerWebsockets(device.webSocketUrl); + this.log(`✅ websockets success`); + return true; + } else { + this.log(`🛑 websockets failure`); + return false; + } + } + + private buildUUID() { + return Math.random().toString(36).slice(2); + } + + handleApplicationError(error: any, errorType: ErrorType, message?: string) { + switch (errorType) { + case ErrorType.HTTP_REQUEST_FAILED: + console.error("HTTP request failed:", message, error); + break; + case ErrorType.WEBSOCKET_ERROR: + console.error("WebSocket error:", message, error); + break; + case ErrorType.INVALID_TOKEN: + console.error("Invalid token error:", message, error); + break; + case ErrorType.EXCESSIVE_DEVICE: + console.error("Excessive device registration error:", message, error); + break; + default: + console.error("Unknown error:", message, error); + break; + } + } + + private async createDevice(): Promise { + try { + const response = await fetch(this.root.DEVICES_URL, { + method: "POST", + headers: { + Authorization: `Bearer ${this._token}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(this.root.DEVICE_DATA), + }); + + if (!response.ok) { + if (response.status === 429 || response.status === 403) { + /** + * + * + { + message: "User has excessive device registrations", + errors: [ + { + description: "User has excessive device registrations", + } + ], + trackingId: "xxxxx", +} + * + */ + + throw new Error(ErrorType.EXCESSIVE_DEVICE); + } else { + throw new Error(ErrorType.UNKNOWN_ERROR); + } + } + const device = (await response.json()) as AbbeviatedDevice; + return device; + } catch (error: unknown) { + if (typeof error === "object" && error && "message" in error) { + if (error.message === ErrorType.EXCESSIVE_DEVICE) { + this.handleApplicationError( + error, + ErrorType.EXCESSIVE_DEVICE, + "WebSocket connection error" + ); + } else if (error.message === ErrorType.FORBIDDEN_ERROR) { + this.handleApplicationError( + error, + ErrorType.FORBIDDEN_ERROR, + "403 forbidden" + ); + } else { + this.handleApplicationError( + error, + ErrorType.UNKNOWN_ERROR, + "Unknown error on creation" + ); + } + } + } + } + + private async getDeviceInfo(): Promise { + try { + const response = await fetch(this.root.DEVICES_URL, { + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + + if (!response.ok && response.status === 401) { + throw new Error(ErrorType.INVALID_TOKEN); + } + + const data = (await response.json()) as + | { devices: AbbeviatedDevice[] } + | { + message: string; + errors: { description: string }[]; + trackingId: string; + }; + if ("devices" in data) { + this.log(`Total devices: ${data.devices.length}`); + const device = data.devices.find( + (device: any) => device.name === this.root.DEVICE_DATA.name + ); + return device; + } + } catch (error) { + if (typeof error === "object" && error && "message" in error) { + this.handleApplicationError( + error, + ErrorType.INVALID_TOKEN, + `[❌ SpeedyBot] Token invalid-- double check the token is correct or you can regenerate a new one here: +https://developer.webex.com/my-apps + +` + ); + } + } + } + + public async resetDevices() { + type Device = { + url: string; + webSocketUrl: string; + services: unknown; + }; + + try { + const deviceListResponse = await fetch( + "https://wdm-a.wbx2.com/wdm/api/v1/devices", + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + + if (!deviceListResponse.ok) { + if (deviceListResponse.status === 401) { + this.log(`Reset devices invalid token`); + throw new Error(ErrorType.INVALID_TOKEN); + } + throw new Error(ErrorType.HTTP_REQUEST_FAILED); + } + + const { devices = [] }: { devices: Device[] } = + (await deviceListResponse.json()) as { devices: Device[] }; + + for (const device of devices) { + const { url } = device; + if (url) { + const deleteResponse = await fetch(url, { + method: "DELETE", + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + + if (!deleteResponse.ok) { + throw new Error(ErrorType.HTTP_REQUEST_FAILED); + } + } + } + + return true; + } catch (error) { + if (error instanceof Error) { + if (error.message === ErrorType.HTTP_REQUEST_FAILED) { + this.handleApplicationError( + error, + ErrorType.HTTP_REQUEST_FAILED, + "Failed to reset devices" + ); + } else if (error.message === ErrorType.INVALID_TOKEN) { + this.handleApplicationError( + error, + ErrorType.INVALID_TOKEN, + `[❌ SpeedyBot] Token invalid-- double check the token is correct or you can regenerate a new one here: +https://developer.webex.com/my-apps + + ` + ); + } else { + this.handleApplicationError( + error, + ErrorType.UNKNOWN_ERROR, + "Unknown error while resetting devices" + ); + } + } + return false; + } + } + + public registerWebsockets(webSocketUrl: string) { + this.ws = new WebSocket(webSocketUrl); + this.ws.on("open", async () => { + this.log("🎸 Websocket open"); + const msg = { + id: this.buildUUID(), + type: "authorization", + data: { + token: `Bearer ${this._token}`, + }, + }; + this.ws.send(JSON.stringify(msg)); + }); + + this.ws.on("message", async (message: string) => { + try { + const msg = JSON.parse(message); + this.log(`📬 raw message received ${JSON.stringify(msg)}\n`); + await this.processMessage(msg); + } catch (error: unknown) { + if (typeof error === "object" && error && "message" in error) { + this.handleApplicationError( + error, + ErrorType.WEBSOCKET_ERROR, + "WebSocket error on message" + ); + } + } + }); + + this.ws.on("error", (error) => { + this.handleApplicationError( + error, + ErrorType.WEBSOCKET_ERROR, + "WebSocket connection error" + ); + }); + } + + public disconnect() { + if (this.ws) { + return this.ws.close(); + } + } + + private async checkEmail(email: string) { + const emailRes = await fetch("https://webexapis.com/v1/people/me", { + headers: { + Authorization: `Bearer ${this._token}`, + }, + }); + const { emails } = (await emailRes.json()) as SelfData; + const [myEmail] = emails; + return email !== myEmail; + } + + private async fetchMessagePayload(id: string): Promise { + const messageId = id.includes("-") + ? Buffer.from(`ciscospark://us/MESSAGE/${id}`).toString("base64") + : id; + + const response = await fetch( + `https://webexapis.com/v1/messages/${messageId}`, + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + const data = (await response.json()) as Message_Details; + return data; + } + + private async fetchCardPayload(id: string): Promise { + const attachmentActionId = id.includes("-") + ? Buffer.from(`ciscospark://us/ATTACHMENT_ACTION/${id}`).toString( + "base64" + ) + : id; + const response = await fetch( + `https://webexapis.com/v1/attachment/actions/${attachmentActionId}`, + { + headers: { + Authorization: `Bearer ${this._token}`, + }, + } + ); + const data = (await response.json()) as Promise; + return data; + } + + async processMessage(msg: MessagePayload): Promise { + if ( + msg.data.eventType === "conversation.activity" && + "activity" in msg.data && + msg.data.activity + ) { + const { id, verb, actor } = msg.data.activity; + const { emailAddress } = actor; + const proceed = await this.checkEmail(emailAddress); + if (!proceed) return false; // filter out mesages from agent + + // text [post] or file [share] message + if (verb === "post" || verb === "share") { + if (this.msgFcn) { + const payload = await this.fetchMessagePayload(id); + this.log(`[${verb}]`, id, payload); + const env = this.buildText(payload); + await this.msgFcn(env); + } + } + + // if adaptive card/attachmentAction submission [cardAction] + if (verb === "cardAction") { + if (this.submitFcn) { + const payload = await this.fetchCardPayload(id); + this.log("[cardAction]", payload); + const env = this.buildCard(payload); + await this.submitFcn(env); + } + } + } + + return true; + } + + setToken(token: string) { + this._token = token; + } + + getToken(): string { + return this._token; + } + + private buildText(payload: Message_Details | File_Details): MessageEnvelope { + return { + id: "__websocket_id", + name: "__websocket_name", + targetUrl: "__websocket_targetUrl", + resource: "messages", + event: "created", + orgId: "__websocket_orgId", + createdBy: "__websocket_createdBy", + appId: "__websocket_appId", + ownedBy: "creator", + status: "active", + created: new Date().toISOString(), + actorId: "__websocket_actorId", + data: payload, + }; + } + + private buildCard(payload: Submit_Details): AA_Envelope { + return { + id: "__websocket_id", + name: "__websocket_name", + targetUrl: "__websocket_targetUrl", + resource: "attachmentActions", + event: "created", + orgId: "__websocket_orgId", + createdBy: "__websocket_createdBy", + appId: "__websocket_appId", + ownedBy: "creator", + status: "active", + created: new Date().toISOString(), + actorId: "__websocket_actorId", + data: payload, + }; + } +} + +export const announceWebsockets = (email: string, name = "Your bot") => { + const isColorSupported = process.stdout.isTTY; + console.log(logoRoll()); + if (isColorSupported) { + const WEBSOCKETS_READY = `\x1b[1m\x1b[7m\x1b[32m 🌐 CONNECTED \x1b[0m\x1b[32m Websockets active, listening...\x1b[0m`; + process.stdout.write(WEBSOCKETS_READY + "\n"); + } else { + console.log("Websockets Registered. Listening..."); + } + console.log(`You can reach ${name} here: ${email}`); +}; + +/** + * Helper to surround SpeedyBot instance with websockets + * + */ +export async function SpeedySockets( + BotRef: SpeedyBot, + config: SocketConfig = { + debug: false, + force: false, + }, + cb?: (data?: { email: string; name?: string }) => any +): Promise { + try { + const token = BotRef.getToken(); + if (!token) { + throw new Error("No token provided (try Bot.setToken('__REPLACE__ME__')"); + } + const inst = new LocalSockets(token, config); + + inst.onSubmit(async (payload) => { + BotRef.runMiddleware(payload); + }); + + inst.onText((payload) => { + BotRef.runMiddleware(payload); + }); + + await inst.start(); + const data = await BotRef.getSelf(); + const { displayName } = data; + const [email] = data.emails; + + if (!cb) { + announceWebsockets(email, displayName); + } else { + return cb({ email, name: displayName }); + } + } catch (e) { + console.log(e); + throw e; + } +} diff --git a/examples/worker/settings/bot.ts b/examples/worker/settings/bot.ts index 8176156..1cab41c 100644 --- a/examples/worker/settings/bot.ts +++ b/examples/worker/settings/bot.ts @@ -14,14 +14,6 @@ Bot.addStep(async ($) => { } } - // file handler - if ($.file) { - const { name, extension, contentType } = $.file; - await $.send(`You uploaded "${name}", a *.${extension} file [${contentType}]`); - // Fetch raw bytes (which you can pass onto other systems) - // const TheData = await $.file.getData(); // do something w/ the contents/bytes - } - // adaptive card/form submissions if ($.data && !$.data.showCard && !$.data.randomSpeedyBot) { const dataSnippet = $.buildDataSnippet($.data); diff --git a/package-lock.json b/package-lock.json index 1676563..e41b612 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,36 +1,31 @@ { "name": "speedybot", - "version": "2.0.0-beta.73", + "version": "2.0.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "speedybot", - "version": "2.0.0-beta.73", + "version": "2.0.4", "license": "MIT", "bin": { "speedybot": "bin/cli.js" }, "devDependencies": { "@rollup/rollup-linux-x64-gnu": "latest", - "@types/jest": "^29.1.2", - "@types/minimist": "^1.2.5", "@types/node": "^18.8.4", "@vitest/coverage-v8": "^0.32.2", "@vitest/ui": "^0.32.2", "adaptivecards": "2.11.1", "element-plus": "^2.3.10", - "fs-extra": "^11.2.0", "monaco-editor": "^0.41.0", - "ts-jest": "^29.0.3", - "ts-node-dev": "^2.0.0", "tsx": "^3.10.1", "typedoc": "^0.22.18", "typedoc-plugin-markdown": "3.12.1", "typedoc-theme-hierarchy": "1.2.1", "typescript": "^4.7.2", "vite": "^4.3.9", - "vitepress": "^1.0.0-rc.31", + "vitepress": "^1.2.0", "vitest": "^0.32.2" }, "engines": { @@ -83,132 +78,151 @@ } }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.20.0.tgz", - "integrity": "sha512-uujahcBt4DxduBTvYdwO3sBfHuJvJokiC3BP1+O70fglmE1ShkH8lpXqZBac1rrU3FnNYSUs4pL9lBdTKeRPOQ==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.3.tgz", + "integrity": "sha512-vRHXYCpPlTDE7i6UOy2xE03zHF2C8MEFjPN2v7fRbqVpcOvAUQK81x3Kc21xyb5aSIpYCjWCZbYZuz8Glyzyyg==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.20.0" + "@algolia/cache-common": "4.23.3" } }, "node_modules/@algolia/cache-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.20.0.tgz", - "integrity": "sha512-vCfxauaZutL3NImzB2G9LjLt36vKAckc6DhMp05An14kVo8F1Yofb6SIl6U3SaEz8pG2QOB9ptwM5c+zGevwIQ==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.23.3.tgz", + "integrity": "sha512-h9XcNI6lxYStaw32pHpB1TMm0RuxphF+Ik4o7tcQiodEdpKK+wKufY6QXtba7t3k8eseirEMVB83uFFF3Nu54A==", "dev": true }, "node_modules/@algolia/cache-in-memory": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.20.0.tgz", - "integrity": "sha512-Wm9ak/IaacAZXS4mB3+qF/KCoVSBV6aLgIGFEtQtJwjv64g4ePMapORGmCyulCFwfePaRAtcaTbMcJF+voc/bg==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.23.3.tgz", + "integrity": "sha512-yvpbuUXg/+0rbcagxNT7un0eo3czx2Uf0y4eiR4z4SD7SiptwYTpbuS0IHxcLHG3lq22ukx1T6Kjtk/rT+mqNg==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.20.0" + "@algolia/cache-common": "4.23.3" } }, "node_modules/@algolia/client-account": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.20.0.tgz", - "integrity": "sha512-GGToLQvrwo7am4zVkZTnKa72pheQeez/16sURDWm7Seyz+HUxKi3BM6fthVVPUEBhtJ0reyVtuK9ArmnaKl10Q==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.23.3.tgz", + "integrity": "sha512-hpa6S5d7iQmretHHF40QGq6hz0anWEHGlULcTIT9tbUssWUriN9AUXIFQ8Ei4w9azD0hc1rUok9/DeQQobhQMA==", "dev": true, "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/client-search": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/client-analytics": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.20.0.tgz", - "integrity": "sha512-EIr+PdFMOallRdBTHHdKI3CstslgLORQG7844Mq84ib5oVFRVASuuPmG4bXBgiDbcsMLUeOC6zRVJhv1KWI0ug==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.23.3.tgz", + "integrity": "sha512-LBsEARGS9cj8VkTAVEZphjxTjMVCci+zIIiRhpFun9jGDUlS1XmhCW7CTrnaWeIuCQS/2iPyRqSy1nXPjcBLRA==", "dev": true, "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/client-search": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/client-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.20.0.tgz", - "integrity": "sha512-P3WgMdEss915p+knMMSd/fwiHRHKvDu4DYRrCRaBrsfFw7EQHon+EbRSm4QisS9NYdxbS04kcvNoavVGthyfqQ==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.23.3.tgz", + "integrity": "sha512-l6EiPxdAlg8CYhroqS5ybfIczsGUIAC47slLPOMDeKSVXYG1n0qGiz4RjAHLw2aD0xzh2EXZ7aRguPfz7UKDKw==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/client-personalization": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.20.0.tgz", - "integrity": "sha512-N9+zx0tWOQsLc3K4PVRDV8GUeOLAY0i445En79Pr3zWB+m67V+n/8w4Kw1C5LlbHDDJcyhMMIlqezh6BEk7xAQ==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.23.3.tgz", + "integrity": "sha512-3E3yF3Ocr1tB/xOZiuC3doHQBQ2zu2MPTYZ0d4lpfWads2WTKG7ZzmGnsHmm63RflvDeLK/UVx7j2b3QuwKQ2g==", "dev": true, "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/client-search": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.20.0.tgz", - "integrity": "sha512-zgwqnMvhWLdpzKTpd3sGmMlr4c+iS7eyyLGiaO51zDZWGMkpgoNVmltkzdBwxOVXz0RsFMznIxB9zuarUv4TZg==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.23.3.tgz", + "integrity": "sha512-P4VAKFHqU0wx9O+q29Q8YVuaowaZ5EM77rxfmGnkHUJggh28useXQdopokgwMeYw2XUht49WX5RcTQ40rZIabw==", "dev": true, "dependencies": { - "@algolia/client-common": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/transporter": "4.20.0" + "@algolia/client-common": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/logger-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.20.0.tgz", - "integrity": "sha512-xouigCMB5WJYEwvoWW5XDv7Z9f0A8VoXJc3VKwlHJw/je+3p2RcDXfksLI4G4lIVncFUYMZx30tP/rsdlvvzHQ==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.23.3.tgz", + "integrity": "sha512-y9kBtmJwiZ9ZZ+1Ek66P0M68mHQzKRxkW5kAAXYN/rdzgDN0d2COsViEFufxJ0pb45K4FRcfC7+33YB4BLrZ+g==", "dev": true }, "node_modules/@algolia/logger-console": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.20.0.tgz", - "integrity": "sha512-THlIGG1g/FS63z0StQqDhT6bprUczBI8wnLT3JWvfAQDZX5P6fCg7dG+pIrUBpDIHGszgkqYEqECaKKsdNKOUA==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.23.3.tgz", + "integrity": "sha512-8xoiseoWDKuCVnWP8jHthgaeobDLolh00KJAdMe9XPrWPuf1by732jSpgy2BlsLTaT9m32pHI8CRfrOqQzHv3A==", + "dev": true, + "dependencies": { + "@algolia/logger-common": "4.23.3" + } + }, + "node_modules/@algolia/recommend": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.23.3.tgz", + "integrity": "sha512-9fK4nXZF0bFkdcLBRDexsnGzVmu4TSYZqxdpgBW2tEyfuSSY54D4qSRkLmNkrrz4YFvdh2GM1gA8vSsnZPR73w==", "dev": true, "dependencies": { - "@algolia/logger-common": "4.20.0" + "@algolia/cache-browser-local-storage": "4.23.3", + "@algolia/cache-common": "4.23.3", + "@algolia/cache-in-memory": "4.23.3", + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/logger-console": "4.23.3", + "@algolia/requester-browser-xhr": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/requester-node-http": "4.23.3", + "@algolia/transporter": "4.23.3" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.20.0.tgz", - "integrity": "sha512-HbzoSjcjuUmYOkcHECkVTwAelmvTlgs48N6Owt4FnTOQdwn0b8pdht9eMgishvk8+F8bal354nhx/xOoTfwiAw==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.3.tgz", + "integrity": "sha512-jDWGIQ96BhXbmONAQsasIpTYWslyjkiGu0Quydjlowe+ciqySpiDUrJHERIRfELE5+wFc7hc1Q5hqjGoV7yghw==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.20.0" + "@algolia/requester-common": "4.23.3" } }, "node_modules/@algolia/requester-common": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.20.0.tgz", - "integrity": "sha512-9h6ye6RY/BkfmeJp7Z8gyyeMrmmWsMOCRBXQDs4mZKKsyVlfIVICpcSibbeYcuUdurLhIlrOUkH3rQEgZzonng==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.23.3.tgz", + "integrity": "sha512-xloIdr/bedtYEGcXCiF2muajyvRhwop4cMZo+K2qzNht0CMzlRkm8YsDdj5IaBhshqfgmBb3rTg4sL4/PpvLYw==", "dev": true }, "node_modules/@algolia/requester-node-http": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.20.0.tgz", - "integrity": "sha512-ocJ66L60ABSSTRFnCHIEZpNHv6qTxsBwJEPfYaSBsLQodm0F9ptvalFkHMpvj5DfE22oZrcrLbOYM2bdPJRHng==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.23.3.tgz", + "integrity": "sha512-zgu++8Uj03IWDEJM3fuNl34s746JnZOWn1Uz5taV1dFyJhVM/kTNw9Ik7YJWiUNHJQXcaD8IXD1eCb0nq/aByA==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.20.0" + "@algolia/requester-common": "4.23.3" } }, "node_modules/@algolia/transporter": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.20.0.tgz", - "integrity": "sha512-Lsii1pGWOAISbzeyuf+r/GPhvHMPHSPrTDWNcIzOE1SG1inlJHICaVe2ikuoRjcpgxZNU54Jl+if15SUCsaTUg==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.23.3.tgz", + "integrity": "sha512-Wjl5gttqnf/gQKJA+dafnD0Y6Yw97yvfY8R9h0dQltX1GXTgNs1zWgvtWW0tHl1EgMdhAyw189uWiZMnL3QebQ==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.20.0", - "@algolia/logger-common": "4.20.0", - "@algolia/requester-common": "4.20.0" + "@algolia/cache-common": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/requester-common": "4.23.3" } }, "node_modules/@ampproject/remapping": { @@ -224,4332 +238,2312 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "node_modules/@babel/parser": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", "dev": true, - "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@docsearch/css": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.0.tgz", + "integrity": "sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==", + "dev": true + }, + "node_modules/@docsearch/js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.6.0.tgz", + "integrity": "sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" + "@docsearch/react": "3.6.0", + "preact": "^10.0.0" } }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@docsearch/react": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.0.tgz", + "integrity": "sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==", "dev": true, "dependencies": { - "color-name": "1.1.3" + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.6.0", + "algoliasearch": "^4.19.1" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } } }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/@element-plus/icons-vue": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz", + "integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==", "dev": true, - "engines": { - "node": ">=0.8.0" + "peerDependencies": { + "vue": "^3.2.0" } }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], "dev": true, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], "dev": true, - "peer": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz", - "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==", - "dev": true, - "peer": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.5", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.5", - "@babel/parser": "^7.23.5", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "node": ">=12" } }, - "node_modules/@babel/generator": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz", - "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==", + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.23.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], "dev": true, - "peer": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.22.15" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], "dev": true, - "peer": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], "dev": true, - "peer": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], "dev": true, - "peer": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helpers": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz", - "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==", + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.5", - "@babel/types": "^7.23.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/@babel/parser": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", - "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "node_modules/@floating-ui/core": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.1.tgz", + "integrity": "sha512-QgcKYwzcc8vvZ4n/5uklchy8KVdjJwcOeI+HnnTNclJjs2nYsy23DOCf+sSV1kBwD9yDAoVKCkv/gEPzgQU3Pw==", "dev": true, - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@floating-ui/utils": "^0.1.3" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "node_modules/@floating-ui/dom": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz", + "integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==", "dev": true, - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@floating-ui/core": "^1.4.2", + "@floating-ui/utils": "^0.1.3" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@floating-ui/utils": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", + "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==", + "dev": true }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@sinclair/typebox": "^0.27.8" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "peer": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 8" } }, - "node_modules/@babel/traverse": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz", - "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.5", - "@babel/types": "^7.23.5", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } + "node_modules/@polka/url": { + "version": "1.0.0-next.23", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", + "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", + "dev": true }, - "node_modules/@babel/types": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz", - "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==", + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==", "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz", + "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz", + "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@ctrl/tinycolor": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", - "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz", + "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==", + "cpu": [ + "arm64" + ], "dev": true, - "engines": { - "node": ">=10" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@docsearch/css": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.5.2.tgz", - "integrity": "sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==", - "dev": true + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz", + "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@docsearch/js": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.5.2.tgz", - "integrity": "sha512-p1YFTCDflk8ieHgFJYfmyHBki1D61+U9idwrLh+GQQMrBSP3DLGKpy0XUJtPjAOPltcVbqsTjiPFfH7JImjUNg==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz", + "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@docsearch/react": "3.5.2", - "preact": "^10.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@docsearch/react": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.5.2.tgz", - "integrity": "sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==", + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz", + "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@algolia/autocomplete-core": "1.9.3", - "@algolia/autocomplete-preset-algolia": "1.9.3", - "@docsearch/css": "3.5.2", - "algoliasearch": "^4.19.1" - }, - "peerDependencies": { - "@types/react": ">= 16.8.0 < 19.0.0", - "react": ">= 16.8.0 < 19.0.0", - "react-dom": ">= 16.8.0 < 19.0.0", - "search-insights": ">= 1 < 3" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "search-insights": { - "optional": true - } - } - }, - "node_modules/@element-plus/icons-vue": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz", - "integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==", - "dev": true, - "peerDependencies": { - "vue": "^3.2.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz", + "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.1.tgz", - "integrity": "sha512-QgcKYwzcc8vvZ4n/5uklchy8KVdjJwcOeI+HnnTNclJjs2nYsy23DOCf+sSV1kBwD9yDAoVKCkv/gEPzgQU3Pw==", - "dev": true, - "dependencies": { - "@floating-ui/utils": "^0.1.3" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz", - "integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==", - "dev": true, - "dependencies": { - "@floating-ui/core": "^1.4.2", - "@floating-ui/utils": "^0.1.3" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", - "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==", - "dev": true - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "peer": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "peer": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "peer": true, - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "peer": true, - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "peer": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "peer": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "linux" + ] }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz", + "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==", + "cpu": [ + "arm64" + ], "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz", + "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "peer": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz", + "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==", + "cpu": [ + "riscv64" + ], "dev": true, - "peer": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz", + "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==", + "cpu": [ + "s390x" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz", + "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "os": [ + "linux" + ] }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.23", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", - "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", - "dev": true - }, - "node_modules/@popperjs/core": { - "name": "@sxzz/popperjs-es", - "version": "2.11.7", - "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", - "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.6.1.tgz", - "integrity": "sha512-cEXJQY/ZqMACb+nxzDeX9IPLAg7S94xouJJCNVE5BJM8JUEP4HeTF+ti3cmxWeSJo+5D+o8Tc0UAWUkfENdeyw==", - "cpu": [ - "arm64" - ], + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz", + "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==", + "cpu": [ + "x64" + ], "dev": true, "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.6.1.tgz", - "integrity": "sha512-DNGZvZDO5YF7jN5fX8ZqmGLjZEXIJRdJEdTFMhiyXqyXubBa0WVLDWSNlQ5JR2PNgDbEV1VQowhVRUh+74D+RA==", - "cpu": [ - "x64" - ], - "dev": true, "os": [ "linux" ] }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "peer": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "peer": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.7", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.7.tgz", - "integrity": "sha512-6Sfsq+EaaLrw4RmdFWE9Onp63TOUue71AWb4Gpa6JxzgTYtimbM086WnYTy2U67AofR++QKCo08ZP6pwx8YFHQ==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.4", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", - "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/chai": { - "version": "4.3.11", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz", - "integrity": "sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==", - "dev": true - }, - "node_modules/@types/chai-subset": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.5.tgz", - "integrity": "sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==", - "dev": true, - "dependencies": { - "@types/chai": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/hast": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.3.tgz", - "integrity": "sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ==", - "dev": true, - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "29.5.10", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", - "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", - "dev": true, - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "node_modules/@types/linkify-it": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", - "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==", - "dev": true - }, - "node_modules/@types/lodash": { - "version": "4.14.202", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", - "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", - "dev": true - }, - "node_modules/@types/lodash-es": { - "version": "4.17.12", - "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", - "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/markdown-it": { - "version": "13.0.7", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-13.0.7.tgz", - "integrity": "sha512-U/CBi2YUUcTHBt5tjO2r5QV/x0Po6nsYwQU4Y04fBS6vfoImaiZ6f8bi3CjTCxBPQSO1LMyUqkByzi8AidyxfA==", - "dev": true, - "dependencies": { - "@types/linkify-it": "*", - "@types/mdurl": "*" - } - }, - "node_modules/@types/mdast": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.3.tgz", - "integrity": "sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==", - "dev": true, - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/mdurl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz", - "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==", - "dev": true - }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.19.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.1.tgz", - "integrity": "sha512-mZJ9V11gG5Vp0Ox2oERpeFDl+JvCwK24PGy76vVY/UgBtjwJWc5rYBThFxmbnYOm9UPZNm6wEl/sxHt2SU7x9A==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true - }, - "node_modules/@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", - "dev": true - }, - "node_modules/@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true - }, - "node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, - "node_modules/@types/web-bluetooth": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", - "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==", - "dev": true - }, - "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/@vitejs/plugin-vue": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.5.1.tgz", - "integrity": "sha512-DaUzYFr+2UGDG7VSSdShKa9sIWYBa1LL8KC0MNOf2H5LjcTPjob0x8LbkqXWmAtbANJCkpiQTj66UVcQkN2s3g==", - "dev": true, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.0.0 || ^5.0.0", - "vue": "^3.2.25" - } - }, - "node_modules/@vitest/coverage-v8": { - "version": "0.32.4", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-0.32.4.tgz", - "integrity": "sha512-itiCYY3TmWEK+5wnFBoNr0ZA+adACp7Op1r2TeX5dPOgU2See7+Gx2NlK2lVMHVxfPsu5z9jszKa3i//eR+hqg==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.1", - "@bcoe/v8-coverage": "^0.2.3", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.1", - "istanbul-reports": "^3.1.5", - "magic-string": "^0.30.0", - "picocolors": "^1.0.0", - "std-env": "^3.3.3", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "vitest": ">=0.32.0 <1" - } - }, - "node_modules/@vitest/expect": { - "version": "0.32.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.32.4.tgz", - "integrity": "sha512-m7EPUqmGIwIeoU763N+ivkFjTzbaBn0n9evsTOcde03ugy2avPs3kZbYmw3DkcH1j5mxhMhdamJkLQ6dM1bk/A==", - "dev": true, - "dependencies": { - "@vitest/spy": "0.32.4", - "@vitest/utils": "0.32.4", - "chai": "^4.3.7" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "0.32.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.32.4.tgz", - "integrity": "sha512-cHOVCkiRazobgdKLnczmz2oaKK9GJOw6ZyRcaPdssO1ej+wzHVIkWiCiNacb3TTYPdzMddYkCgMjZ4r8C0JFCw==", - "dev": true, - "dependencies": { - "@vitest/utils": "0.32.4", - "p-limit": "^4.0.0", - "pathe": "^1.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@vitest/runner/node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@vitest/snapshot": { - "version": "0.32.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.32.4.tgz", - "integrity": "sha512-IRpyqn9t14uqsFlVI2d7DFMImGMs1Q9218of40bdQQgMePwVdmix33yMNnebXcTzDU5eiV3eUsoxxH5v0x/IQA==", - "dev": true, - "dependencies": { - "magic-string": "^0.30.0", - "pathe": "^1.1.1", - "pretty-format": "^29.5.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "0.32.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.32.4.tgz", - "integrity": "sha512-oA7rCOqVOOpE6rEoXuCOADX7Lla1LIa4hljI2MSccbpec54q+oifhziZIJXxlE/CvI2E+ElhBHzVu0VEvJGQKQ==", - "dev": true, - "dependencies": { - "tinyspy": "^2.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/ui": { - "version": "0.32.4", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-0.32.4.tgz", - "integrity": "sha512-92y7bkjf55L08nomvHHYQkDWQEIkb36dJkgi+F/zpO5cFbrmk1pv/dYiaZKQ772uP96fAWinmux6sXNMNUh16w==", - "dev": true, - "dependencies": { - "@vitest/utils": "0.32.4", - "fast-glob": "^3.2.12", - "fflate": "^0.8.0", - "flatted": "^3.2.7", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "sirv": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "vitest": ">=0.30.1 <1" - } - }, - "node_modules/@vitest/utils": { - "version": "0.32.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.32.4.tgz", - "integrity": "sha512-Gwnl8dhd1uJ+HXrYyV0eRqfmk9ek1ASE/LWfTCuWMw+d07ogHqp4hEAV28NiecimK6UY9DpSEPh+pXBA5gtTBg==", - "dev": true, - "dependencies": { - "diff-sequences": "^29.4.3", - "loupe": "^2.3.6", - "pretty-format": "^29.5.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.9.tgz", - "integrity": "sha512-+/Lf68Vr/nFBA6ol4xOtJrW+BQWv3QWKfRwGSm70jtXwfhZNF4R/eRgyVJYoxFRhdCTk/F6g99BP0ffPgZihfQ==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.23.3", - "@vue/shared": "3.3.9", - "estree-walker": "^2.0.2", - "source-map-js": "^1.0.2" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.9.tgz", - "integrity": "sha512-nfWubTtLXuT4iBeDSZ5J3m218MjOy42Vp2pmKVuBKo2/BLcrFUX8nCSr/bKRFiJ32R8qbdnnnBgRn9AdU5v0Sg==", - "dev": true, - "dependencies": { - "@vue/compiler-core": "3.3.9", - "@vue/shared": "3.3.9" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.9.tgz", - "integrity": "sha512-wy0CNc8z4ihoDzjASCOCsQuzW0A/HP27+0MDSSICMjVIFzk/rFViezkR3dzH+miS2NDEz8ywMdbjO5ylhOLI2A==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.23.3", - "@vue/compiler-core": "3.3.9", - "@vue/compiler-dom": "3.3.9", - "@vue/compiler-ssr": "3.3.9", - "@vue/reactivity-transform": "3.3.9", - "@vue/shared": "3.3.9", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.5", - "postcss": "^8.4.31", - "source-map-js": "^1.0.2" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.9.tgz", - "integrity": "sha512-NO5oobAw78R0G4SODY5A502MGnDNiDjf6qvhn7zD7TJGc8XDeIEw4fg6JU705jZ/YhuokBKz0A5a/FL/XZU73g==", - "dev": true, - "dependencies": { - "@vue/compiler-dom": "3.3.9", - "@vue/shared": "3.3.9" - } - }, - "node_modules/@vue/devtools-api": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.1.tgz", - "integrity": "sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==", - "dev": true - }, - "node_modules/@vue/reactivity": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.9.tgz", - "integrity": "sha512-VmpIqlNp+aYDg2X0xQhJqHx9YguOmz2UxuUJDckBdQCNkipJvfk9yA75woLWElCa0Jtyec3lAAt49GO0izsphw==", - "dev": true, - "dependencies": { - "@vue/shared": "3.3.9" - } - }, - "node_modules/@vue/reactivity-transform": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.9.tgz", - "integrity": "sha512-HnUFm7Ry6dFa4Lp63DAxTixUp8opMtQr6RxQCpDI1vlh12rkGIeYqMvJtK+IKyEfEOa2I9oCkD1mmsPdaGpdVg==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.23.3", - "@vue/compiler-core": "3.3.9", - "@vue/shared": "3.3.9", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.5" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.9.tgz", - "integrity": "sha512-xxaG9KvPm3GTRuM4ZyU8Tc+pMVzcu6eeoSRQJ9IE7NmCcClW6z4B3Ij6L4EDl80sxe/arTtQ6YmgiO4UZqRc+w==", - "dev": true, - "dependencies": { - "@vue/reactivity": "3.3.9", - "@vue/shared": "3.3.9" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.9.tgz", - "integrity": "sha512-e7LIfcxYSWbV6BK1wQv9qJyxprC75EvSqF/kQKe6bdZEDNValzeRXEVgiX7AHI6hZ59HA4h7WT5CGvm69vzJTQ==", - "dev": true, - "dependencies": { - "@vue/runtime-core": "3.3.9", - "@vue/shared": "3.3.9", - "csstype": "^3.1.2" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.9.tgz", - "integrity": "sha512-w0zT/s5l3Oa3ZjtLW88eO4uV6AQFqU8X5GOgzq7SkQQu6vVr+8tfm+OI2kDBplS/W/XgCBuFXiPw6T5EdwXP0A==", - "dev": true, - "dependencies": { - "@vue/compiler-ssr": "3.3.9", - "@vue/shared": "3.3.9" - }, - "peerDependencies": { - "vue": "3.3.9" - } - }, - "node_modules/@vue/shared": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.9.tgz", - "integrity": "sha512-ZE0VTIR0LmYgeyhurPTpy4KzKsuDyQbMSdM49eKkMnT5X4VfFBLysMzjIZhLEFQYjjOVVfbvUDHckwjDFiO2eA==", - "dev": true - }, - "node_modules/@vueuse/core": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", - "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", - "dev": true, - "dependencies": { - "@types/web-bluetooth": "^0.0.16", - "@vueuse/metadata": "9.13.0", - "@vueuse/shared": "9.13.0", - "vue-demi": "*" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@vueuse/core/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", - "dev": true, - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, - "node_modules/@vueuse/integrations": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-10.6.1.tgz", - "integrity": "sha512-mPDupuofMJ4DPmtX/FfP1MajmWRzYDv8WSaTCo8LQ5kFznjWgmUQ16ApjYqgMquqffNY6+IRMdMgosLDRZOSZA==", - "dev": true, - "dependencies": { - "@vueuse/core": "10.6.1", - "@vueuse/shared": "10.6.1", - "vue-demi": ">=0.14.6" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "async-validator": "*", - "axios": "*", - "change-case": "*", - "drauu": "*", - "focus-trap": "*", - "fuse.js": "*", - "idb-keyval": "*", - "jwt-decode": "*", - "nprogress": "*", - "qrcode": "*", - "sortablejs": "*", - "universal-cookie": "*" - }, - "peerDependenciesMeta": { - "async-validator": { - "optional": true - }, - "axios": { - "optional": true - }, - "change-case": { - "optional": true - }, - "drauu": { - "optional": true - }, - "focus-trap": { - "optional": true - }, - "fuse.js": { - "optional": true - }, - "idb-keyval": { - "optional": true - }, - "jwt-decode": { - "optional": true - }, - "nprogress": { - "optional": true - }, - "qrcode": { - "optional": true - }, - "sortablejs": { - "optional": true - }, - "universal-cookie": { - "optional": true - } - } - }, - "node_modules/@vueuse/integrations/node_modules/@types/web-bluetooth": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", - "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", - "dev": true - }, - "node_modules/@vueuse/integrations/node_modules/@vueuse/core": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.6.1.tgz", - "integrity": "sha512-Pc26IJbqgC9VG1u6VY/xrXXfxD33hnvxBnKrLlA2LJlyHII+BSrRoTPJgGYq7qZOu61itITFUnm6QbacwZ4H8Q==", - "dev": true, - "dependencies": { - "@types/web-bluetooth": "^0.0.20", - "@vueuse/metadata": "10.6.1", - "@vueuse/shared": "10.6.1", - "vue-demi": ">=0.14.6" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@vueuse/integrations/node_modules/@vueuse/metadata": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.6.1.tgz", - "integrity": "sha512-qhdwPI65Bgcj23e5lpGfQsxcy0bMjCAsUGoXkJ7DsoeDUdasbZ2DBa4dinFCOER3lF4gwUv+UD2AlA11zdzMFw==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@vueuse/integrations/node_modules/@vueuse/shared": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.6.1.tgz", - "integrity": "sha512-TECVDTIedFlL0NUfHWncf3zF9Gc4VfdxfQc8JFwoVZQmxpONhLxFrlm0eHQeidHj4rdTPL3KXJa0TZCk1wnc5Q==", - "dev": true, - "dependencies": { - "vue-demi": ">=0.14.6" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@vueuse/integrations/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", - "dev": true, - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, - "node_modules/@vueuse/metadata": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", - "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@vueuse/shared": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", - "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", - "dev": true, - "dependencies": { - "vue-demi": "*" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/@vueuse/shared/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", - "dev": true, - "hasInstallScript": true, - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/adaptivecards": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/adaptivecards/-/adaptivecards-2.11.1.tgz", - "integrity": "sha512-dyF23HK+lRMEreexJgHz4y9U5B0ZuGk66N8nhwXRnICyYjq8hE4A6n8rLoV/CNY2QAZ0iRjOIR2J8U7M1CKl8Q==", - "dev": true - }, - "node_modules/algoliasearch": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.20.0.tgz", - "integrity": "sha512-y+UHEjnOItoNy0bYO+WWmLWBlPwDjKHW6mNHrPi0NkuhpQOOEbrkwQH/wgKFDLh7qlKjzoKeiRtlpewDPDG23g==", - "dev": true, - "dependencies": { - "@algolia/cache-browser-local-storage": "4.20.0", - "@algolia/cache-common": "4.20.0", - "@algolia/cache-in-memory": "4.20.0", - "@algolia/client-account": "4.20.0", - "@algolia/client-analytics": "4.20.0", - "@algolia/client-common": "4.20.0", - "@algolia/client-personalization": "4.20.0", - "@algolia/client-search": "4.20.0", - "@algolia/logger-common": "4.20.0", - "@algolia/logger-console": "4.20.0", - "@algolia/requester-browser-xhr": "4.20.0", - "@algolia/requester-common": "4.20.0", - "@algolia/requester-node-http": "4.20.0", - "@algolia/transporter": "4.20.0" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "peer": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "peer": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/async-validator": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", - "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", - "dev": true - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "peer": true, - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "peer": true, - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, - "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "peer": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001565", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz", - "integrity": "sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true - }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chai": { - "version": "4.3.10", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", - "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true, - "peer": true - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "peer": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "peer": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true, - "peer": true - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "peer": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", - "dev": true - }, - "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", - "dev": true - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "peer": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dynamic-dedupe": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", - "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", - "dev": true, - "dependencies": { - "xtend": "^4.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.601", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.601.tgz", - "integrity": "sha512-SpwUMDWe9tQu8JX5QCO1+p/hChAi9AE9UpoC3rcHVc+gdCGlbT3SGb5I1klgb952HRIyvt9wZhSz9bNBYz9swA==", - "dev": true, - "peer": true - }, - "node_modules/element-plus": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.4.3.tgz", - "integrity": "sha512-b3q26j+lM4SBqiyzw8HybybGnP2pk4MWgrnzzzYW5qKQUgV6EG1Zg7nMCfgCVccI8tNvZoTiUHb2mFaiB9qT8w==", - "dev": true, - "dependencies": { - "@ctrl/tinycolor": "^3.4.1", - "@element-plus/icons-vue": "^2.3.1", - "@floating-ui/dom": "^1.0.1", - "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", - "@types/lodash": "^4.14.182", - "@types/lodash-es": "^4.17.6", - "@vueuse/core": "^9.1.0", - "async-validator": "^4.2.5", - "dayjs": "^1.11.3", - "escape-html": "^1.0.3", - "lodash": "^4.17.21", - "lodash-es": "^4.17.21", - "lodash-unified": "^1.0.2", - "memoize-one": "^6.0.0", - "normalize-wheel-es": "^1.2.0" - }, - "peerDependencies": { - "vue": "^3.2.0" - } - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz", + "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==", + "cpu": [ + "arm64" + ], "dev": true, - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz", + "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==", + "cpu": [ + "ia32" + ], "dev": true, - "peer": true + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz", + "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==", + "cpu": [ + "x64" + ], "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/@shikijs/core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.6.0.tgz", + "integrity": "sha512-NIEAi5U5R7BLkbW1pG/ZKu3eb1lzc3/+jD0lFsuxMT7zjaf9bbNwdNyMr7zh/Zl8EXQtQ+MYBAt5G+JLu+5DlA==", + "dev": true + }, + "node_modules/@shikijs/transformers": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.6.0.tgz", + "integrity": "sha512-qGfHe1ECiqfE2STPWvfogIj/9Q0SK+MCRJdoITkW7AmFuB7DmbFnBT2US84+zklJOB51MzNO8RUXZiauWssJlQ==", "dev": true, - "peer": true, "dependencies": { - "is-arrayish": "^0.2.1" + "shiki": "1.6.0" } }, - "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "node_modules/@shikijs/transformers/node_modules/shiki": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.6.0.tgz", + "integrity": "sha512-P31ROeXcVgW/k3Z+vUUErcxoTah7ZRaimctOpzGuqAntqnnSmx1HOsvnbAB8Z2qfXPRhw61yptAzCsuKOhTHwQ==", "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" + "dependencies": { + "@shikijs/core": "1.6.0" } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@types/chai": { + "version": "4.3.11", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz", + "integrity": "sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==", + "dev": true + }, + "node_modules/@types/chai-subset": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.5.tgz", + "integrity": "sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==", "dev": true, - "peer": true, - "engines": { - "node": ">=6" + "dependencies": { + "@types/chai": "*" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.202", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", + "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", + "dev": true + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@types/lodash": "*" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/@types/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==", "dev": true, - "peer": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "dev": true }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/@types/node": { + "version": "18.19.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.1.tgz", + "integrity": "sha512-mZJ9V11gG5Vp0Ox2oERpeFDl+JvCwK24PGy76vVY/UgBtjwJWc5rYBThFxmbnYOm9UPZNm6wEl/sxHt2SU7x9A==", "dev": true, - "peer": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "undici-types": "~5.26.4" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.8.0" - } + "node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==", + "dev": true }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "node_modules/@vitest/coverage-v8": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-0.32.4.tgz", + "integrity": "sha512-itiCYY3TmWEK+5wnFBoNr0ZA+adACp7Op1r2TeX5dPOgU2See7+Gx2NlK2lVMHVxfPsu5z9jszKa3i//eR+hqg==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" + "@ampproject/remapping": "^2.2.1", + "@bcoe/v8-coverage": "^0.2.3", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.1.5", + "magic-string": "^0.30.0", + "picocolors": "^1.0.0", + "std-env": "^3.3.3", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.1.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": ">=0.32.0 <1" } }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "node_modules/@vitest/expect": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.32.4.tgz", + "integrity": "sha512-m7EPUqmGIwIeoU763N+ivkFjTzbaBn0n9evsTOcde03ugy2avPs3kZbYmw3DkcH1j5mxhMhdamJkLQ6dM1bk/A==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "@vitest/spy": "0.32.4", + "@vitest/utils": "0.32.4", + "chai": "^4.3.7" }, - "engines": { - "node": ">=8.6.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "node_modules/@vitest/runner": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.32.4.tgz", + "integrity": "sha512-cHOVCkiRazobgdKLnczmz2oaKK9GJOw6ZyRcaPdssO1ej+wzHVIkWiCiNacb3TTYPdzMddYkCgMjZ4r8C0JFCw==", "dev": true, "dependencies": { - "reusify": "^1.0.4" + "@vitest/utils": "0.32.4", + "p-limit": "^4.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, - "peer": true, "dependencies": { - "bser": "2.1.1" + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fflate": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.1.tgz", - "integrity": "sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ==", - "dev": true + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/@vitest/snapshot": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.32.4.tgz", + "integrity": "sha512-IRpyqn9t14uqsFlVI2d7DFMImGMs1Q9218of40bdQQgMePwVdmix33yMNnebXcTzDU5eiV3eUsoxxH5v0x/IQA==", "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "magic-string": "^0.30.0", + "pathe": "^1.1.1", + "pretty-format": "^29.5.0" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@vitest/spy": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.32.4.tgz", + "integrity": "sha512-oA7rCOqVOOpE6rEoXuCOADX7Lla1LIa4hljI2MSccbpec54q+oifhziZIJXxlE/CvI2E+ElhBHzVu0VEvJGQKQ==", "dev": true, - "peer": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "tinyspy": "^2.1.1" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true - }, - "node_modules/focus-trap": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", - "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", + "node_modules/@vitest/ui": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-0.32.4.tgz", + "integrity": "sha512-92y7bkjf55L08nomvHHYQkDWQEIkb36dJkgi+F/zpO5cFbrmk1pv/dYiaZKQ772uP96fAWinmux6sXNMNUh16w==", "dev": true, "dependencies": { - "tabbable": "^6.2.0" + "@vitest/utils": "0.32.4", + "fast-glob": "^3.2.12", + "fflate": "^0.8.0", + "flatted": "^3.2.7", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "sirv": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": ">=0.30.1 <1" } }, - "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "node_modules/@vitest/utils": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.32.4.tgz", + "integrity": "sha512-Gwnl8dhd1uJ+HXrYyV0eRqfmk9ek1ASE/LWfTCuWMw+d07ogHqp4hEAV28NiecimK6UY9DpSEPh+pXBA5gtTBg==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" }, - "engines": { - "node": ">=14.14" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/@vue/compiler-core": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.27.tgz", + "integrity": "sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "dependencies": { + "@babel/parser": "^7.24.4", + "@vue/shared": "3.4.27", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/@vue/compiler-dom": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz", + "integrity": "sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "@vue/compiler-core": "3.4.27", + "@vue/shared": "3.4.27" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/@vue/compiler-sfc": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz", + "integrity": "sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==", "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" + "dependencies": { + "@babel/parser": "^7.24.4", + "@vue/compiler-core": "3.4.27", + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.38", + "source-map-js": "^1.2.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/@vue/compiler-ssr": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz", + "integrity": "sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==", "dev": true, - "peer": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" + "dependencies": { + "@vue/compiler-dom": "3.4.27", + "@vue/shared": "3.4.27" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "node_modules/@vue/devtools-api": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.2.1.tgz", + "integrity": "sha512-6oNCtyFOrNdqm6GUkFujsCgFlpbsHLnZqq7edeM/+cxAbMyCWvsaCsIMUaz7AiluKLccCGEM8fhOsjaKgBvb7g==", "dev": true, - "engines": { - "node": "*" + "dependencies": { + "@vue/devtools-kit": "^7.2.1" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "node_modules/@vue/devtools-kit": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.2.1.tgz", + "integrity": "sha512-Wak/fin1X0Q8LLIfCAHBrdaaB+R6IdpSXsDByPHbQ3BmkCP0/cIo/oEGp9i0U2+gEqD4L3V9RDjNf1S34DTzQQ==", "dev": true, - "peer": true, - "engines": { - "node": ">=8.0.0" + "dependencies": { + "@vue/devtools-shared": "^7.2.1", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1" + }, + "peerDependencies": { + "vue": "^3.0.0" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/@vue/devtools-shared": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.2.1.tgz", + "integrity": "sha512-PCJF4UknJmOal68+X9XHyVeQ+idv0LFujkTOIW30+GaMJqwFVN9LkQKX4gLqn61KkGMdJTzQ1bt7EJag3TI6AA==", "dev": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "rfdc": "^1.3.1" } }, - "node_modules/get-tsconfig": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", - "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "node_modules/@vue/reactivity": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.27.tgz", + "integrity": "sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==", "dev": true, "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "@vue/shared": "3.4.27" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/@vue/runtime-core": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.27.tgz", + "integrity": "sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@vue/reactivity": "3.4.27", + "@vue/shared": "3.4.27" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@vue/runtime-dom": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz", + "integrity": "sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" + "@vue/runtime-core": "3.4.27", + "@vue/shared": "3.4.27", + "csstype": "^3.1.3" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/@vue/server-renderer": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.27.tgz", + "integrity": "sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==", "dev": true, - "peer": true, - "engines": { - "node": ">=4" + "dependencies": { + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27" + }, + "peerDependencies": { + "vue": "3.4.27" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "node_modules/@vue/shared": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.27.tgz", + "integrity": "sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==", "dev": true }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", "dev": true, "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" }, - "optionalDependencies": { - "uglify-js": "^3.1.4" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.6", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", + "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", "dev": true, + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "node_modules/@vueuse/integrations": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-10.9.0.tgz", + "integrity": "sha512-acK+A01AYdWSvL4BZmCoJAcyHJ6EqhmkQEXbQLwev1MY7NBnS+hcEMx/BzVoR9zKI+UqEPMD9u6PsyAuiTRT4Q==", "dev": true, "dependencies": { - "function-bind": "^1.1.2" + "@vueuse/core": "10.9.0", + "@vueuse/shared": "10.9.0", + "vue-demi": ">=0.14.7" }, - "engines": { - "node": ">= 0.4" + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "*", + "axios": "*", + "change-case": "*", + "drauu": "*", + "focus-trap": "*", + "fuse.js": "*", + "idb-keyval": "*", + "jwt-decode": "*", + "nprogress": "*", + "qrcode": "*", + "sortablejs": "*", + "universal-cookie": "*" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } } }, - "node_modules/hast-util-from-parse5": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", - "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", + "node_modules/@vueuse/integrations/node_modules/@types/web-bluetooth": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", + "dev": true + }, + "node_modules/@vueuse/integrations/node_modules/@vueuse/core": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz", + "integrity": "sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==", "dev": true, "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "hastscript": "^8.0.0", - "property-information": "^6.0.0", - "vfile": "^6.0.0", - "vfile-location": "^5.0.0", - "web-namespaces": "^2.0.0" + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "10.9.0", + "@vueuse/shared": "10.9.0", + "vue-demi": ">=0.14.7" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/hast-util-parse-selector": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", - "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "node_modules/@vueuse/integrations/node_modules/@vueuse/metadata": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.9.0.tgz", + "integrity": "sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==", "dev": true, - "dependencies": { - "@types/hast": "^3.0.0" - }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/hast-util-raw": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.1.tgz", - "integrity": "sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==", + "node_modules/@vueuse/integrations/node_modules/@vueuse/shared": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.9.0.tgz", + "integrity": "sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==", "dev": true, "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-from-parse5": "^8.0.0", - "hast-util-to-parse5": "^8.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "parse5": "^7.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" + "vue-demi": ">=0.14.7" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/hast-util-to-html": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.0.tgz", - "integrity": "sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==", + "node_modules/@vueuse/integrations/node_modules/vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", "dev": true, - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-raw": "^9.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/hast-util-to-parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", - "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", "dev": true, - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", "dev": true, "dependencies": { - "@types/hast": "^3.0.0" + "vue-demi": "*" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/hastscript": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", - "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.6", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", + "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", "dev": true, - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/acorn-walk": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, - "peer": true, "engines": { - "node": ">=10.17.0" + "node": ">=0.4.0" + } + }, + "node_modules/adaptivecards": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/adaptivecards/-/adaptivecards-2.11.1.tgz", + "integrity": "sha512-dyF23HK+lRMEreexJgHz4y9U5B0ZuGk66N8nhwXRnICyYjq8hE4A6n8rLoV/CNY2QAZ0iRjOIR2J8U7M1CKl8Q==", + "dev": true + }, + "node_modules/algoliasearch": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.3.tgz", + "integrity": "sha512-Le/3YgNvjW9zxIQMRhUHuhiUjAlKY/zsdZpfq4dlLqg6mEm0nL6yk+7f2hDOtLpxsgE4jSzDmvHL7nXdBp5feg==", + "dev": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.23.3", + "@algolia/cache-common": "4.23.3", + "@algolia/cache-in-memory": "4.23.3", + "@algolia/client-account": "4.23.3", + "@algolia/client-analytics": "4.23.3", + "@algolia/client-common": "4.23.3", + "@algolia/client-personalization": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/logger-console": "4.23.3", + "@algolia/recommend": "4.23.3", + "@algolia/requester-browser-xhr": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/requester-node-http": "4.23.3", + "@algolia/transporter": "4.23.3" } }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, - "peer": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "*" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "peer": true, - "engines": { - "node": ">=0.8.19" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, - "peer": true + "engines": { + "node": ">=8" + } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/chai": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", "dev": true, "dependencies": { - "binary-extensions": "^2.0.0" + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, "dependencies": { - "hasown": "^2.0.0" + "get-func-name": "^2.0.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "*" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, + "dependencies": { + "ms": "2.1.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, - "peer": true, + "dependencies": { + "type-detect": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, - "peer": true, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/element-plus": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.4.3.tgz", + "integrity": "sha512-b3q26j+lM4SBqiyzw8HybybGnP2pk4MWgrnzzzYW5qKQUgV6EG1Zg7nMCfgCVccI8tNvZoTiUHb2mFaiB9qT8w==", "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.3.1", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.3", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" }, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "vue": "^3.2.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, "engines": { - "node": ">=0.12.0" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", "dev": true, - "peer": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">=8" + "node": ">=12" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "peer": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "node_modules/esbuild/node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", - "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "node_modules/esbuild/node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/istanbul-lib-instrument/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/esbuild/node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], "dev": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/esbuild/node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], "dev": true, - "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/istanbul-lib-instrument/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "peer": true - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "node_modules/esbuild/node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], "dev": true, - "peer": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=12" } }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], "dev": true, - "peer": true, - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "node_modules/esbuild/node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], "dev": true, - "peer": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], "dev": true, - "peer": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], "dev": true, - "peer": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } + "node": ">=12" } }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], "dev": true, - "peer": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "node_modules/esbuild/node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], "dev": true, - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], "dev": true, - "peer": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], "dev": true, - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "node": ">=12" } }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], "dev": true, - "peer": true, - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "node_modules/esbuild/node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, - "peer": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8.6.0" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, - "peer": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, - "peer": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "node_modules/fflate": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.1.tgz", + "integrity": "sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ==", + "dev": true }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, - "peer": true, "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" + "to-regex-range": "^5.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/focus-trap": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", + "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", "dev": true, - "peer": true, "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, + "tabbable": "^6.2.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, - "peer": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "*" } }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "node_modules/get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", "dev": true, - "peer": true, "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "resolve-pkg-maps": "^1.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, - "peer": true, "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-snapshot/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "peer": true, "dependencies": { - "yallist": "^4.0.0" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10" + "node": ">= 6" } }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, - "peer": true, "dependencies": { - "lru-cache": "^6.0.0" + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" }, "bin": { - "semver": "bin/semver.js" + "handlebars": "bin/handlebars" }, "engines": { - "node": ">=10" + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/jest-snapshot/node_modules/yallist": { + "node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "peer": true - }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, - "peer": true, "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "peer": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "peer": true, "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" + "is-extglob": "^2.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "peer": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.12.0" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, - "peer": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=10" } }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, - "peer": true, - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "peer": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, - "bin": { - "json5": "lib/cli.js" + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/jsonc-parser": { @@ -4570,33 +2564,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "peer": true - }, "node_modules/local-pkg": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", @@ -4609,19 +2576,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "peer": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -4645,12 +2599,6 @@ "lodash-es": "*" } }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, "node_modules/loupe": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", @@ -4660,16 +2608,6 @@ "get-func-name": "^2.0.1" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "peer": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", @@ -4677,15 +2615,12 @@ "dev": true }, "node_modules/magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" } }, "node_modules/make-dir": { @@ -4736,170 +2671,38 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "peer": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, "node_modules/mark.js": { "version": "8.11.1", "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", - "dev": true - }, - "node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.0.2.tgz", - "integrity": "sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/memoize-one": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", - "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "peer": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromark-util-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz", - "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", - "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] + "dev": true }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", - "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" } }, - "node_modules/micromark-util-symbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", - "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "dev": true }, - "node_modules/micromark-util-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", - "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] + "engines": { + "node": ">= 8" + } }, "node_modules/micromatch": { "version": "4.0.5", @@ -4914,16 +2717,6 @@ "node": ">=8.6" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4951,17 +2744,11 @@ "integrity": "sha512-ihFnidEeU8iXzcVHy74dhkxh/dn8Dc08ERl0xwoMMGqp4+LvRSCgicb+zGqWthVokQKvCSxITlh3P08OzdTYCQ==", "dev": true }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true }, "node_modules/mlly": { "version": "1.4.2", @@ -5014,61 +2801,18 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "peer": true - }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true, - "peer": true - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true, - "peer": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/normalize-wheel-es": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==", "dev": true }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "peer": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5078,118 +2822,6 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "peer": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "peer": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "peer": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "peer": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -5199,22 +2831,6 @@ "node": ">=0.10.0" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, "node_modules/pathe": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz", @@ -5230,6 +2846,12 @@ "node": "*" } }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -5248,29 +2870,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "peer": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/pkg-types": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", @@ -5283,9 +2882,9 @@ } }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "dev": true, "funding": [ { @@ -5304,16 +2903,16 @@ "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" } }, "node_modules/preact": { - "version": "10.19.2", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.2.tgz", - "integrity": "sha512-UA9DX/OJwv6YwP9Vn7Ti/vF80XL+YA5H2l7BpCtUr3ya8LWHFzpiO5R+N7dN16ujpIxhekRFuOOF82bXX7K/lg==", + "version": "10.22.0", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.22.0.tgz", + "integrity": "sha512-RRurnSjJPj4rp5K6XoP45Ui33ncb7e4H7WiOHVpjbkvqvA3U+N8Z6Qbo0AE6leGYBV66n8EhEaFixvIu3SkxFw==", "dev": true, "funding": { "type": "opencollective", @@ -5346,47 +2945,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "peer": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/property-information": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.4.0.tgz", - "integrity": "sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "peer": true - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5413,68 +2971,6 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "peer": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -5484,16 +2980,6 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - } - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -5504,17 +2990,11 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true }, "node_modules/rollup": { "version": "3.29.4", @@ -5550,50 +3030,17 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/search-insights": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.11.0.tgz", - "integrity": "sha512-Uin2J8Bpm3xaZi9Y8QibSys6uJOFZ+REMrf42v20AA3FUDUrshKkMEP6liJbMAHCm71wO6ls4mwAf7a3gFVxLw==", - "dev": true, - "peer": true - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "peer": true, + ], "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" + "queue-microtask": "^1.2.2" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/search-insights": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.13.0.tgz", + "integrity": "sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw==", "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } + "peer": true }, "node_modules/shiki": { "version": "0.10.1", @@ -5606,37 +3053,12 @@ "vscode-textmate": "5.2.0" } }, - "node_modules/shikiji": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.7.6.tgz", - "integrity": "sha512-KzEtvSGQtBvfwVIB70kOmIfl/5rz1LC8j+tvlHXsJKAIdONNQvG1at7ivUUq3xUctqgO6fsO3AGomUSh0F+wsQ==", - "dev": true, - "dependencies": { - "hast-util-to-html": "^9.0.0" - } - }, - "node_modules/shikiji-transformers": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/shikiji-transformers/-/shikiji-transformers-0.7.6.tgz", - "integrity": "sha512-yTp+7JMD/aXbV9ndn14eo9IK/UNt8iDsLNyqlOmCtcldlkqWE9T2YKAlOHOTVaeDfYWUWZa2EgSXb/CBfepBrw==", - "dev": true, - "dependencies": { - "shikiji": "0.7.6" - } - }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "peer": true - }, "node_modules/sirv": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", @@ -5651,22 +3073,6 @@ "node": ">= 10" } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "peer": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5677,51 +3083,21 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "peer": true - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, "node_modules/stackback": { @@ -5736,95 +3112,6 @@ "integrity": "sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==", "dev": true }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "peer": true, - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/stringify-entities": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.3.tgz", - "integrity": "sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==", - "dev": true, - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-literal": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", @@ -5849,300 +3136,69 @@ "node": ">=8" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/tabbable": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", - "dev": true - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tinybench": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz", - "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==", - "dev": true - }, - "node_modules/tinypool": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.5.0.tgz", - "integrity": "sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz", - "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true, - "peer": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", - "dev": true, - "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "^7.5.3", - "yargs-parser": "^21.0.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "node_modules/ts-jest/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-jest/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-jest/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "dev": true }, - "node_modules/ts-node-dev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", - "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "dependencies": { - "chokidar": "^3.5.1", - "dynamic-dedupe": "^0.3.0", - "minimist": "^1.2.6", - "mkdirp": "^1.0.4", - "resolve": "^1.0.0", - "rimraf": "^2.6.1", - "source-map-support": "^0.5.12", - "tree-kill": "^1.2.2", - "ts-node": "^10.4.0", - "tsconfig": "^7.0.0" - }, - "bin": { - "ts-node-dev": "lib/bin.js", - "tsnd": "lib/bin.js" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=0.8.0" - }, - "peerDependencies": { - "node-notifier": "*", - "typescript": "*" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=8" } }, - "node_modules/tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "node_modules/tinybench": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz", + "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.5.0.tgz", + "integrity": "sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==", "dev": true, - "dependencies": { - "@types/strip-bom": "^3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/tsconfig/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/tinyspy": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz", + "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==", "dev": true, "engines": { - "node": ">=4" + "node": ">=14.0.0" } }, - "node_modules/tsconfig/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, "node_modules/tsx": { @@ -6181,19 +3237,6 @@ "node": ">=4" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typedoc": { "version": "0.22.18", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.18.tgz", @@ -6332,74 +3375,6 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, - "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -6409,43 +3384,6 @@ "node": ">= 10.0.0" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, "node_modules/v8-to-istanbul": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", @@ -6460,49 +3398,6 @@ "node": ">=10.12.0" } }, - "node_modules/vfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", - "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-location": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.2.tgz", - "integrity": "sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/vite": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", @@ -6582,33 +3477,34 @@ } }, "node_modules/vitepress": { - "version": "1.0.0-rc.31", - "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.0.0-rc.31.tgz", - "integrity": "sha512-ikH9pIjOOAbyoYAGBVfTz8TzuXp+UoWaIRMU4bw/oiTg8R65SbAaGKY84xx6TuL+f4VqUJ8lhzW82YyxSLvstA==", - "dev": true, - "dependencies": { - "@docsearch/css": "^3.5.2", - "@docsearch/js": "^3.5.2", - "@types/markdown-it": "^13.0.7", - "@vitejs/plugin-vue": "^4.5.0", - "@vue/devtools-api": "^6.5.1", - "@vueuse/core": "^10.6.1", - "@vueuse/integrations": "^10.6.1", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.2.0.tgz", + "integrity": "sha512-m/4PAQVyPBvKHV7sFKwcmNmrsoSxdjnw/Eg40YyuBSaBHhrro9ubnfWk5GT0xGfE98LqjZkHCWKNJlR6G/7Ayg==", + "dev": true, + "dependencies": { + "@docsearch/css": "^3.6.0", + "@docsearch/js": "^3.6.0", + "@shikijs/core": "^1.5.2", + "@shikijs/transformers": "^1.5.2", + "@types/markdown-it": "^14.1.1", + "@vitejs/plugin-vue": "^5.0.4", + "@vue/devtools-api": "^7.2.0", + "@vue/shared": "^3.4.27", + "@vueuse/core": "^10.9.0", + "@vueuse/integrations": "^10.9.0", "focus-trap": "^7.5.4", "mark.js": "8.11.1", "minisearch": "^6.3.0", - "mrmime": "^1.0.1", - "shikiji": "^0.7.4", - "shikiji-transformers": "^0.7.4", - "vite": "^5.0.2", - "vue": "^3.3.8" + "shiki": "^1.5.2", + "vite": "^5.2.11", + "vue": "^3.4.27" }, "bin": { "vitepress": "bin/vitepress.js" }, "peerDependencies": { - "markdown-it-mathjax3": "^4.3.2", - "postcss": "^8.4.31" + "markdown-it-mathjax3": "^4", + "postcss": "^8" }, "peerDependenciesMeta": { "markdown-it-mathjax3": { @@ -6620,9 +3516,9 @@ } }, "node_modules/vitepress/node_modules/@esbuild/darwin-arm64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.8.tgz", - "integrity": "sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], @@ -6641,25 +3537,38 @@ "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", "dev": true }, + "node_modules/vitepress/node_modules/@vitejs/plugin-vue": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz", + "integrity": "sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, "node_modules/vitepress/node_modules/@vueuse/core": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.6.1.tgz", - "integrity": "sha512-Pc26IJbqgC9VG1u6VY/xrXXfxD33hnvxBnKrLlA2LJlyHII+BSrRoTPJgGYq7qZOu61itITFUnm6QbacwZ4H8Q==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz", + "integrity": "sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==", "dev": true, "dependencies": { "@types/web-bluetooth": "^0.0.20", - "@vueuse/metadata": "10.6.1", - "@vueuse/shared": "10.6.1", - "vue-demi": ">=0.14.6" + "@vueuse/metadata": "10.9.0", + "@vueuse/shared": "10.9.0", + "vue-demi": ">=0.14.7" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/vitepress/node_modules/@vueuse/core/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", "dev": true, "hasInstallScript": true, "bin": { @@ -6683,30 +3592,30 @@ } }, "node_modules/vitepress/node_modules/@vueuse/metadata": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.6.1.tgz", - "integrity": "sha512-qhdwPI65Bgcj23e5lpGfQsxcy0bMjCAsUGoXkJ7DsoeDUdasbZ2DBa4dinFCOER3lF4gwUv+UD2AlA11zdzMFw==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.9.0.tgz", + "integrity": "sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==", "dev": true, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/vitepress/node_modules/@vueuse/shared": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.6.1.tgz", - "integrity": "sha512-TECVDTIedFlL0NUfHWncf3zF9Gc4VfdxfQc8JFwoVZQmxpONhLxFrlm0eHQeidHj4rdTPL3KXJa0TZCk1wnc5Q==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.9.0.tgz", + "integrity": "sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==", "dev": true, "dependencies": { - "vue-demi": ">=0.14.6" + "vue-demi": ">=0.14.7" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/vitepress/node_modules/@vueuse/shared/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", "dev": true, "hasInstallScript": true, "bin": { @@ -6730,9 +3639,9 @@ } }, "node_modules/vitepress/node_modules/esbuild": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.8.tgz", - "integrity": "sha512-l7iffQpT2OrZfH2rXIp7/FkmaeZM0vxbxN9KfiCwGYuZqzMg/JdvX26R31Zxn/Pxvsrg3Y9N6XTcnknqDyyv4w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", "dev": true, "hasInstallScript": true, "bin": { @@ -6742,35 +3651,39 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.19.8", - "@esbuild/android-arm64": "0.19.8", - "@esbuild/android-x64": "0.19.8", - "@esbuild/darwin-arm64": "0.19.8", - "@esbuild/darwin-x64": "0.19.8", - "@esbuild/freebsd-arm64": "0.19.8", - "@esbuild/freebsd-x64": "0.19.8", - "@esbuild/linux-arm": "0.19.8", - "@esbuild/linux-arm64": "0.19.8", - "@esbuild/linux-ia32": "0.19.8", - "@esbuild/linux-loong64": "0.19.8", - "@esbuild/linux-mips64el": "0.19.8", - "@esbuild/linux-ppc64": "0.19.8", - "@esbuild/linux-riscv64": "0.19.8", - "@esbuild/linux-s390x": "0.19.8", - "@esbuild/linux-x64": "0.19.8", - "@esbuild/netbsd-x64": "0.19.8", - "@esbuild/openbsd-x64": "0.19.8", - "@esbuild/sunos-x64": "0.19.8", - "@esbuild/win32-arm64": "0.19.8", - "@esbuild/win32-ia32": "0.19.8", - "@esbuild/win32-x64": "0.19.8" + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, "node_modules/vitepress/node_modules/rollup": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.6.1.tgz", - "integrity": "sha512-jZHaZotEHQaHLgKr8JnQiDT1rmatjgKlMekyksz+yk9jt/8z9quNjnKNRoaM0wd9DC2QKXjmWWuDYtM3jfF8pQ==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz", + "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==", "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, "bin": { "rollup": "dist/bin/rollup" }, @@ -6779,30 +3692,43 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.6.1", - "@rollup/rollup-android-arm64": "4.6.1", - "@rollup/rollup-darwin-arm64": "4.6.1", - "@rollup/rollup-darwin-x64": "4.6.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.6.1", - "@rollup/rollup-linux-arm64-gnu": "4.6.1", - "@rollup/rollup-linux-arm64-musl": "4.6.1", - "@rollup/rollup-linux-x64-gnu": "4.6.1", - "@rollup/rollup-linux-x64-musl": "4.6.1", - "@rollup/rollup-win32-arm64-msvc": "4.6.1", - "@rollup/rollup-win32-ia32-msvc": "4.6.1", - "@rollup/rollup-win32-x64-msvc": "4.6.1", + "@rollup/rollup-android-arm-eabi": "4.17.2", + "@rollup/rollup-android-arm64": "4.17.2", + "@rollup/rollup-darwin-arm64": "4.17.2", + "@rollup/rollup-darwin-x64": "4.17.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.17.2", + "@rollup/rollup-linux-arm-musleabihf": "4.17.2", + "@rollup/rollup-linux-arm64-gnu": "4.17.2", + "@rollup/rollup-linux-arm64-musl": "4.17.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2", + "@rollup/rollup-linux-riscv64-gnu": "4.17.2", + "@rollup/rollup-linux-s390x-gnu": "4.17.2", + "@rollup/rollup-linux-x64-gnu": "4.17.2", + "@rollup/rollup-linux-x64-musl": "4.17.2", + "@rollup/rollup-win32-arm64-msvc": "4.17.2", + "@rollup/rollup-win32-ia32-msvc": "4.17.2", + "@rollup/rollup-win32-x64-msvc": "4.17.2", "fsevents": "~2.3.2" } }, + "node_modules/vitepress/node_modules/shiki": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.6.0.tgz", + "integrity": "sha512-P31ROeXcVgW/k3Z+vUUErcxoTah7ZRaimctOpzGuqAntqnnSmx1HOsvnbAB8Z2qfXPRhw61yptAzCsuKOhTHwQ==", + "dev": true, + "dependencies": { + "@shikijs/core": "1.6.0" + } + }, "node_modules/vitepress/node_modules/vite": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.4.tgz", - "integrity": "sha512-RzAr8LSvM8lmhB4tQ5OPcBhpjOZRZjuxv9zO5UcxeoY2bd3kP3Ticd40Qma9/BqZ8JS96Ll/jeBX9u+LJZrhVg==", + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz", + "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==", "dev": true, "dependencies": { - "esbuild": "^0.19.3", - "postcss": "^8.4.31", - "rollup": "^4.2.0" + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" }, "bin": { "vite": "bin/vite.js" @@ -6939,16 +3865,16 @@ "dev": true }, "node_modules/vue": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.9.tgz", - "integrity": "sha512-sy5sLCTR8m6tvUk1/ijri3Yqzgpdsmxgj6n6yl7GXXCXqVbmW2RCXe9atE4cEI6Iv7L89v5f35fZRRr5dChP9w==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", + "integrity": "sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==", "dev": true, "dependencies": { - "@vue/compiler-dom": "3.3.9", - "@vue/compiler-sfc": "3.3.9", - "@vue/runtime-dom": "3.3.9", - "@vue/server-renderer": "3.3.9", - "@vue/shared": "3.3.9" + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-sfc": "3.4.27", + "@vue/runtime-dom": "3.4.27", + "@vue/server-renderer": "3.4.27", + "@vue/shared": "3.4.27" }, "peerDependencies": { "typescript": "*" @@ -6959,42 +3885,6 @@ } } }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "peer": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/web-namespaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "peer": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/why-is-node-running": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", @@ -7017,129 +3907,11 @@ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "peer": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "peer": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "peer": true - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "peer": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } } } } diff --git a/package.json b/package.json index 79e75f9..abf3ea1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "speedybot", - "version": "2.0.4", + "version": "2.0.5", "main": "dist/cjs/src/index.js", "module": "dist/mjs/src/index.js", "types": "dist/mjs/src/index.d.ts", @@ -8,6 +8,10 @@ "bin": { "speedybot": "./bin/cli.js" }, + "files": [ + "dist/cjs", + "dist/mjs" + ], "exports": { ".": { "import": "./dist/mjs/src/index.js", @@ -15,6 +19,7 @@ } }, "devDependencies": { + "@rollup/rollup-linux-x64-gnu": "latest", "@types/node": "^18.8.4", "@vitest/coverage-v8": "^0.32.2", "@vitest/ui": "^0.32.2", @@ -27,9 +32,8 @@ "typedoc-theme-hierarchy": "1.2.1", "typescript": "^4.7.2", "vite": "^4.3.9", - "vitepress": "^1.0.0-rc.31", - "vitest": "^0.32.2", - "@rollup/rollup-linux-x64-gnu": "latest" + "vitepress": "^1.2.0", + "vitest": "^0.32.2" }, "scripts": { "dist:example": "tee examples/worker/settings/bot.ts examples/i18n/settings/bot.ts < examples/bot.sample.ts >/dev/null", @@ -61,7 +65,7 @@ }, "keywords": [ "bot", - "scaffold", + "speedy", "continerless", "speedybot", "serverless" diff --git a/src/speedybot.ts b/src/speedybot.ts index 7ba6c99..c331ee7 100644 --- a/src/speedybot.ts +++ b/src/speedybot.ts @@ -1,5 +1,6 @@ import { CONSTANTS, mainRequester } from "./index"; import { + Chunk, CoreMakerequest, Destination, ENVELOPES, @@ -8,6 +9,7 @@ import { MessageResponse, Message_Details, File_Details, + RoomConfig, Room_Details, SelfData, SpeedyFile, @@ -923,6 +925,12 @@ ${type === "json" ? JSON.stringify(data, null, 2) : data} return list; } + /** + * Create firehose and attachmentActions webhooks + * @param url + * @param secret + * @returns + */ Setup(url: string, secret: string) { return Promise.all([ this.createFirehose(url, secret), @@ -1307,6 +1315,11 @@ ${type === "json" ? JSON.stringify(data, null, 2) : data} }; } + /** + * @hidden + * + * Utility to traverse Link headers for pagination, built-in back-off + */ public async peekFile(url: string): Promise> { const res = await this.makeRequest( url, @@ -1375,6 +1388,10 @@ ${type === "json" ? JSON.stringify(data, null, 2) : data} return res; } + /** + * + * Utility to traverse Link headers for pagination, built-in back-off + */ fuzzyMatch(candidate: string, options: string[]): boolean { const lowerCaseCandidate = candidate.toLowerCase(); return options.some((option) => @@ -1414,4 +1431,96 @@ ${type === "json" ? JSON.stringify(data, null, 2) : data} ) { return this.card().addHeader(appName, { iconURL: logoUrl, ...config }); } + + /** + * @hidden + * + * Utility to traverse Link headers for pagination, built-in back-off + */ + private async fetchData( + url: string, + retries: number = 3, + onChunk?: Chunk + ): Promise { + const delay = (ms: number) => + new Promise((resolve) => setTimeout(resolve, ms)); + try { + const response = await fetch(url, { + method: "GET", + headers: { + Authorization: `Bearer ${this._token}`, + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + if (response.status === 429 && retries > 0) { + const retryAfter = + parseInt(response.headers.get("Retry-After") || "1", 10) * 1000; + await delay(retryAfter); + return await this.fetchData(url, retries - 1); + } else { + const text = await response.text(); + throw new Error( + `Error fetching messages: ${response.statusText}, ${text}` + ); + } + } + + const { items } = await response.json(); + const data = items as T[]; + const linkHeader = response.headers.get("Link"); + const hasNext = linkHeader ? linkHeader.includes(`rel="next"`) : false; + const nextURL = hasNext + ? linkHeader!.split(";")[0].replace("<", "").replace(">", "") + : null; + + if (onChunk) { + await onChunk(data); + } + if (hasNext && nextURL) { + const nextPageData = await this.fetchData(nextURL, retries); + return data.concat(nextPageData); + } + + return data; + } catch (error) { + throw new Error(`Error fetching data: ${error}`); + } + } + + /** + * @hidden + */ + private buildQueryURL( + target: string, + options?: Record + ): string { + const queryParams: string[] = []; + + if (options) { + Object.entries(options).forEach(([key, value]) => { + if (value !== undefined && value !== null) { + queryParams.push( + `${encodeURIComponent(key)}=${encodeURIComponent(value)}` + ); + } + }); + } + + const queryString = + queryParams.length > 0 ? `?${queryParams.join("&")}` : ""; + return `${target}${queryString}`; + } + + /** + * @hidden + */ + public async getAllRooms( + options?: Partial + ): Promise { + const url = this.buildQueryURL(this.API.rooms, options); + const collection = await this.fetchData(url); + return collection as Room_Details[]; + } } diff --git a/src/types.ts b/src/types.ts index c325d14..b9e3ef1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -240,16 +240,6 @@ export type Submit_Details = { created: Date | string; }; -export type AA_Details = { - id: string; - type: string; - messageId: string; - inputs: any; - personId: string; - roomId: string; - created: Date | string; -}; - // Get Self data from token export type SelfData = { id: string; @@ -417,3 +407,9 @@ export type Room_Details = { isPublic: boolean; isReadOnly: boolean; }; + +export type Chunk = (messageChunk: T[]) => void; +export type RoomConfig = { + type: "group" | "direct"; + sortBy: "id" | "lastactivity" | "created"; +};