+
-
-
-
+
+
+
-
+
diff --git a/frontend/src/views/admin/status/StatusView.vue b/frontend/src/views/admin/status/StatusView.vue
new file mode 100644
index 00000000..3a911e9d
--- /dev/null
+++ b/frontend/src/views/admin/status/StatusView.vue
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Add custom conversation statuses to extend default workflow.
+
+
+
+
+
diff --git a/frontend/src/views/admin/tags/TagsView.vue b/frontend/src/views/admin/tags/TagsView.vue
new file mode 100644
index 00000000..c70308fd
--- /dev/null
+++ b/frontend/src/views/admin/tags/TagsView.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create and organize tags to categorize conversations.
+
+
+
+
+
diff --git a/frontend/src/components/admin/team/teams/AddTeamForm.vue b/frontend/src/views/admin/teams/CreateTeamForm.vue
similarity index 88%
rename from frontend/src/components/admin/team/teams/AddTeamForm.vue
rename to frontend/src/views/admin/teams/CreateTeamForm.vue
index 17787dab..874e993f 100644
--- a/frontend/src/components/admin/team/teams/AddTeamForm.vue
+++ b/frontend/src/views/admin/teams/CreateTeamForm.vue
@@ -7,7 +7,7 @@
diff --git a/frontend/src/views/admin/teams/TeamList.vue b/frontend/src/views/admin/teams/TeamList.vue
new file mode 100644
index 00000000..34ffd140
--- /dev/null
+++ b/frontend/src/views/admin/teams/TeamList.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
+
diff --git a/frontend/src/views/admin/teams/Teams.vue b/frontend/src/views/admin/teams/Teams.vue
new file mode 100644
index 00000000..b1b3b7ce
--- /dev/null
+++ b/frontend/src/views/admin/teams/Teams.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ Configure team settings including working hours and SLA policies.
+ Manage agent auto-assignment rules for team efficiency.
+
+
+
+
+
diff --git a/frontend/src/components/admin/templates/AddEditTemplate.vue b/frontend/src/views/admin/templates/CreateEditTemplate.vue
similarity index 73%
rename from frontend/src/components/admin/templates/AddEditTemplate.vue
rename to frontend/src/views/admin/templates/CreateEditTemplate.vue
index 9bccc59c..4822d622 100644
--- a/frontend/src/components/admin/templates/AddEditTemplate.vue
+++ b/frontend/src/views/admin/templates/CreateEditTemplate.vue
@@ -3,15 +3,19 @@
-
+
diff --git a/frontend/src/views/admin/templates/Templates.vue b/frontend/src/views/admin/templates/Templates.vue
new file mode 100644
index 00000000..89da6c71
--- /dev/null
+++ b/frontend/src/views/admin/templates/Templates.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Outgoing email templates
+ Email notification templates
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Design templates for customer communications and responses.
+ Configure internal team notification templates.
+
+
+
+
+
diff --git a/frontend/src/components/admin/team/users/AddUserForm.vue b/frontend/src/views/admin/users/CreateUser.vue
similarity index 71%
rename from frontend/src/components/admin/team/users/AddUserForm.vue
rename to frontend/src/views/admin/users/CreateUser.vue
index 056af836..f8a6ddc7 100644
--- a/frontend/src/components/admin/team/users/AddUserForm.vue
+++ b/frontend/src/views/admin/users/CreateUser.vue
@@ -7,18 +7,18 @@
diff --git a/frontend/src/views/admin/users/Users.vue b/frontend/src/views/admin/users/Users.vue
new file mode 100644
index 00000000..1b3bf04d
--- /dev/null
+++ b/frontend/src/views/admin/users/Users.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+ Manage your support agents, their roles and permissions and teams.
+
+
+
+
+
diff --git a/frontend/src/views/conversation/ConversationDetailView.vue b/frontend/src/views/conversation/ConversationDetailView.vue
new file mode 100644
index 00000000..3b036419
--- /dev/null
+++ b/frontend/src/views/conversation/ConversationDetailView.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
diff --git a/frontend/src/views/inbox/InboxView.vue b/frontend/src/views/inbox/InboxView.vue
new file mode 100644
index 00000000..b7b844b6
--- /dev/null
+++ b/frontend/src/views/inbox/InboxView.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
+
diff --git a/frontend/src/views/login/UserLoginView.vue b/frontend/src/views/login/UserLoginView.vue
new file mode 100644
index 00000000..76f5df8d
--- /dev/null
+++ b/frontend/src/views/login/UserLoginView.vue
@@ -0,0 +1,234 @@
+
+
+
+
+
+
+
+
Libredesk
+
Sign in to your account
+
+
+
+
+
+
+
+
+
+
+ Or continue with
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/outerapp/ResetPasswordView.vue b/frontend/src/views/outerapp/ResetPasswordView.vue
new file mode 100644
index 00000000..5dccb669
--- /dev/null
+++ b/frontend/src/views/outerapp/ResetPasswordView.vue
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
Reset Password
+
+ Enter your email to receive a password reset link.
+
+
+
+
+
+
+
+
+ Back to Login
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/outerapp/SetPasswordView.vue b/frontend/src/views/outerapp/SetPasswordView.vue
new file mode 100644
index 00000000..e7b970ab
--- /dev/null
+++ b/frontend/src/views/outerapp/SetPasswordView.vue
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
Set New Password
+
Please enter your new password twice to confirm.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/reports/DashboardView.vue b/frontend/src/views/reports/DashboardView.vue
new file mode 100644
index 00000000..775a481c
--- /dev/null
+++ b/frontend/src/views/reports/DashboardView.vue
@@ -0,0 +1,133 @@
+
+
+
+
+
+ Last updated: {{ new Date(lastUpdate).toLocaleTimeString() }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/search/SearchView.vue b/frontend/src/views/search/SearchView.vue
new file mode 100644
index 00000000..b2670381
--- /dev/null
+++ b/frontend/src/views/search/SearchView.vue
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
{{ error }}
+
+
+
+
+
+ No results found for "{{ searchQuery }}". Try a different search term.
+
+
+
+
+ Please enter at least {{ MIN_SEARCH_LENGTH }} characters to search.
+
+
+
Search conversations
+
+ Search by reference number, messages, or any keywords related to your conversations.
+
+
+
+
+
+
+
+
diff --git a/frontend/src/websocket.js b/frontend/src/websocket.js
index 57563798..0f1d6904 100644
--- a/frontend/src/websocket.js
+++ b/frontend/src/websocket.js
@@ -1,144 +1,170 @@
-import { useConversationStore } from './stores/conversation';
-import { CONVERSATION_WS_ACTIONS } from './constants/conversation';
+import { useConversationStore } from './stores/conversation'
+import { WS_EVENT } from './constants/websocket'
-let socket;
-let reconnectInterval = 1000;
-let maxReconnectInterval = 30000;
-let reconnectTimeout;
-let isReconnecting = false;
-let manualClose = false;
-let convStore;
-
-function initializeWebSocket () {
- socket = new WebSocket('/ws');
- socket.addEventListener('open', handleOpen)
- socket.addEventListener('message', handleMessage)
- socket.addEventListener('error', handleError)
- socket.addEventListener('close', handleClose)
-}
-
-function handleOpen () {
- console.log('WebSocket connection established')
- reconnectInterval = 1000;
- if (reconnectTimeout) {
- clearTimeout(reconnectTimeout)
- reconnectTimeout = null;
+export class WebSocketClient {
+ constructor() {
+ this.socket = null
+ this.reconnectInterval = 1000
+ this.maxReconnectInterval = 30000
+ this.reconnectAttempts = 0
+ this.maxReconnectAttempts = 50
+ this.isReconnecting = false
+ this.manualClose = false
+ this.pingInterval = null
+ this.lastPong = Date.now()
+ this.convStore = useConversationStore()
}
-}
-function handleMessage (event) {
- try {
- if (event.data) {
- const data = JSON.parse(event.data)
- switch (data.type) {
- case 'new_message':
- convStore.updateConversationLastMessage(data.data)
- convStore.updateConversationMessageList(data.data)
- break;
- case 'message_prop_update':
- convStore.updateMessageProp(data.data)
- break;
- case 'new_conversation':
- convStore.addNewConversation(data.data)
- break;
- case 'conversation_prop_update':
- convStore.updateConversationProp(data.data)
- break;
- default:
- console.warn(`Unknown websocket event type: ${data.type}`)
+ init () {
+ this.connect()
+ this.setupNetworkListeners()
+ }
+
+ connect () {
+ if (this.isReconnecting || this.manualClose) return
+
+ try {
+ this.socket = new WebSocket('/ws')
+ this.socket.addEventListener('open', this.handleOpen.bind(this))
+ this.socket.addEventListener('message', this.handleMessage.bind(this))
+ this.socket.addEventListener('error', this.handleError.bind(this))
+ this.socket.addEventListener('close', this.handleClose.bind(this))
+ } catch (error) {
+ console.error('WebSocket connection error:', error)
+ this.reconnect()
+ }
+ }
+
+ handleOpen () {
+ console.log('WebSocket connected')
+ this.reconnectInterval = 1000
+ this.reconnectAttempts = 0
+ this.isReconnecting = false
+ this.lastPong = Date.now()
+ this.setupPing()
+ }
+
+ handleMessage (event) {
+ try {
+ if (!event.data) return
+
+ if (event.data === 'pong') {
+ this.lastPong = Date.now()
+ return
}
+
+ const data = JSON.parse(event.data)
+ const handlers = {
+ [WS_EVENT.NEW_MESSAGE]: () => {
+ this.convStore.updateConversationList(data.data)
+ this.convStore.updateConversationMessage(data.data)
+ },
+ [WS_EVENT.MESSAGE_PROP_UPDATE]: () => this.convStore.updateMessageProp(data.data),
+ [WS_EVENT.CONVERSATION_PROP_UPDATE]: () => this.convStore.updateConversationProp(data.data)
+ }
+
+ const handler = handlers[data.type]
+ if (handler) {
+ handler()
+ } else {
+ console.warn(`Unknown websocket event: ${data.type}`)
+ }
+ } catch (error) {
+ console.error('Message handling error:', error)
+ }
+ }
+
+ handleError (event) {
+ console.error('WebSocket error:', event)
+ this.reconnect()
+ }
+
+ handleClose () {
+ this.clearPing()
+ if (!this.manualClose) {
+ this.reconnect()
+ }
+ }
+
+ reconnect () {
+ if (this.isReconnecting || this.reconnectAttempts >= this.maxReconnectAttempts) return
+
+ this.isReconnecting = true
+ this.reconnectAttempts++
+
+ setTimeout(() => {
+ this.isReconnecting = false
+ this.connect()
+ this.reconnectInterval = Math.min(this.reconnectInterval * 1.5, this.maxReconnectInterval)
+ }, this.reconnectInterval)
+ }
+
+ setupNetworkListeners () {
+ window.addEventListener('online', () => {
+ if (this.socket?.readyState !== WebSocket.OPEN) {
+ this.reconnectInterval = 1000
+ this.reconnect()
+ }
+ })
+
+ window.addEventListener('focus', () => {
+ if (this.socket?.readyState !== WebSocket.OPEN) {
+ this.reconnect()
+ }
+ })
+ }
+
+ setupPing () {
+ this.clearPing()
+ this.pingInterval = setInterval(() => {
+ if (this.socket?.readyState === WebSocket.OPEN) {
+ try {
+ this.socket.send('ping')
+ if (Date.now() - this.lastPong > 10000) {
+ console.warn('No pong received in 10 seconds, closing connection')
+ this.socket.close()
+ }
+ } catch (e) {
+ console.error('Ping error:', e)
+ this.reconnect()
+ }
+ }
+ }, 5000)
+ }
+
+ clearPing () {
+ if (this.pingInterval) {
+ clearInterval(this.pingInterval)
+ this.pingInterval = null
+ }
+ }
+
+ send (message) {
+ if (this.socket?.readyState === WebSocket.OPEN) {
+ this.socket.send(JSON.stringify(message))
+ } else {
+ console.warn('WebSocket is not open. Message not sent:', message)
+ }
+ }
+
+ close () {
+ this.manualClose = true
+ this.clearPing()
+ if (this.socket) {
+ this.socket.close()
}
- } catch (error) {
- console.error('Error handling WebSocket message:', error)
}
}
-function handleError (event) {
- console.error('WebSocket error observed:', event)
-}
-
-function handleClose () {
- if (!manualClose) {
- reconnect()
- }
-}
-
-function reconnect () {
- if (isReconnecting) return;
- isReconnecting = true;
- reconnectTimeout = setTimeout(() => {
- initializeWebSocket()
- reconnectInterval = Math.min(reconnectInterval * 2, maxReconnectInterval)
- isReconnecting = false;
- }, reconnectInterval)
-}
-
-function setupNetworkListeners () {
- window.addEventListener('online', () => {
- if (!isReconnecting && socket.readyState !== WebSocket.OPEN) {
- reconnectInterval = 1000;
- reconnect()
- }
- })
-}
+let wsClient
export function initWS () {
- convStore = useConversationStore()
- initializeWebSocket()
- setupNetworkListeners()
-}
-
-function waitForWebSocketOpen (callback) {
- if (socket) {
- if (socket.readyState === WebSocket.OPEN) {
- callback()
- } else {
- socket.addEventListener('open', function handler () {
- socket.removeEventListener('open', handler)
- callback()
- })
- }
+ if (!wsClient) {
+ wsClient = new WebSocketClient()
+ wsClient.init()
}
+ return wsClient
}
-export function sendMessage (message) {
- waitForWebSocketOpen(() => {
- socket.send(JSON.stringify(message))
- })
-}
-
-export function subscribeConversationsList (type) {
- const message = {
- action: CONVERSATION_WS_ACTIONS.SUB_LIST,
- type: type,
- }
- waitForWebSocketOpen(() => {
- socket.send(JSON.stringify(message))
- })
-}
-
-export function setCurrentConversation (uuid) {
- const message = {
- action: CONVERSATION_WS_ACTIONS.SET_CURRENT,
- uuid: uuid,
- }
- waitForWebSocketOpen(() => {
- socket.send(JSON.stringify(message))
- })
-}
-
-export function unsetCurrentConversation () {
- const message = {
- action: CONVERSATION_WS_ACTIONS.UNSET_CURRENT
- }
- waitForWebSocketOpen(() => {
- socket.send(JSON.stringify(message))
- })
-}
-
-export function closeWebSocket () {
- manualClose = true;
- if (socket) {
- socket.close()
- }
-}
\ No newline at end of file
+export const sendMessage = message => wsClient?.send(message)
+export const closeWebSocket = () => wsClient?.close()
\ No newline at end of file
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
index ca273b4a..76a0dcfc 100644
--- a/frontend/tailwind.config.js
+++ b/frontend/tailwind.config.js
@@ -2,6 +2,7 @@ const animate = require("tailwindcss-animate")
/** @type {import('tailwindcss').Config} */
module.exports = {
+ mode: 'jit',
darkMode: ["class"],
safelist: ["dark"],
prefix: "",
@@ -22,8 +23,16 @@ module.exports = {
},
},
extend: {
+ height: {
+ screen: '100dvh',
+ },
+ minHeight: {
+ screen: '100dvh',
+ },
fontFamily: {
+ jakarta: ['Plus Jakarta Sans', 'Helvetica Neue', 'sans-serif'],
inter: ['Inter', 'Helvetica Neue', 'sans-serif'],
+ poppins: ['Poppins', 'Helvetica Neue', 'sans-serif'],
},
colors: {
border: "hsl(var(--border))",
@@ -31,6 +40,7 @@ module.exports = {
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
+ sidebar: "white",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
@@ -83,12 +93,50 @@ module.exports = {
from: { height: 'var(--radix-collapsible-content-height)' },
to: { height: 0 },
},
+ 'fade-in-down': {
+ '0%': {
+ opacity: '0',
+ transform: 'translateY(-3px)'
+ },
+ '100%': {
+ opacity: '1',
+ transform: 'translateY(0)'
+ },
+ },
+ 'bounce-in': {
+ '0%': { transform: 'scale(0)' },
+ '50%': { transform: 'scale(1.2)' },
+ '100%': { transform: 'scale(1)' },
+ },
+ 'fade-in': {
+ '0%': { opacity: '0' },
+ '100%': { opacity: '1' },
+ },
+ 'fade-out': {
+ '0%': { opacity: '1' },
+ '100%': { opacity: '0' },
+ },
+ 'slide-in': {
+ '0%': { transform: 'translateY(10px)', opacity: '0' },
+ '100%': { transform: 'translateY(0)', opacity: '1' }
+ },
+ 'slide-out': {
+ '0%': { transform: 'translateY(0)', opacity: '1' },
+ '100%': { transform: 'translateY(10px)', opacity: '0' }
+ },
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
- "collapsible-down": "collapsible-down 0.2s ease-in-out",
- "collapsible-up": "collapsible-up 0.2s ease-in-out",
+ 'collapsible-down': 'collapsible-down 0.2s ease-in-out',
+ 'collapsible-up': 'collapsible-up 0.2s ease-in-out',
+ 'fade-in-down': 'fade-in-down 0.3s ease-out',
+ 'bounce-in': 'bounce-in 0.3s',
+ 'bounce-out': 'bounce-in 0.3s reverse',
+ 'fade-in': 'fade-in 0.3s ease-out',
+ 'fade-out': 'fade-out 0.3s ease-in',
+ 'slide-in': 'slide-in 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
+ 'slide-out': 'slide-out 0.3s cubic-bezier(0.4, 0, 0.2, 1)'
},
},
},
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
deleted file mode 100644
index 33b24a84..00000000
--- a/frontend/yarn.lock
+++ /dev/null
@@ -1,9765 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"@alloc/quick-lru@^5.2.0":
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
- integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
-
-"@ampproject/remapping@^2.2.0":
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4"
- integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==
- dependencies:
- "@jridgewell/gen-mapping" "^0.3.5"
- "@jridgewell/trace-mapping" "^0.3.24"
-
-"@babel/code-frame@^7.0.0":
- version "7.24.2"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae"
- integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==
- dependencies:
- "@babel/highlight" "^7.24.2"
- picocolors "^1.0.0"
-
-"@babel/code-frame@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465"
- integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==
- dependencies:
- "@babel/highlight" "^7.24.7"
- picocolors "^1.0.0"
-
-"@babel/compat-data@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.7.tgz#d23bbea508c3883ba8251fb4164982c36ea577ed"
- integrity sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==
-
-"@babel/core@^7.24.4", "@babel/core@^7.24.5":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.7.tgz#b676450141e0b52a3d43bc91da86aa608f950ac4"
- integrity sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==
- dependencies:
- "@ampproject/remapping" "^2.2.0"
- "@babel/code-frame" "^7.24.7"
- "@babel/generator" "^7.24.7"
- "@babel/helper-compilation-targets" "^7.24.7"
- "@babel/helper-module-transforms" "^7.24.7"
- "@babel/helpers" "^7.24.7"
- "@babel/parser" "^7.24.7"
- "@babel/template" "^7.24.7"
- "@babel/traverse" "^7.24.7"
- "@babel/types" "^7.24.7"
- convert-source-map "^2.0.0"
- debug "^4.1.0"
- gensync "^1.0.0-beta.2"
- json5 "^2.2.3"
- semver "^6.3.1"
-
-"@babel/generator@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.7.tgz#1654d01de20ad66b4b4d99c135471bc654c55e6d"
- integrity sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==
- dependencies:
- "@babel/types" "^7.24.7"
- "@jridgewell/gen-mapping" "^0.3.5"
- "@jridgewell/trace-mapping" "^0.3.25"
- jsesc "^2.5.1"
-
-"@babel/helper-annotate-as-pure@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab"
- integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==
- dependencies:
- "@babel/types" "^7.24.7"
-
-"@babel/helper-compilation-targets@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz#4eb6c4a80d6ffeac25ab8cd9a21b5dfa48d503a9"
- integrity sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==
- dependencies:
- "@babel/compat-data" "^7.24.7"
- "@babel/helper-validator-option" "^7.24.7"
- browserslist "^4.22.2"
- lru-cache "^5.1.1"
- semver "^6.3.1"
-
-"@babel/helper-create-class-features-plugin@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz#2eaed36b3a1c11c53bdf80d53838b293c52f5b3b"
- integrity sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==
- dependencies:
- "@babel/helper-annotate-as-pure" "^7.24.7"
- "@babel/helper-environment-visitor" "^7.24.7"
- "@babel/helper-function-name" "^7.24.7"
- "@babel/helper-member-expression-to-functions" "^7.24.7"
- "@babel/helper-optimise-call-expression" "^7.24.7"
- "@babel/helper-replace-supers" "^7.24.7"
- "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7"
- "@babel/helper-split-export-declaration" "^7.24.7"
- semver "^6.3.1"
-
-"@babel/helper-environment-visitor@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9"
- integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==
- dependencies:
- "@babel/types" "^7.24.7"
-
-"@babel/helper-function-name@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2"
- integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==
- dependencies:
- "@babel/template" "^7.24.7"
- "@babel/types" "^7.24.7"
-
-"@babel/helper-hoist-variables@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee"
- integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==
- dependencies:
- "@babel/types" "^7.24.7"
-
-"@babel/helper-member-expression-to-functions@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz#67613d068615a70e4ed5101099affc7a41c5225f"
- integrity sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==
- dependencies:
- "@babel/traverse" "^7.24.7"
- "@babel/types" "^7.24.7"
-
-"@babel/helper-module-imports@^7.16.7":
- version "7.24.3"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128"
- integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==
- dependencies:
- "@babel/types" "^7.24.0"
-
-"@babel/helper-module-imports@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b"
- integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==
- dependencies:
- "@babel/traverse" "^7.24.7"
- "@babel/types" "^7.24.7"
-
-"@babel/helper-module-transforms@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz#31b6c9a2930679498db65b685b1698bfd6c7daf8"
- integrity sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==
- dependencies:
- "@babel/helper-environment-visitor" "^7.24.7"
- "@babel/helper-module-imports" "^7.24.7"
- "@babel/helper-simple-access" "^7.24.7"
- "@babel/helper-split-export-declaration" "^7.24.7"
- "@babel/helper-validator-identifier" "^7.24.7"
-
-"@babel/helper-optimise-call-expression@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz#8b0a0456c92f6b323d27cfd00d1d664e76692a0f"
- integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==
- dependencies:
- "@babel/types" "^7.24.7"
-
-"@babel/helper-plugin-utils@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz#98c84fe6fe3d0d3ae7bfc3a5e166a46844feb2a0"
- integrity sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==
-
-"@babel/helper-replace-supers@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz#f933b7eed81a1c0265740edc91491ce51250f765"
- integrity sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==
- dependencies:
- "@babel/helper-environment-visitor" "^7.24.7"
- "@babel/helper-member-expression-to-functions" "^7.24.7"
- "@babel/helper-optimise-call-expression" "^7.24.7"
-
-"@babel/helper-simple-access@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3"
- integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==
- dependencies:
- "@babel/traverse" "^7.24.7"
- "@babel/types" "^7.24.7"
-
-"@babel/helper-skip-transparent-expression-wrappers@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz#5f8fa83b69ed5c27adc56044f8be2b3ea96669d9"
- integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==
- dependencies:
- "@babel/traverse" "^7.24.7"
- "@babel/types" "^7.24.7"
-
-"@babel/helper-split-export-declaration@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856"
- integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==
- dependencies:
- "@babel/types" "^7.24.7"
-
-"@babel/helper-string-parser@^7.24.1":
- version "7.24.1"
- resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e"
- integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==
-
-"@babel/helper-string-parser@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz#4d2d0f14820ede3b9807ea5fc36dfc8cd7da07f2"
- integrity sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==
-
-"@babel/helper-validator-identifier@^7.24.5":
- version "7.24.5"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62"
- integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==
-
-"@babel/helper-validator-identifier@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db"
- integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==
-
-"@babel/helper-validator-option@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz#24c3bb77c7a425d1742eec8fb433b5a1b38e62f6"
- integrity sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==
-
-"@babel/helpers@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.7.tgz#aa2ccda29f62185acb5d42fb4a3a1b1082107416"
- integrity sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==
- dependencies:
- "@babel/template" "^7.24.7"
- "@babel/types" "^7.24.7"
-
-"@babel/highlight@^7.24.2":
- version "7.24.5"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.5.tgz#bc0613f98e1dd0720e99b2a9ee3760194a704b6e"
- integrity sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==
- dependencies:
- "@babel/helper-validator-identifier" "^7.24.5"
- chalk "^2.4.2"
- js-tokens "^4.0.0"
- picocolors "^1.0.0"
-
-"@babel/highlight@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d"
- integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==
- dependencies:
- "@babel/helper-validator-identifier" "^7.24.7"
- chalk "^2.4.2"
- js-tokens "^4.0.0"
- picocolors "^1.0.0"
-
-"@babel/parser@^7.24.4":
- version "7.24.5"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.5.tgz#4a4d5ab4315579e5398a82dcf636ca80c3392790"
- integrity sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==
-
-"@babel/parser@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85"
- integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==
-
-"@babel/plugin-syntax-jsx@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d"
- integrity sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.24.7"
-
-"@babel/plugin-syntax-typescript@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz#58d458271b4d3b6bb27ee6ac9525acbb259bad1c"
- integrity sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.24.7"
-
-"@babel/plugin-transform-modules-commonjs@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz#9fd5f7fdadee9085886b183f1ad13d1ab260f4ab"
- integrity sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==
- dependencies:
- "@babel/helper-module-transforms" "^7.24.7"
- "@babel/helper-plugin-utils" "^7.24.7"
- "@babel/helper-simple-access" "^7.24.7"
-
-"@babel/plugin-transform-typescript@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.7.tgz#b006b3e0094bf0813d505e0c5485679eeaf4a881"
- integrity sha512-iLD3UNkgx2n/HrjBesVbYX6j0yqn/sJktvbtKKgcaLIQ4bTTQ8obAypc1VpyHPD2y4Phh9zHOaAt8e/L14wCpw==
- dependencies:
- "@babel/helper-annotate-as-pure" "^7.24.7"
- "@babel/helper-create-class-features-plugin" "^7.24.7"
- "@babel/helper-plugin-utils" "^7.24.7"
- "@babel/plugin-syntax-typescript" "^7.24.7"
-
-"@babel/preset-typescript@^7.24.1":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz#66cd86ea8f8c014855671d5ea9a737139cbbfef1"
- integrity sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.24.7"
- "@babel/helper-validator-option" "^7.24.7"
- "@babel/plugin-syntax-jsx" "^7.24.7"
- "@babel/plugin-transform-modules-commonjs" "^7.24.7"
- "@babel/plugin-transform-typescript" "^7.24.7"
-
-"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.24.1":
- version "7.24.5"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.5.tgz#230946857c053a36ccc66e1dd03b17dd0c4ed02c"
- integrity sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==
- dependencies:
- regenerator-runtime "^0.14.0"
-
-"@babel/template@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315"
- integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==
- dependencies:
- "@babel/code-frame" "^7.24.7"
- "@babel/parser" "^7.24.7"
- "@babel/types" "^7.24.7"
-
-"@babel/traverse@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.7.tgz#de2b900163fa741721ba382163fe46a936c40cf5"
- integrity sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==
- dependencies:
- "@babel/code-frame" "^7.24.7"
- "@babel/generator" "^7.24.7"
- "@babel/helper-environment-visitor" "^7.24.7"
- "@babel/helper-function-name" "^7.24.7"
- "@babel/helper-hoist-variables" "^7.24.7"
- "@babel/helper-split-export-declaration" "^7.24.7"
- "@babel/parser" "^7.24.7"
- "@babel/types" "^7.24.7"
- debug "^4.3.1"
- globals "^11.1.0"
-
-"@babel/types@^7.24.0":
- version "7.24.5"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.5.tgz#7661930afc638a5383eb0c4aee59b74f38db84d7"
- integrity sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==
- dependencies:
- "@babel/helper-string-parser" "^7.24.1"
- "@babel/helper-validator-identifier" "^7.24.5"
- to-fast-properties "^2.0.0"
-
-"@babel/types@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2"
- integrity sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==
- dependencies:
- "@babel/helper-string-parser" "^7.24.7"
- "@babel/helper-validator-identifier" "^7.24.7"
- to-fast-properties "^2.0.0"
-
-"@bassist/utils@^0.4.0":
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/@bassist/utils/-/utils-0.4.0.tgz#58eb247b37afc3c405543884731a134f522fc64b"
- integrity sha512-aoFTl0jUjm8/tDZodP41wnEkvB+C5O9NFCuYN/ztL6jSUSsuBkXq90/1ifBm1XhV/zySHgLYlU1+tgo3XtQ+nA==
- dependencies:
- "@withtypes/mime" "^0.1.2"
-
-"@colors/colors@1.5.0":
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
- integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
-
-"@cypress/request@^3.0.0":
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/@cypress/request/-/request-3.0.1.tgz#72d7d5425236a2413bd3d8bb66d02d9dc3168960"
- integrity sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==
- dependencies:
- aws-sign2 "~0.7.0"
- aws4 "^1.8.0"
- caseless "~0.12.0"
- combined-stream "~1.0.6"
- extend "~3.0.2"
- forever-agent "~0.6.1"
- form-data "~2.3.2"
- http-signature "~1.3.6"
- is-typedarray "~1.0.0"
- isstream "~0.1.2"
- json-stringify-safe "~5.0.1"
- mime-types "~2.1.19"
- performance-now "^2.1.0"
- qs "6.10.4"
- safe-buffer "^5.1.2"
- tough-cookie "^4.1.3"
- tunnel-agent "^0.6.0"
- uuid "^8.3.2"
-
-"@cypress/xvfb@^1.2.4":
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a"
- integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==
- dependencies:
- debug "^3.1.0"
- lodash.once "^4.1.1"
-
-"@emotion/babel-plugin@^11.11.0":
- version "11.11.0"
- resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c"
- integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==
- dependencies:
- "@babel/helper-module-imports" "^7.16.7"
- "@babel/runtime" "^7.18.3"
- "@emotion/hash" "^0.9.1"
- "@emotion/memoize" "^0.8.1"
- "@emotion/serialize" "^1.1.2"
- babel-plugin-macros "^3.1.0"
- convert-source-map "^1.5.0"
- escape-string-regexp "^4.0.0"
- find-root "^1.1.0"
- source-map "^0.5.7"
- stylis "4.2.0"
-
-"@emotion/cache@^11.11.0":
- version "11.11.0"
- resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff"
- integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==
- dependencies:
- "@emotion/memoize" "^0.8.1"
- "@emotion/sheet" "^1.2.2"
- "@emotion/utils" "^1.2.1"
- "@emotion/weak-memoize" "^0.3.1"
- stylis "4.2.0"
-
-"@emotion/css@^11.7.1":
- version "11.11.2"
- resolved "https://registry.yarnpkg.com/@emotion/css/-/css-11.11.2.tgz#e5fa081d0c6e335352e1bc2b05953b61832dca5a"
- integrity sha512-VJxe1ucoMYMS7DkiMdC2T7PWNbrEI0a39YRiyDvK2qq4lXwjRbVP/z4lpG+odCsRzadlR+1ywwrTzhdm5HNdew==
- dependencies:
- "@emotion/babel-plugin" "^11.11.0"
- "@emotion/cache" "^11.11.0"
- "@emotion/serialize" "^1.1.2"
- "@emotion/sheet" "^1.2.2"
- "@emotion/utils" "^1.2.1"
-
-"@emotion/hash@^0.9.1":
- version "0.9.1"
- resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43"
- integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==
-
-"@emotion/memoize@^0.8.1":
- version "0.8.1"
- resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17"
- integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==
-
-"@emotion/serialize@^1.1.2":
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.4.tgz#fc8f6d80c492cfa08801d544a05331d1cc7cd451"
- integrity sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==
- dependencies:
- "@emotion/hash" "^0.9.1"
- "@emotion/memoize" "^0.8.1"
- "@emotion/unitless" "^0.8.1"
- "@emotion/utils" "^1.2.1"
- csstype "^3.0.2"
-
-"@emotion/sheet@^1.2.2":
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec"
- integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==
-
-"@emotion/unitless@^0.8.1":
- version "0.8.1"
- resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3"
- integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==
-
-"@emotion/utils@^1.2.1":
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4"
- integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==
-
-"@emotion/weak-memoize@^0.3.1":
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6"
- integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==
-
-"@esbuild/aix-ppc64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f"
- integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==
-
-"@esbuild/android-arm64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052"
- integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==
-
-"@esbuild/android-arm@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28"
- integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==
-
-"@esbuild/android-x64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e"
- integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==
-
-"@esbuild/darwin-arm64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a"
- integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==
-
-"@esbuild/darwin-x64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22"
- integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==
-
-"@esbuild/freebsd-arm64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e"
- integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==
-
-"@esbuild/freebsd-x64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261"
- integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==
-
-"@esbuild/linux-arm64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b"
- integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==
-
-"@esbuild/linux-arm@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9"
- integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==
-
-"@esbuild/linux-ia32@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2"
- integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==
-
-"@esbuild/linux-loong64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df"
- integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==
-
-"@esbuild/linux-mips64el@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe"
- integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==
-
-"@esbuild/linux-ppc64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4"
- integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==
-
-"@esbuild/linux-riscv64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc"
- integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==
-
-"@esbuild/linux-s390x@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de"
- integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==
-
-"@esbuild/linux-x64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0"
- integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==
-
-"@esbuild/netbsd-x64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047"
- integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==
-
-"@esbuild/openbsd-x64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70"
- integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==
-
-"@esbuild/sunos-x64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b"
- integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==
-
-"@esbuild/win32-arm64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d"
- integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==
-
-"@esbuild/win32-ia32@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b"
- integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==
-
-"@esbuild/win32-x64@0.21.5":
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c"
- integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==
-
-"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
- integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
- dependencies:
- eslint-visitor-keys "^3.3.0"
-
-"@eslint-community/regexpp@^4.6.1":
- version "4.10.0"
- resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63"
- integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==
-
-"@eslint/eslintrc@^2.1.4":
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad"
- integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==
- dependencies:
- ajv "^6.12.4"
- debug "^4.3.2"
- espree "^9.6.0"
- globals "^13.19.0"
- ignore "^5.2.0"
- import-fresh "^3.2.1"
- js-yaml "^4.1.0"
- minimatch "^3.1.2"
- strip-json-comments "^3.1.1"
-
-"@eslint/js@8.57.0":
- version "8.57.0"
- resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f"
- integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==
-
-"@floating-ui/core@^1.0.0":
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.2.tgz#d37f3e0ac1f1c756c7de45db13303a266226851a"
- integrity sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==
- dependencies:
- "@floating-ui/utils" "^0.2.0"
-
-"@floating-ui/core@^1.6.0":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.7.tgz#7602367795a390ff0662efd1c7ae8ca74e75fb12"
- integrity sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==
- dependencies:
- "@floating-ui/utils" "^0.2.7"
-
-"@floating-ui/dom@^1.0.0", "@floating-ui/dom@^1.6.7":
- version "1.6.10"
- resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.10.tgz#b74c32f34a50336c86dcf1f1c845cf3a39e26d6f"
- integrity sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==
- dependencies:
- "@floating-ui/core" "^1.6.0"
- "@floating-ui/utils" "^0.2.7"
-
-"@floating-ui/dom@^1.6.1", "@floating-ui/dom@^1.6.5":
- version "1.6.5"
- resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.5.tgz#323f065c003f1d3ecf0ff16d2c2c4d38979f4cb9"
- integrity sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==
- dependencies:
- "@floating-ui/core" "^1.0.0"
- "@floating-ui/utils" "^0.2.0"
-
-"@floating-ui/utils@^0.2.0", "@floating-ui/utils@^0.2.1":
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.2.tgz#d8bae93ac8b815b2bd7a98078cf91e2724ef11e5"
- integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==
-
-"@floating-ui/utils@^0.2.7":
- version "0.2.7"
- resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.7.tgz#d0ece53ce99ab5a8e37ebdfe5e32452a2bfc073e"
- integrity sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==
-
-"@floating-ui/vue@^1.0.6":
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/@floating-ui/vue/-/vue-1.0.6.tgz#31860a12f1135d19554c232d99c5bab631c5c576"
- integrity sha512-EdrOljjkpkkqZnrpqUcPoz9NvHxuTjUtSInh6GMv3+Mcy+giY2cE2pHh9rpacRcZ2eMSCxel9jWkWXTjLmY55w==
- dependencies:
- "@floating-ui/dom" "^1.6.1"
- "@floating-ui/utils" "^0.2.1"
- vue-demi ">=0.13.0"
-
-"@floating-ui/vue@^1.1.0":
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/@floating-ui/vue/-/vue-1.1.4.tgz#1dd6905a58baaa9a84c44c2cf28e281f715957a1"
- integrity sha512-ammH7T3vyCx7pmm9OF19Wc42zrGnUw0QvLoidgypWsCLJMtGXEwY7paYIHO+K+oLC3mbWpzIHzeTVienYenlNg==
- dependencies:
- "@floating-ui/dom" "^1.0.0"
- "@floating-ui/utils" "^0.2.7"
- vue-demi ">=0.13.0"
-
-"@formkit/auto-animate@^0.8.2":
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/@formkit/auto-animate/-/auto-animate-0.8.2.tgz#24a56e816159fd5585405dcee6bb992f81c27585"
- integrity sha512-SwPWfeRa5veb1hOIBMdzI+73te5puUBHmqqaF1Bu7FjvxlYSz/kJcZKSa9Cg60zL0uRNeJL2SbRxV6Jp6Q1nFQ==
-
-"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
- version "9.3.0"
- resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
- integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
-
-"@hapi/topo@^5.1.0":
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
- integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
- dependencies:
- "@hapi/hoek" "^9.0.0"
-
-"@humanwhocodes/config-array@^0.11.14":
- version "0.11.14"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b"
- integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==
- dependencies:
- "@humanwhocodes/object-schema" "^2.0.2"
- debug "^4.3.1"
- minimatch "^3.0.5"
-
-"@humanwhocodes/module-importer@^1.0.1":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
- integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
-
-"@humanwhocodes/object-schema@^2.0.2":
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3"
- integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==
-
-"@iconify/types@^2.0.0":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57"
- integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==
-
-"@iconify/vue@^4.1.2":
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/@iconify/vue/-/vue-4.1.2.tgz#b76135785ca366b29bf0736eee9cfefc1c2ef79e"
- integrity sha512-CQnYqLiQD5LOAaXhBrmj1mdL2/NCJvwcC4jtW2Z8ukhThiFkLDkutarTOV2trfc9EXqUqRs0KqXOL9pZ/IyysA==
- dependencies:
- "@iconify/types" "^2.0.0"
-
-"@internationalized/date@^3.5.4":
- version "3.5.4"
- resolved "https://registry.yarnpkg.com/@internationalized/date/-/date-3.5.4.tgz#49ba11634fd4350b7a9308e297032267b4063c44"
- integrity sha512-qoVJVro+O0rBaw+8HPjUB1iH8Ihf8oziEnqMnvhJUSuVIrHOuZ6eNLHNvzXJKUvAtaDiqMnRlg8Z2mgh09BlUw==
- dependencies:
- "@swc/helpers" "^0.5.0"
-
-"@internationalized/date@^3.5.5":
- version "3.5.5"
- resolved "https://registry.yarnpkg.com/@internationalized/date/-/date-3.5.5.tgz#7d34cb9da35127f98dd669fc926bb37e771e177f"
- integrity sha512-H+CfYvOZ0LTJeeLOqm19E3uj/4YjrmOFtBufDHPfvtI80hFAMqtrp7oCACpe4Cil5l8S0Qu/9dYfZc/5lY8WQQ==
- dependencies:
- "@swc/helpers" "^0.5.0"
-
-"@internationalized/number@^3.5.3":
- version "3.5.3"
- resolved "https://registry.yarnpkg.com/@internationalized/number/-/number-3.5.3.tgz#9fa060c1c4809f23fb3d38dd3f3d1ae4c87e95a8"
- integrity sha512-rd1wA3ebzlp0Mehj5YTuTI50AQEx80gWFyHcQu+u91/5NgdwBecO8BH6ipPfE+lmQ9d63vpB3H9SHoIUiupllw==
- dependencies:
- "@swc/helpers" "^0.5.0"
-
-"@intlify/core-base@9.13.1":
- version "9.13.1"
- resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.13.1.tgz#bd1f38e665095993ef9b67aeeb794f3cabcb515d"
- integrity sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==
- dependencies:
- "@intlify/message-compiler" "9.13.1"
- "@intlify/shared" "9.13.1"
-
-"@intlify/message-compiler@9.13.1":
- version "9.13.1"
- resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.13.1.tgz#ff8129badf77db3fb648b8d3cceee87c8033ed0a"
- integrity sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==
- dependencies:
- "@intlify/shared" "9.13.1"
- source-map-js "^1.0.2"
-
-"@intlify/shared@9.13.1":
- version "9.13.1"
- resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.13.1.tgz#202741d11ece1a9c7480bfd3f27afcf9cb8f72e4"
- integrity sha512-u3b6BKGhE6j/JeRU6C/RL2FgyJfy6LakbtfeVF8fJXURpZZTzfh3e05J0bu0XPw447Q6/WUp3C4ajv4TMS4YsQ==
-
-"@isaacs/cliui@^8.0.2":
- version "8.0.2"
- resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
- integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
- dependencies:
- string-width "^5.1.2"
- string-width-cjs "npm:string-width@^4.2.0"
- strip-ansi "^7.0.1"
- strip-ansi-cjs "npm:strip-ansi@^6.0.1"
- wrap-ansi "^8.1.0"
- wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
-
-"@isaacs/string-locale-compare@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz#291c227e93fd407a96ecd59879a35809120e432b"
- integrity sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==
-
-"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5":
- version "0.3.5"
- resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36"
- integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==
- dependencies:
- "@jridgewell/set-array" "^1.2.1"
- "@jridgewell/sourcemap-codec" "^1.4.10"
- "@jridgewell/trace-mapping" "^0.3.24"
-
-"@jridgewell/resolve-uri@^3.1.0":
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
- integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
-
-"@jridgewell/set-array@^1.2.1":
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280"
- integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
-
-"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15":
- version "1.4.15"
- resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
- integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
-
-"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
- version "0.3.25"
- resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
- integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
- dependencies:
- "@jridgewell/resolve-uri" "^3.1.0"
- "@jridgewell/sourcemap-codec" "^1.4.14"
-
-"@juggle/resize-observer@^3.3.1":
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
- integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
-
-"@mapbox/geojson-rewind@^0.5.2":
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz#591a5d71a9cd1da1a0bf3420b3bea31b0fc7946a"
- integrity sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==
- dependencies:
- get-stream "^6.0.1"
- minimist "^1.2.6"
-
-"@mapbox/jsonlint-lines-primitives@^2.0.2":
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz#ce56e539f83552b58d10d672ea4d6fc9adc7b234"
- integrity sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==
-
-"@mapbox/mapbox-gl-supported@^2.0.1":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-2.0.1.tgz#c15367178d8bfe4765e6b47b542fe821ce259c7b"
- integrity sha512-HP6XvfNIzfoMVfyGjBckjiAOQK9WfX0ywdLubuPMPv+Vqf5fj0uCbgBQYpiqcWZT6cbyyRnTSXDheT1ugvF6UQ==
-
-"@mapbox/point-geometry@0.1.0", "@mapbox/point-geometry@^0.1.0", "@mapbox/point-geometry@~0.1.0":
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz#8a83f9335c7860effa2eeeca254332aa0aeed8f2"
- integrity sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==
-
-"@mapbox/tiny-sdf@^2.0.5":
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz#9a1d33e5018093e88f6a4df2343e886056287282"
- integrity sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA==
-
-"@mapbox/unitbezier@^0.0.1":
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz#d32deb66c7177e9e9dfc3bbd697083e2e657ff01"
- integrity sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==
-
-"@mapbox/vector-tile@^1.3.1":
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz#d3a74c90402d06e89ec66de49ec817ff53409666"
- integrity sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==
- dependencies:
- "@mapbox/point-geometry" "~0.1.0"
-
-"@mapbox/whoots-js@^3.1.0":
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe"
- integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==
-
-"@nodelib/fs.scandir@2.1.5":
- version "2.1.5"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
- integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
- dependencies:
- "@nodelib/fs.stat" "2.0.5"
- run-parallel "^1.1.9"
-
-"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
- integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
-
-"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8":
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
- integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
- dependencies:
- "@nodelib/fs.scandir" "2.1.5"
- fastq "^1.6.0"
-
-"@npmcli/agent@^2.0.0":
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-2.2.2.tgz#967604918e62f620a648c7975461c9c9e74fc5d5"
- integrity sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==
- dependencies:
- agent-base "^7.1.0"
- http-proxy-agent "^7.0.0"
- https-proxy-agent "^7.0.1"
- lru-cache "^10.0.1"
- socks-proxy-agent "^8.0.3"
-
-"@npmcli/arborist@^7.2.1":
- version "7.5.1"
- resolved "https://registry.yarnpkg.com/@npmcli/arborist/-/arborist-7.5.1.tgz#7075f8d0e34e92dee1292b0f055bc31725a54b56"
- integrity sha512-rjGX1tzn9HVQHv5lIP2wANvJmG5+/aFiVFoTBSzneOaSuBUJOnFRha2DE+cIRRekuGllmYff2/XcXnOWrZOJ/w==
- dependencies:
- "@isaacs/string-locale-compare" "^1.1.0"
- "@npmcli/fs" "^3.1.0"
- "@npmcli/installed-package-contents" "^2.1.0"
- "@npmcli/map-workspaces" "^3.0.2"
- "@npmcli/metavuln-calculator" "^7.1.0"
- "@npmcli/name-from-folder" "^2.0.0"
- "@npmcli/node-gyp" "^3.0.0"
- "@npmcli/package-json" "^5.1.0"
- "@npmcli/query" "^3.1.0"
- "@npmcli/redact" "^2.0.0"
- "@npmcli/run-script" "^8.1.0"
- bin-links "^4.0.1"
- cacache "^18.0.0"
- common-ancestor-path "^1.0.1"
- hosted-git-info "^7.0.1"
- json-parse-even-better-errors "^3.0.0"
- json-stringify-nice "^1.1.4"
- minimatch "^9.0.4"
- nopt "^7.0.0"
- npm-install-checks "^6.2.0"
- npm-package-arg "^11.0.2"
- npm-pick-manifest "^9.0.0"
- npm-registry-fetch "^17.0.0"
- pacote "^18.0.1"
- parse-conflict-json "^3.0.0"
- proc-log "^4.2.0"
- proggy "^2.0.0"
- promise-all-reject-late "^1.0.0"
- promise-call-limit "^3.0.1"
- read-package-json-fast "^3.0.2"
- semver "^7.3.7"
- ssri "^10.0.5"
- treeverse "^3.0.0"
- walk-up-path "^3.0.1"
-
-"@npmcli/config@^8.0.2":
- version "8.3.1"
- resolved "https://registry.yarnpkg.com/@npmcli/config/-/config-8.3.1.tgz#14814f52f4fb0293e45bfb1d3e6877c1d1cc514b"
- integrity sha512-lEY3TnkVrNUwI0vCDTFlKTbxK9DxZ83JmXXcQI7kp7pyg7zj/a36xSDmcikXvUbtV2PQpmUwmV0HDAB94NcgNA==
- dependencies:
- "@npmcli/map-workspaces" "^3.0.2"
- ci-info "^4.0.0"
- ini "^4.1.2"
- nopt "^7.0.0"
- proc-log "^4.2.0"
- read-package-json-fast "^3.0.2"
- semver "^7.3.5"
- walk-up-path "^3.0.1"
-
-"@npmcli/fs@^3.1.0":
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.1.tgz#59cdaa5adca95d135fc00f2bb53f5771575ce726"
- integrity sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==
- dependencies:
- semver "^7.3.5"
-
-"@npmcli/git@^5.0.0", "@npmcli/git@^5.0.6":
- version "5.0.7"
- resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-5.0.7.tgz#7ff675e33b4dc0b0adb1f0c4aa302109efc06463"
- integrity sha512-WaOVvto604d5IpdCRV2KjQu8PzkfE96d50CQGKgywXh2GxXmDeUO5EWcBC4V57uFyrNqx83+MewuJh3WTR3xPA==
- dependencies:
- "@npmcli/promise-spawn" "^7.0.0"
- lru-cache "^10.0.1"
- npm-pick-manifest "^9.0.0"
- proc-log "^4.0.0"
- promise-inflight "^1.0.1"
- promise-retry "^2.0.1"
- semver "^7.3.5"
- which "^4.0.0"
-
-"@npmcli/installed-package-contents@^2.0.1", "@npmcli/installed-package-contents@^2.1.0":
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz#63048e5f6e40947a3a88dcbcb4fd9b76fdd37c17"
- integrity sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==
- dependencies:
- npm-bundled "^3.0.0"
- npm-normalize-package-bin "^3.0.0"
-
-"@npmcli/map-workspaces@^3.0.2", "@npmcli/map-workspaces@^3.0.6":
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/@npmcli/map-workspaces/-/map-workspaces-3.0.6.tgz#27dc06c20c35ef01e45a08909cab9cb3da08cea6"
- integrity sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==
- dependencies:
- "@npmcli/name-from-folder" "^2.0.0"
- glob "^10.2.2"
- minimatch "^9.0.0"
- read-package-json-fast "^3.0.0"
-
-"@npmcli/metavuln-calculator@^7.1.0":
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/@npmcli/metavuln-calculator/-/metavuln-calculator-7.1.1.tgz#4d3b6c3192f72bc8ad59476de0da939c33877fcf"
- integrity sha512-Nkxf96V0lAx3HCpVda7Vw4P23RILgdi/5K1fmj2tZkWIYLpXAN8k2UVVOsW16TsS5F8Ws2I7Cm+PU1/rsVF47g==
- dependencies:
- cacache "^18.0.0"
- json-parse-even-better-errors "^3.0.0"
- pacote "^18.0.0"
- proc-log "^4.1.0"
- semver "^7.3.5"
-
-"@npmcli/name-from-folder@^2.0.0":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz#c44d3a7c6d5c184bb6036f4d5995eee298945815"
- integrity sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==
-
-"@npmcli/node-gyp@^3.0.0":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz#101b2d0490ef1aa20ed460e4c0813f0db560545a"
- integrity sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==
-
-"@npmcli/package-json@^5.0.0", "@npmcli/package-json@^5.1.0":
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-5.1.0.tgz#10d117b5fb175acc14c70901a151c52deffc843e"
- integrity sha512-1aL4TuVrLS9sf8quCLerU3H9J4vtCtgu8VauYozrmEyU57i/EdKleCnsQ7vpnABIH6c9mnTxcH5sFkO3BlV8wQ==
- dependencies:
- "@npmcli/git" "^5.0.0"
- glob "^10.2.2"
- hosted-git-info "^7.0.0"
- json-parse-even-better-errors "^3.0.0"
- normalize-package-data "^6.0.0"
- proc-log "^4.0.0"
- semver "^7.5.3"
-
-"@npmcli/promise-spawn@^7.0.0", "@npmcli/promise-spawn@^7.0.1":
- version "7.0.2"
- resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz#1d53d34ffeb5d151bfa8ec661bcccda8bbdfd532"
- integrity sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==
- dependencies:
- which "^4.0.0"
-
-"@npmcli/query@^3.1.0":
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/@npmcli/query/-/query-3.1.0.tgz#bc202c59e122a06cf8acab91c795edda2cdad42c"
- integrity sha512-C/iR0tk7KSKGldibYIB9x8GtO/0Bd0I2mhOaDb8ucQL/bQVTmGoeREaFj64Z5+iCBRf3dQfed0CjJL7I8iTkiQ==
- dependencies:
- postcss-selector-parser "^6.0.10"
-
-"@npmcli/redact@^2.0.0":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@npmcli/redact/-/redact-2.0.0.tgz#72f9689e87bd0ce419c35e75b8470ce8ac9e14f0"
- integrity sha512-SEjCPAVHWYUIQR+Yn03kJmrJjZDtJLYpj300m3HV9OTRZNpC5YpbMsM3eTkECyT4aWj8lDr9WeY6TWefpubtYQ==
-
-"@npmcli/run-script@^8.0.0", "@npmcli/run-script@^8.1.0":
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-8.1.0.tgz#a563e5e29b1ca4e648a6b1bbbfe7220b4bfe39fc"
- integrity sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==
- dependencies:
- "@npmcli/node-gyp" "^3.0.0"
- "@npmcli/package-json" "^5.0.0"
- "@npmcli/promise-spawn" "^7.0.0"
- node-gyp "^10.0.0"
- proc-log "^4.0.0"
- which "^4.0.0"
-
-"@pkgjs/parseargs@^0.11.0":
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
- integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
-
-"@pkgr/core@^0.1.0":
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31"
- integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==
-
-"@popperjs/core@^2.9.0":
- version "2.11.8"
- resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
- integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
-
-"@radix-icons/vue@^1.0.0":
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/@radix-icons/vue/-/vue-1.0.0.tgz#429450ba373e695e9b5aa028d6ca699c57bb8b1e"
- integrity sha512-gKWWk9tTK/laDRRNe5KLLR8A0qUwx4q4+DN8Fq48hJ904u78R82ayAO3TrxbNLgyn2D0h6rRiGdLzQWj7rPcvA==
-
-"@remirror/core-constants@^2.0.2":
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/@remirror/core-constants/-/core-constants-2.0.2.tgz#f05eccdc69e3a65e7d524b52548f567904a11a1a"
- integrity sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==
-
-"@rollup/rollup-android-arm-eabi@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz#1661ff5ea9beb362795304cb916049aba7ac9c54"
- integrity sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==
-
-"@rollup/rollup-android-arm64@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz#2ffaa91f1b55a0082b8a722525741aadcbd3971e"
- integrity sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==
-
-"@rollup/rollup-darwin-arm64@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz#627007221b24b8cc3063703eee0b9177edf49c1f"
- integrity sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==
-
-"@rollup/rollup-darwin-x64@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz#0605506142b9e796c370d59c5984ae95b9758724"
- integrity sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==
-
-"@rollup/rollup-linux-arm-gnueabihf@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz#62dfd196d4b10c0c2db833897164d2d319ee0cbb"
- integrity sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==
-
-"@rollup/rollup-linux-arm-musleabihf@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz#53ce72aeb982f1f34b58b380baafaf6a240fddb3"
- integrity sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==
-
-"@rollup/rollup-linux-arm64-gnu@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz#1632990f62a75c74f43e4b14ab3597d7ed416496"
- integrity sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==
-
-"@rollup/rollup-linux-arm64-musl@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz#8c03a996efb41e257b414b2e0560b7a21f2d9065"
- integrity sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==
-
-"@rollup/rollup-linux-powerpc64le-gnu@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz#5b98729628d5bcc8f7f37b58b04d6845f85c7b5d"
- integrity sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==
-
-"@rollup/rollup-linux-riscv64-gnu@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz#48e42e41f4cabf3573cfefcb448599c512e22983"
- integrity sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==
-
-"@rollup/rollup-linux-s390x-gnu@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz#e0b4f9a966872cb7d3e21b9e412a4b7efd7f0b58"
- integrity sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==
-
-"@rollup/rollup-linux-x64-gnu@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz#78144741993100f47bd3da72fce215e077ae036b"
- integrity sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==
-
-"@rollup/rollup-linux-x64-musl@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz#d9fe32971883cd1bd858336bd33a1c3ca6146127"
- integrity sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==
-
-"@rollup/rollup-win32-arm64-msvc@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz#71fa3ea369316db703a909c790743972e98afae5"
- integrity sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==
-
-"@rollup/rollup-win32-ia32-msvc@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz#653f5989a60658e17d7576a3996deb3902e342e2"
- integrity sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==
-
-"@rollup/rollup-win32-x64-msvc@4.24.0":
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz#0574d7e87b44ee8511d08cc7f914bcb802b70818"
- integrity sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==
-
-"@rushstack/eslint-patch@^1.3.3":
- version "1.10.2"
- resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.2.tgz#053f1540703faa81dea2966b768ee5581c66aeda"
- integrity sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==
-
-"@sideway/address@^4.1.5":
- version "4.1.5"
- resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5"
- integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==
- dependencies:
- "@hapi/hoek" "^9.0.0"
-
-"@sideway/formula@^3.0.1":
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
- integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
-
-"@sideway/pinpoint@^2.0.0":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
- integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
-
-"@sigstore/bundle@^2.3.0", "@sigstore/bundle@^2.3.1":
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/@sigstore/bundle/-/bundle-2.3.1.tgz#f6cdc67c8400e58ca27f0ef495b27a9327512073"
- integrity sha512-eqV17lO3EIFqCWK3969Rz+J8MYrRZKw9IBHpSo6DEcEX2c+uzDFOgHE9f2MnyDpfs48LFO4hXmk9KhQ74JzU1g==
- dependencies:
- "@sigstore/protobuf-specs" "^0.3.1"
-
-"@sigstore/core@^1.0.0", "@sigstore/core@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@sigstore/core/-/core-1.1.0.tgz#5583d8f7ffe599fa0a89f2bf289301a5af262380"
- integrity sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==
-
-"@sigstore/protobuf-specs@^0.3.0", "@sigstore/protobuf-specs@^0.3.1":
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/@sigstore/protobuf-specs/-/protobuf-specs-0.3.2.tgz#5becf88e494a920f548d0163e2978f81b44b7d6f"
- integrity sha512-c6B0ehIWxMI8wiS/bj6rHMPqeFvngFV7cDU/MY+B16P9Z3Mp9k8L93eYZ7BYzSickzuqAQqAq0V956b3Ju6mLw==
-
-"@sigstore/sign@^2.3.0":
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/@sigstore/sign/-/sign-2.3.1.tgz#4fc4e6faee5689b5e9d42e97f1207273b7dd7b7f"
- integrity sha512-YZ71wKIOweC8ViUeZXboz0iPLqMkskxuoeN/D1CEpAyZvEepbX9oRMIoO6a/DxUqO1VEaqmcmmqzSiqtOsvSmw==
- dependencies:
- "@sigstore/bundle" "^2.3.0"
- "@sigstore/core" "^1.0.0"
- "@sigstore/protobuf-specs" "^0.3.1"
- make-fetch-happen "^13.0.1"
- proc-log "^4.2.0"
- promise-retry "^2.0.1"
-
-"@sigstore/tuf@^2.3.1", "@sigstore/tuf@^2.3.2":
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/@sigstore/tuf/-/tuf-2.3.3.tgz#be416424d5133b61f1adcc75df72136bf1dfe1ff"
- integrity sha512-agQhHNkIddXFslkudjV88vTXiAMEyUtso3at6ZHUNJ1agZb7Ze6VW/PddHipdWBu1t+8OWLW5X5yZOPiOnaWJQ==
- dependencies:
- "@sigstore/protobuf-specs" "^0.3.0"
- tuf-js "^2.2.1"
-
-"@sigstore/verify@^1.2.0":
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/@sigstore/verify/-/verify-1.2.0.tgz#48549186305d8a5e471a3a304cf4cb3e0c99dde7"
- integrity sha512-hQF60nc9yab+Csi4AyoAmilGNfpXT+EXdBgFkP9OgPwIBPwyqVf7JAWPtmqrrrneTmAT6ojv7OlH1f6Ix5BG4Q==
- dependencies:
- "@sigstore/bundle" "^2.3.1"
- "@sigstore/core" "^1.1.0"
- "@sigstore/protobuf-specs" "^0.3.1"
-
-"@swc/helpers@^0.5.0":
- version "0.5.11"
- resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.11.tgz#5bab8c660a6e23c13b2d23fcd1ee44a2db1b0cb7"
- integrity sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==
- dependencies:
- tslib "^2.4.0"
-
-"@tailwindcss/typography@^0.5.10":
- version "0.5.13"
- resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.13.tgz#cd788a4fa4d0ca2506e242d512f377b22c1f7932"
- integrity sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==
- dependencies:
- lodash.castarray "^4.4.0"
- lodash.isplainobject "^4.0.6"
- lodash.merge "^4.6.2"
- postcss-selector-parser "6.0.10"
-
-"@tanstack/table-core@8.19.2":
- version "8.19.2"
- resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.19.2.tgz#5fc8ede54f18867f74715ad93927f7df4d255209"
- integrity sha512-KpRjhgehIhbfH78ARm/GJDXGnpdw4bCg3qas6yjWSi7czJhI/J6pWln7NHtmBkGE9ZbohiiNtLqwGzKmBfixig==
-
-"@tanstack/virtual-core@3.5.0":
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.5.0.tgz#108208d0f1d75271300bc5560cf9a85a1fa01e89"
- integrity sha512-KnPRCkQTyqhanNC0K63GBG3wA8I+D1fQuVnAvcBF8f13akOKeQp1gSbu6f77zCxhEk727iV5oQnbHLYzHrECLg==
-
-"@tanstack/virtual-core@3.8.6":
- version "3.8.6"
- resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.8.6.tgz#ccecf84099a9a0e9732b4f17bf021b82f215d15e"
- integrity sha512-UJeU4SBrx3hqULNzJ3oC0kgJ5miIAg+FwomxMTlQNxob6ppTInifANHd9ukETvzdzxr6zt3CjQ0rttQpVjbt6Q==
-
-"@tanstack/vue-table@^8.19.2":
- version "8.19.2"
- resolved "https://registry.yarnpkg.com/@tanstack/vue-table/-/vue-table-8.19.2.tgz#909f63a225788757f62a7b7fa4568da6349b9a0f"
- integrity sha512-tzY/SfbltF3yvES6bQU8BQzcfl5qqSKB4xCGzbUM3qeRLlHNt6bpiHwFHfr0fhASMPQzwJadP+KW2zyaggRpmg==
- dependencies:
- "@tanstack/table-core" "8.19.2"
-
-"@tanstack/vue-virtual@^3.5.0":
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/@tanstack/vue-virtual/-/vue-virtual-3.5.0.tgz#5794af3b2d0cc0331ba3f671fba8770e0abd4993"
- integrity sha512-wvRQ8sFxn/NDr3WvI5XabhFovZ5MBmpEck2GHpTxYunmV63Ovpl30lRu6W5BPQo35a1GqDZ+Pvzlz6WDWRNqqw==
- dependencies:
- "@tanstack/virtual-core" "3.5.0"
-
-"@tanstack/vue-virtual@^3.8.1":
- version "3.8.6"
- resolved "https://registry.yarnpkg.com/@tanstack/vue-virtual/-/vue-virtual-3.8.6.tgz#c37a11ee8a03f04eaeaca7523eaa3963098e0728"
- integrity sha512-nWwmlFuxChPM6bWEwKOyBBYVrQmvSKSArXhbvX2IyVTpuif9UZiBEvIXnftpCEGRvAGSe7lE1coXHk8g2qmwtQ==
- dependencies:
- "@tanstack/virtual-core" "3.8.6"
-
-"@tiptap/core@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.4.0.tgz#6f8eee8beb5b89363582366b201ccc4798ac98a9"
- integrity sha512-YJSahk8pkxpCs8SflCZfTnJpE7IPyUWIylfgXM2DefjRQa5DZ+c6sNY0s/zbxKYFQ6AuHVX40r9pCfcqHChGxQ==
-
-"@tiptap/extension-blockquote@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.4.0.tgz#0179076ea2fa12e41a198dad087b81d368653b8d"
- integrity sha512-nJJy4KsPgQqWTTDOWzFRdjCfG5+QExfZj44dulgDFNh+E66xhamnbM70PklllXJgEcge7xmT5oKM0gKls5XgFw==
-
-"@tiptap/extension-bold@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.4.0.tgz#b5ced2c3bf51f304890137dbdf394d58c01eb208"
- integrity sha512-csnW6hMDEHoRfxcPRLSqeJn+j35Lgtt1YRiOwn7DlS66sAECGRuoGfCvQSPij0TCDp4VCR9if5Sf8EymhnQumQ==
-
-"@tiptap/extension-bubble-menu@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.4.0.tgz#a079329318fc21407f9a3c9c3da6ef72cb0b4ab6"
- integrity sha512-s99HmttUtpW3rScWq8rqk4+CGCwergNZbHLTkF6Rp6TSboMwfp+rwL5Q/JkcAG9KGLso1vGyXKbt1xHOvm8zMw==
- dependencies:
- tippy.js "^6.3.7"
-
-"@tiptap/extension-bullet-list@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.4.0.tgz#60eea05b5ac8c8e8d615c057559fddb95033abeb"
- integrity sha512-9S5DLIvFRBoExvmZ+/ErpTvs4Wf1yOEs8WXlKYUCcZssK7brTFj99XDwpHFA29HKDwma5q9UHhr2OB2o0JYAdw==
-
-"@tiptap/extension-code-block@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.4.0.tgz#b7f1da4825677a2ea6b8e970a1197877551e5dc8"
- integrity sha512-QWGdv1D56TBGbbJSj2cIiXGJEKguPiAl9ONzJ/Ql1ZksiQsYwx0YHriXX6TOC//T4VIf6NSClHEtwtxWBQ/Csg==
-
-"@tiptap/extension-code@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.4.0.tgz#3a9fed3585bf49f445505c2e9ad71fd66e117304"
- integrity sha512-wjhBukuiyJMq4cTcK3RBTzUPV24k5n1eEPlpmzku6ThwwkMdwynnMGMAmSF3fErh3AOyOUPoTTjgMYN2d10SJA==
-
-"@tiptap/extension-document@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.4.0.tgz#a396b2cbcc8708aa2a0a41d0be481fda4b61c77b"
- integrity sha512-3jRodQJZDGbXlRPERaloS+IERg/VwzpC1IO6YSJR9jVIsBO6xC29P3cKTQlg1XO7p6ZH/0ksK73VC5BzzTwoHg==
-
-"@tiptap/extension-dropcursor@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.4.0.tgz#8f54908f84a4ab7d2d7de7fc0197511138445740"
- integrity sha512-c46HoG2PEEpSZv5rmS5UX/lJ6/kP1iVO0Ax+6JrNfLEIiDULUoi20NqdjolEa38La2VhWvs+o20OviiTOKEE9g==
-
-"@tiptap/extension-floating-menu@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.4.0.tgz#75c48b98d0f833251eab70f269ed186f48fc398e"
- integrity sha512-vLb9v+htbHhXyty0oaXjT3VC8St4xuGSHWUB9GuAJAQ+NajIO6rBPbLUmm9qM0Eh2zico5mpSD1Qtn5FM6xYzg==
- dependencies:
- tippy.js "^6.3.7"
-
-"@tiptap/extension-gapcursor@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.4.0.tgz#2a738509d40f5f856492c11e32b10e4462f71216"
- integrity sha512-F4y/0J2lseohkFUw9P2OpKhrJ6dHz69ZScABUvcHxjznJLd6+0Zt7014Lw5PA8/m2d/w0fX8LZQ88pZr4quZPQ==
-
-"@tiptap/extension-hard-break@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.4.0.tgz#b5bf5b065827280e450fba8f53d137654509d836"
- integrity sha512-3+Z6zxevtHza5IsDBZ4lZqvNR3Kvdqwxq/QKCKu9UhJN1DUjsg/l1Jn2NilSQ3NYkBYh2yJjT8CMo9pQIu776g==
-
-"@tiptap/extension-heading@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.4.0.tgz#16302ce691714244c3d3fa92d2db86a5c895a025"
- integrity sha512-fYkyP/VMo7YHO76YVrUjd95Qeo0cubWn/Spavmwm1gLTHH/q7xMtbod2Z/F0wd6QHnc7+HGhO7XAjjKWDjldaw==
-
-"@tiptap/extension-history@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.4.0.tgz#1dbf8410c091175627414d48a0d857232a8f4094"
- integrity sha512-gr5qsKAXEVGr1Lyk1598F7drTaEtAxqZiuuSwTCzZzkiwgEQsWMWTWc9F8FlneCEaqe1aIYg6WKWlmYPaFwr0w==
-
-"@tiptap/extension-horizontal-rule@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.4.0.tgz#7f27c0778004602686251af7e2f7a8461a3d77ba"
- integrity sha512-yDgxy+YxagcEsBbdWvbQiXYxsv3noS1VTuGwc9G7ZK9xPmBHJ5y0agOkB7HskwsZvJHoaSqNRsh7oZTkf0VR3g==
-
-"@tiptap/extension-image@^2.5.9":
- version "2.5.9"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.5.9.tgz#2f2be205d889f6688ef85c76071d2199baab03e4"
- integrity sha512-v4WZISCvbriac6HE6v7kYYY7KX+v9rJaIZC3gbYGtqnBWfaAwZiVVu8Z03xSrqYhoc+KHuI+oQ4VubcvZ/i7OQ==
-
-"@tiptap/extension-italic@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.4.0.tgz#42ab003e04e1e8d825f698914c0e80ac849144f1"
- integrity sha512-aaW/L9q+KNHHK+X73MPloHeIsT191n3VLd3xm6uUcFDnUNvzYJ/q65/1ZicdtCaOLvTutxdrEvhbkrVREX6a8g==
-
-"@tiptap/extension-link@^2.9.1":
- version "2.9.1"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.9.1.tgz#c9817cd73aea418df77cad71b433bbd32b098734"
- integrity sha512-yG+e3e8cCCN9dZjX4ttEe3e2xhh58ryi3REJV4MdiEkOT9QF75Bl5pUbMIS4tQ8HkOr04QBFMHKM12kbSxg1BA==
- dependencies:
- linkifyjs "^4.1.0"
-
-"@tiptap/extension-list-item@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.4.0.tgz#a97a48850b81e94b9a60cc2aa16e515aa5311456"
- integrity sha512-reUVUx+2cI2NIAqMZhlJ9uK/+zvRzm1GTmlU2Wvzwc7AwLN4yemj6mBDsmBLEXAKPvitfLh6EkeHaruOGymQtg==
-
-"@tiptap/extension-ordered-list@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.4.0.tgz#6cf82e10d7e7f7cc44156d29b0b71a22dec31612"
- integrity sha512-Zo0c9M0aowv+2+jExZiAvhCB83GZMjZsxywmuOrdUbq5EGYKb7q8hDyN3hkrktVHr9UPXdPAYTmLAHztTOHYRA==
-
-"@tiptap/extension-paragraph@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.4.0.tgz#5b9aea8775937b327bbe6754be12ae3144fb09ff"
- integrity sha512-+yse0Ow67IRwcACd9K/CzBcxlpr9OFnmf0x9uqpaWt1eHck1sJnti6jrw5DVVkyEBHDh/cnkkV49gvctT/NyCw==
-
-"@tiptap/extension-placeholder@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-placeholder/-/extension-placeholder-2.4.0.tgz#b4cf5655cf6a4a39eaa5ef6a8376d5b31614db52"
- integrity sha512-SmWOjgWpmhFt0BPOnL65abCUH0wS5yksUJgtANn5bQoHF4HFSsyl7ETRmgf0ykxdjc7tzOg31FfpWVH4wzKSYg==
-
-"@tiptap/extension-strike@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.4.0.tgz#f09c4f51f7fed01c356026d7e8d8a1d1f2ac8f18"
- integrity sha512-pE1uN/fQPOMS3i+zxPYMmPmI3keubnR6ivwM+KdXWOMnBiHl9N4cNpJgq1n2eUUGKLurC2qrQHpnVyGAwBS6Vg==
-
-"@tiptap/extension-text@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.4.0.tgz#a3a5f45a9856d513e574f24e2c9b6028273f8eb3"
- integrity sha512-LV0bvE+VowE8IgLca7pM8ll7quNH+AgEHRbSrsI3SHKDCYB9gTHMjWaAkgkUVaO1u0IfCrjnCLym/PqFKa+vvg==
-
-"@tiptap/pm@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/pm/-/pm-2.4.0.tgz#f6fe81d24569da584658d2e8a3a378aea3619fb3"
- integrity sha512-B1HMEqGS4MzIVXnpgRZDLm30mxDWj51LkBT/if1XD+hj5gm8B9Q0c84bhvODX6KIs+c6z+zsY9VkVu8w9Yfgxg==
- dependencies:
- prosemirror-changeset "^2.2.1"
- prosemirror-collab "^1.3.1"
- prosemirror-commands "^1.5.2"
- prosemirror-dropcursor "^1.8.1"
- prosemirror-gapcursor "^1.3.2"
- prosemirror-history "^1.3.2"
- prosemirror-inputrules "^1.3.0"
- prosemirror-keymap "^1.2.2"
- prosemirror-markdown "^1.12.0"
- prosemirror-menu "^1.2.4"
- prosemirror-model "^1.19.4"
- prosemirror-schema-basic "^1.2.2"
- prosemirror-schema-list "^1.3.0"
- prosemirror-state "^1.4.3"
- prosemirror-tables "^1.3.5"
- prosemirror-trailing-node "^2.0.7"
- prosemirror-transform "^1.8.0"
- prosemirror-view "^1.32.7"
-
-"@tiptap/starter-kit@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/starter-kit/-/starter-kit-2.4.0.tgz#ad2c2d900af41e55eaaccafa92fd6b2acaebd97e"
- integrity sha512-DYYzMZdTEnRn9oZhKOeRCcB+TjhNz5icLlvJKoHoOGL9kCbuUyEf8WRR2OSPckI0+KUIPJL3oHRqO4SqSdTjfg==
- dependencies:
- "@tiptap/core" "^2.4.0"
- "@tiptap/extension-blockquote" "^2.4.0"
- "@tiptap/extension-bold" "^2.4.0"
- "@tiptap/extension-bullet-list" "^2.4.0"
- "@tiptap/extension-code" "^2.4.0"
- "@tiptap/extension-code-block" "^2.4.0"
- "@tiptap/extension-document" "^2.4.0"
- "@tiptap/extension-dropcursor" "^2.4.0"
- "@tiptap/extension-gapcursor" "^2.4.0"
- "@tiptap/extension-hard-break" "^2.4.0"
- "@tiptap/extension-heading" "^2.4.0"
- "@tiptap/extension-history" "^2.4.0"
- "@tiptap/extension-horizontal-rule" "^2.4.0"
- "@tiptap/extension-italic" "^2.4.0"
- "@tiptap/extension-list-item" "^2.4.0"
- "@tiptap/extension-ordered-list" "^2.4.0"
- "@tiptap/extension-paragraph" "^2.4.0"
- "@tiptap/extension-strike" "^2.4.0"
- "@tiptap/extension-text" "^2.4.0"
-
-"@tiptap/suggestion@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/suggestion/-/suggestion-2.4.0.tgz#1926cde5f197d116baf7794f55bd971245540e5c"
- integrity sha512-6dCkjbL8vIzcLWtS6RCBx0jlYPKf2Beuyq5nNLrDDZZuyJow5qJAY0eGu6Xomp9z0WDK/BYOxT4hHNoGMDkoAg==
-
-"@tiptap/vue-3@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@tiptap/vue-3/-/vue-3-2.4.0.tgz#906dc45167498e88b56b8390aabf658e8f1c2fc4"
- integrity sha512-NCw1Y4ScIrMCKC9YlepUHSAB8jq/PQ2f+AbZKh5bY2t/kMSJYLCJVHq9NFzG4TQtktgMGWCcEQVcDJ7YNpsfxw==
- dependencies:
- "@tiptap/extension-bubble-menu" "^2.4.0"
- "@tiptap/extension-floating-menu" "^2.4.0"
-
-"@ts-morph/common@~0.23.0":
- version "0.23.0"
- resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.23.0.tgz#bd4ddbd3f484f29476c8bd985491592ae5fc147e"
- integrity sha512-m7Lllj9n/S6sOkCkRftpM7L24uvmfXQFedlW/4hENcuJH1HHm9u5EgxZb9uVjQSCGrbBWBkOGgcTxNg36r6ywA==
- dependencies:
- fast-glob "^3.3.2"
- minimatch "^9.0.3"
- mkdirp "^3.0.1"
- path-browserify "^1.0.1"
-
-"@tufjs/canonical-json@2.0.0":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz#a52f61a3d7374833fca945b2549bc30a2dd40d0a"
- integrity sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==
-
-"@tufjs/models@2.0.1":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@tufjs/models/-/models-2.0.1.tgz#e429714e753b6c2469af3212e7f320a6973c2812"
- integrity sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==
- dependencies:
- "@tufjs/canonical-json" "2.0.0"
- minimatch "^9.0.4"
-
-"@types/d3-array@*":
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5"
- integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==
-
-"@types/d3-axis@*":
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.6.tgz#e760e5765b8188b1defa32bc8bb6062f81e4c795"
- integrity sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==
- dependencies:
- "@types/d3-selection" "*"
-
-"@types/d3-brush@*":
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.6.tgz#c2f4362b045d472e1b186cdbec329ba52bdaee6c"
- integrity sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==
- dependencies:
- "@types/d3-selection" "*"
-
-"@types/d3-chord@*":
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.6.tgz#1706ca40cf7ea59a0add8f4456efff8f8775793d"
- integrity sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==
-
-"@types/d3-collection@^1.0.10":
- version "1.0.13"
- resolved "https://registry.yarnpkg.com/@types/d3-collection/-/d3-collection-1.0.13.tgz#4bd051f698515963a9a7c925c04aaf0acd3902f8"
- integrity sha512-v0Rgw3IZebRyamcwVmtTDCZ8OmQcj4siaYjNc7wGMZT7PmdSHawGsCOQMxyLvZ7lWjfohYLK0oXtilMOMgfY8A==
-
-"@types/d3-color@*":
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2"
- integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==
-
-"@types/d3-contour@*":
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.6.tgz#9ada3fa9c4d00e3a5093fed0356c7ab929604231"
- integrity sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==
- dependencies:
- "@types/d3-array" "*"
- "@types/geojson" "*"
-
-"@types/d3-delaunay@*":
- version "6.0.4"
- resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz#185c1a80cc807fdda2a3fe960f7c11c4a27952e1"
- integrity sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==
-
-"@types/d3-dispatch@*":
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz#096efdf55eb97480e3f5621ff9a8da552f0961e7"
- integrity sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==
-
-"@types/d3-drag@*":
- version "3.0.7"
- resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.7.tgz#b13aba8b2442b4068c9a9e6d1d82f8bcea77fc02"
- integrity sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==
- dependencies:
- "@types/d3-selection" "*"
-
-"@types/d3-dsv@*":
- version "3.0.7"
- resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz#0a351f996dc99b37f4fa58b492c2d1c04e3dac17"
- integrity sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==
-
-"@types/d3-ease@*":
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b"
- integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==
-
-"@types/d3-fetch@*":
- version "3.0.7"
- resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz#c04a2b4f23181aa376f30af0283dbc7b3b569980"
- integrity sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==
- dependencies:
- "@types/d3-dsv" "*"
-
-"@types/d3-force@*":
- version "3.0.9"
- resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.9.tgz#dd96ccefba4386fe4ff36b8e4ee4e120c21fcf29"
- integrity sha512-IKtvyFdb4Q0LWna6ymywQsEYjK/94SGhPrMfEr1TIc5OBeziTi+1jcCvttts8e0UWZIxpasjnQk9MNk/3iS+kA==
-
-"@types/d3-format@*":
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.4.tgz#b1e4465644ddb3fdf3a263febb240a6cd616de90"
- integrity sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==
-
-"@types/d3-geo@*":
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440"
- integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==
- dependencies:
- "@types/geojson" "*"
-
-"@types/d3-hierarchy@*":
- version "3.1.7"
- resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz#6023fb3b2d463229f2d680f9ac4b47466f71f17b"
- integrity sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==
-
-"@types/d3-interpolate@*":
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c"
- integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==
- dependencies:
- "@types/d3-color" "*"
-
-"@types/d3-path@*":
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.0.tgz#2b907adce762a78e98828f0b438eaca339ae410a"
- integrity sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==
-
-"@types/d3-path@^1":
- version "1.0.11"
- resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.11.tgz#45420fee2d93387083b34eae4fe6d996edf482bc"
- integrity sha512-4pQMp8ldf7UaB/gR8Fvvy69psNHkTpD/pVw3vmEi8iZAB9EPMBruB1JvHO4BIq9QkUUd2lV1F5YXpMNj7JPBpw==
-
-"@types/d3-polygon@*":
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.2.tgz#dfae54a6d35d19e76ac9565bcb32a8e54693189c"
- integrity sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==
-
-"@types/d3-quadtree@*":
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz#d4740b0fe35b1c58b66e1488f4e7ed02952f570f"
- integrity sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==
-
-"@types/d3-random@*":
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.3.tgz#ed995c71ecb15e0cd31e22d9d5d23942e3300cfb"
- integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==
-
-"@types/d3-sankey@^0.11.2":
- version "0.11.2"
- resolved "https://registry.yarnpkg.com/@types/d3-sankey/-/d3-sankey-0.11.2.tgz#803214b11dc0a17db5d782fe9055cd92b06a5d75"
- integrity sha512-U6SrTWUERSlOhnpSrgvMX64WblX1AxX6nEjI2t3mLK2USpQrnbwYYK+AS9SwiE7wgYmOsSSKoSdr8aoKBH0HgQ==
- dependencies:
- "@types/d3-shape" "^1"
-
-"@types/d3-scale-chromatic@*":
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz#fc0db9c10e789c351f4c42d96f31f2e4df8f5644"
- integrity sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==
-
-"@types/d3-scale@*":
- version "4.0.8"
- resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb"
- integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==
- dependencies:
- "@types/d3-time" "*"
-
-"@types/d3-selection@*":
- version "3.0.10"
- resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.10.tgz#98cdcf986d0986de6912b5892e7c015a95ca27fe"
- integrity sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg==
-
-"@types/d3-shape@*":
- version "3.1.6"
- resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.6.tgz#65d40d5a548f0a023821773e39012805e6e31a72"
- integrity sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==
- dependencies:
- "@types/d3-path" "*"
-
-"@types/d3-shape@^1":
- version "1.3.12"
- resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-1.3.12.tgz#8f2f9f7a12e631ce6700d6d55b84795ce2c8b259"
- integrity sha512-8oMzcd4+poSLGgV0R1Q1rOlx/xdmozS4Xab7np0eamFFUYq71AU9pOCJEFnkXW2aI/oXdVYJzw6pssbSut7Z9Q==
- dependencies:
- "@types/d3-path" "^1"
-
-"@types/d3-time-format@*":
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.3.tgz#d6bc1e6b6a7db69cccfbbdd4c34b70632d9e9db2"
- integrity sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==
-
-"@types/d3-time@*":
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be"
- integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==
-
-"@types/d3-timer@*":
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70"
- integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==
-
-"@types/d3-transition@*":
- version "3.0.8"
- resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.8.tgz#677707f5eed5b24c66a1918cde05963021351a8f"
- integrity sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ==
- dependencies:
- "@types/d3-selection" "*"
-
-"@types/d3-zoom@*":
- version "3.0.8"
- resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz#dccb32d1c56b1e1c6e0f1180d994896f038bc40b"
- integrity sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==
- dependencies:
- "@types/d3-interpolate" "*"
- "@types/d3-selection" "*"
-
-"@types/d3@^7.4.0":
- version "7.4.3"
- resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.3.tgz#d4550a85d08f4978faf0a4c36b848c61eaac07e2"
- integrity sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==
- dependencies:
- "@types/d3-array" "*"
- "@types/d3-axis" "*"
- "@types/d3-brush" "*"
- "@types/d3-chord" "*"
- "@types/d3-color" "*"
- "@types/d3-contour" "*"
- "@types/d3-delaunay" "*"
- "@types/d3-dispatch" "*"
- "@types/d3-drag" "*"
- "@types/d3-dsv" "*"
- "@types/d3-ease" "*"
- "@types/d3-fetch" "*"
- "@types/d3-force" "*"
- "@types/d3-format" "*"
- "@types/d3-geo" "*"
- "@types/d3-hierarchy" "*"
- "@types/d3-interpolate" "*"
- "@types/d3-path" "*"
- "@types/d3-polygon" "*"
- "@types/d3-quadtree" "*"
- "@types/d3-random" "*"
- "@types/d3-scale" "*"
- "@types/d3-scale-chromatic" "*"
- "@types/d3-selection" "*"
- "@types/d3-shape" "*"
- "@types/d3-time" "*"
- "@types/d3-time-format" "*"
- "@types/d3-timer" "*"
- "@types/d3-transition" "*"
- "@types/d3-zoom" "*"
-
-"@types/dagre@^0.7.50":
- version "0.7.52"
- resolved "https://registry.yarnpkg.com/@types/dagre/-/dagre-0.7.52.tgz#edbf0bca6922cd0ad1936a7486f9d03523d7565a"
- integrity sha512-XKJdy+OClLk3hketHi9Qg6gTfe1F3y+UFnHxKA2rn9Dw+oXa4Gb378Ztz9HlMgZKSxpPmn4BNVh9wgkpvrK1uw==
-
-"@types/estree@1.0.6":
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
- integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
-
-"@types/geojson@*", "@types/geojson@^7946.0.10", "@types/geojson@^7946.0.8":
- version "7946.0.14"
- resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613"
- integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==
-
-"@types/leaflet@1.7.6":
- version "1.7.6"
- resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.7.6.tgz#6580f4babb648972c5af3abc3d66866753fa9311"
- integrity sha512-Emkz3V08QnlelSbpT46OEAx+TBZYTOX2r1yM7W+hWg5+djHtQ1GbEXBDRLaqQDOYcDI51Ss0ayoqoKD4CtLUDA==
- dependencies:
- "@types/geojson" "*"
-
-"@types/mapbox__point-geometry@*", "@types/mapbox__point-geometry@^0.1.2":
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz#0ef017b75eedce02ff6243b4189210e2e6d5e56d"
- integrity sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==
-
-"@types/mapbox__vector-tile@^1.3.0":
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/@types/mapbox__vector-tile/-/mapbox__vector-tile-1.3.4.tgz#ad757441ef1d34628d9e098afd9c91423c1f8734"
- integrity sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==
- dependencies:
- "@types/geojson" "*"
- "@types/mapbox__point-geometry" "*"
- "@types/pbf" "*"
-
-"@types/node@*":
- version "20.12.11"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.11.tgz#c4ef00d3507000d17690643278a60dc55a9dc9be"
- integrity sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==
- dependencies:
- undici-types "~5.26.4"
-
-"@types/parse-json@^4.0.0":
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239"
- integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==
-
-"@types/pbf@*", "@types/pbf@^3.0.2":
- version "3.0.5"
- resolved "https://registry.yarnpkg.com/@types/pbf/-/pbf-3.0.5.tgz#a9495a58d8c75be4ffe9a0bd749a307715c07404"
- integrity sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==
-
-"@types/prismjs@^1.9.1":
- version "1.26.5"
- resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.5.tgz#72499abbb4c4ec9982446509d2f14fb8483869d6"
- integrity sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==
-
-"@types/sinonjs__fake-timers@8.1.1":
- version "8.1.1"
- resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3"
- integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==
-
-"@types/sizzle@^2.3.2":
- version "2.3.8"
- resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.8.tgz#518609aefb797da19bf222feb199e8f653ff7627"
- integrity sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==
-
-"@types/supercluster@^5.0.2":
- version "5.0.3"
- resolved "https://registry.yarnpkg.com/@types/supercluster/-/supercluster-5.0.3.tgz#aa03a77c6545265e63b50fa267ab12afe0c27658"
- integrity sha512-XMSqQEr7YDuNtFwSgaHHOjsbi0ZGL62V9Js4CW45RBuRYlNWSW/KDqN+RFFE7HdHcGhJPtN0klKvw06r9Kg7rg==
- dependencies:
- "@types/geojson" "*"
-
-"@types/three@^0.135.0":
- version "0.135.0"
- resolved "https://registry.yarnpkg.com/@types/three/-/three-0.135.0.tgz#db7f9d9699b60aba844fc5b2893adf6dd6811665"
- integrity sha512-l7WLhIHjhHMtlpyTSltPPAKLpiMwgMD1hXHj59AVUpYRoZP7Fd9NNOSRSvZBCPLpTHPYojgQvSJCoza9zoL7bg==
-
-"@types/throttle-debounce@^5.0.0":
- version "5.0.2"
- resolved "https://registry.yarnpkg.com/@types/throttle-debounce/-/throttle-debounce-5.0.2.tgz#3489d91673a4be830c2c9e2acf1f6cdab724102c"
- integrity sha512-pDzSNulqooSKvSNcksnV72nk8p7gRqN8As71Sp28nov1IgmPKWbOEIwAWvBME5pPTtaXJAvG3O4oc76HlQ4kqQ==
-
-"@types/topojson-client@*", "@types/topojson-client@^3.0.0":
- version "3.1.4"
- resolved "https://registry.yarnpkg.com/@types/topojson-client/-/topojson-client-3.1.4.tgz#81b83f9ecd6542dc5c3df21967f992e3fe192c33"
- integrity sha512-Ntf3ZSetMYy7z3PrVCvcqmdRoVhgKA9UKN0ZuuZf8Ts2kcyL4qK34IXBs6qO5fem62EK4k03PtkJPVoroVu4/w==
- dependencies:
- "@types/geojson" "*"
- "@types/topojson-specification" "*"
-
-"@types/topojson-server@*":
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/@types/topojson-server/-/topojson-server-3.0.4.tgz#7a18bfa740d95ad3ce57a68f4e662fa8dc3965ca"
- integrity sha512-5+ieK8ePfP+K2VH6Vgs1VCt+fO1U8XZHj0UsF+NktaF0DavAo1q3IvCBXgokk/xmtvoPltSUs6vxuR/zMdOE1g==
- dependencies:
- "@types/geojson" "*"
- "@types/topojson-specification" "*"
-
-"@types/topojson-simplify@*":
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/@types/topojson-simplify/-/topojson-simplify-3.0.3.tgz#03013bde7b3eb47cac98b74ecb2a739927087415"
- integrity sha512-sBO5UZ0O2dB0bNwo0vut2yLHhj3neUGi9uL7/ROdm8Gs6dtt4jcB9OGDKr+M2isZwQM2RuzVmifnMZpxj4IGNw==
- dependencies:
- "@types/geojson" "*"
- "@types/topojson-specification" "*"
-
-"@types/topojson-specification@*", "@types/topojson-specification@^1.0.2":
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/@types/topojson-specification/-/topojson-specification-1.0.5.tgz#bf0009b2e0debb2d97237b124c00b9ea92570375"
- integrity sha512-C7KvcQh+C2nr6Y2Ub4YfgvWvWCgP2nOQMtfhlnwsRL4pYmmwzBS7HclGiS87eQfDOU/DLQpX6GEscviaz4yLIQ==
- dependencies:
- "@types/geojson" "*"
-
-"@types/topojson@^3.2.3":
- version "3.2.6"
- resolved "https://registry.yarnpkg.com/@types/topojson/-/topojson-3.2.6.tgz#8ca07f8e71b0d6f978bc2b1f0a1c745adc0b52cd"
- integrity sha512-ppfdlxjxofWJ66XdLgIlER/85RvpGyfOf8jrWf+3kVIjEatFxEZYD/Ea83jO672Xu1HRzd/ghwlbcZIUNHTskw==
- dependencies:
- "@types/geojson" "*"
- "@types/topojson-client" "*"
- "@types/topojson-server" "*"
- "@types/topojson-simplify" "*"
- "@types/topojson-specification" "*"
-
-"@types/web-bluetooth@^0.0.20":
- version "0.0.20"
- resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz#f066abfcd1cbe66267cdbbf0de010d8a41b41597"
- integrity sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==
-
-"@types/yauzl@^2.9.1":
- version "2.10.3"
- resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999"
- integrity sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==
- dependencies:
- "@types/node" "*"
-
-"@ungap/structured-clone@^1.2.0":
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
- integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==
-
-"@unovis/dagre-layout@0.8.8-2":
- version "0.8.8-2"
- resolved "https://registry.yarnpkg.com/@unovis/dagre-layout/-/dagre-layout-0.8.8-2.tgz#0a4905dc062398927d11facbe1224da5311e070d"
- integrity sha512-ZfDvfcYtzzhZhgKZty8XDi+zQIotfRqfNVF5M3dFQ9d9C5MTaRdbeBnPUkNrmlLJGgQ42HMOE2ajZLfm2VlRhg==
- dependencies:
- "@unovis/graphlibrary" "^2.2.0-2"
- lodash-es "^4.17.21"
-
-"@unovis/graphlibrary@2.2.0-2", "@unovis/graphlibrary@^2.2.0-2":
- version "2.2.0-2"
- resolved "https://registry.yarnpkg.com/@unovis/graphlibrary/-/graphlibrary-2.2.0-2.tgz#fa18dead78745a94ea21f23aa4eeee95785954d1"
- integrity sha512-HeEzpd/vDyWiIJt0rnh+2ICXUIuF2N0+Z9OJJiKg0DB+eFUcD+bk+9QPhYHwkFwfxdjDA9fHi1DZ/O/bbV58Nw==
- dependencies:
- lodash-es "^4.17.21"
-
-"@unovis/ts@^1.4.4":
- version "1.4.4"
- resolved "https://registry.yarnpkg.com/@unovis/ts/-/ts-1.4.4.tgz#36464fdcb3cf3c9a6e6ffa4f3573500ed1c6e4ec"
- integrity sha512-OoAbCdxSq3tvEKDUDkWNIkPWJ1tnjklWR+8W3zhVqUkOvpqTYW8IjAl+07dPS9/qv+mtjZry5zOt1aBCMPCfdA==
- dependencies:
- "@emotion/css" "^11.7.1"
- "@juggle/resize-observer" "^3.3.1"
- "@types/d3" "^7.4.0"
- "@types/d3-collection" "^1.0.10"
- "@types/d3-sankey" "^0.11.2"
- "@types/dagre" "^0.7.50"
- "@types/geojson" "^7946.0.8"
- "@types/leaflet" "1.7.6"
- "@types/supercluster" "^5.0.2"
- "@types/three" "^0.135.0"
- "@types/throttle-debounce" "^5.0.0"
- "@types/topojson" "^3.2.3"
- "@types/topojson-client" "^3.0.0"
- "@types/topojson-specification" "^1.0.2"
- "@unovis/dagre-layout" "0.8.8-2"
- "@unovis/graphlibrary" "2.2.0-2"
- d3 "^7.2.1"
- d3-collection "^1.0.7"
- d3-geo-projection "^4.0.0"
- d3-interpolate-path "^2.2.3"
- d3-sankey "^0.12.3"
- elkjs "^0.8.2"
- geojson "^0.5.0"
- leaflet "1.7.1"
- maplibre-gl "^2.1.9"
- striptags "^3.2.0"
- supercluster "^7.1.5"
- three "^0.135.0"
- throttle-debounce "^5.0.0"
- to-px "^1.1.0"
- topojson-client "^3.1.0"
- tslib "^2.3.1"
-
-"@unovis/vue@^1.4.4":
- version "1.4.4"
- resolved "https://registry.yarnpkg.com/@unovis/vue/-/vue-1.4.4.tgz#836396fdc3f92ee08c1e68f0862d4ad8557f08bd"
- integrity sha512-19xdi/0+18NzUyRh4sK0GCIv5JbqSMSEqXaMio4Vya8I/8JYU0Sgyo4jwr+O60Rl8fSOXScL9NJQHxPHJeTcMg==
-
-"@vee-validate/zod@^4.13.2":
- version "4.13.2"
- resolved "https://registry.yarnpkg.com/@vee-validate/zod/-/zod-4.13.2.tgz#8798762aedd1b9e481ab4c5baa36aa6a2c6acf87"
- integrity sha512-y1aqelutD6btX2ayZk3w8udClAykptphlGLwu0vlCqY2r9mrJqMn1EKqtcwXAvEom+ceTcHJOwGr2FUA7i+ZEg==
- dependencies:
- type-fest "^4.8.3"
- vee-validate "4.13.2"
- zod "^3.22.4"
-
-"@vitejs/plugin-vue@^5.0.3":
- version "5.0.4"
- resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz#508d6a0f2440f86945835d903fcc0d95d1bb8a37"
- integrity sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==
-
-"@vue/compiler-core@3.4.31", "@vue/compiler-core@^3.0.0":
- version "3.4.31"
- resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.4.31.tgz#b51a76f1b30e9b5eba0553264dff0f171aedb7c6"
- integrity sha512-skOiodXWTV3DxfDhB4rOf3OGalpITLlgCeOwb+Y9GJpfQ8ErigdBUHomBzvG78JoVE8MJoQsb+qhZiHfKeNeEg==
- dependencies:
- "@babel/parser" "^7.24.7"
- "@vue/shared" "3.4.31"
- entities "^4.5.0"
- estree-walker "^2.0.2"
- source-map-js "^1.2.0"
-
-"@vue/compiler-core@3.4.37":
- version "3.4.37"
- resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.4.37.tgz#55db3900e09424c65c39111a05a3c6e698f371e3"
- integrity sha512-ZDDT/KiLKuCRXyzWecNzC5vTcubGz4LECAtfGPENpo0nrmqJHwuWtRLxk/Sb9RAKtR9iFflFycbkjkY+W/PZUQ==
- dependencies:
- "@babel/parser" "^7.24.7"
- "@vue/shared" "3.4.37"
- entities "^5.0.0"
- estree-walker "^2.0.2"
- source-map-js "^1.2.0"
-
-"@vue/compiler-dom@3.4.31", "@vue/compiler-dom@^3.4.27":
- version "3.4.31"
- resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.31.tgz#30961ca847f5d6ad18ffa26236c219f61b195f6b"
- integrity sha512-wK424WMXsG1IGMyDGyLqB+TbmEBFM78hIsOJ9QwUVLGrcSk0ak6zYty7Pj8ftm7nEtdU/DGQxAXp0/lM/2cEpQ==
- dependencies:
- "@vue/compiler-core" "3.4.31"
- "@vue/shared" "3.4.31"
-
-"@vue/compiler-dom@3.4.37":
- version "3.4.37"
- resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.37.tgz#a1fcf79e287cb828545082ff1afa8630480a3044"
- integrity sha512-rIiSmL3YrntvgYV84rekAtU/xfogMUJIclUMeIKEtVBFngOL3IeZHhsH3UaFEgB5iFGpj6IW+8YuM/2Up+vVag==
- dependencies:
- "@vue/compiler-core" "3.4.37"
- "@vue/shared" "3.4.37"
-
-"@vue/compiler-sfc@3.4.37":
- version "3.4.37"
- resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.37.tgz#8afaf1a86cb849422c765d4369ba1e85fffe0234"
- integrity sha512-vCfetdas40Wk9aK/WWf8XcVESffsbNkBQwS5t13Y/PcfqKfIwJX2gF+82th6dOpnpbptNMlMjAny80li7TaCIg==
- dependencies:
- "@babel/parser" "^7.24.7"
- "@vue/compiler-core" "3.4.37"
- "@vue/compiler-dom" "3.4.37"
- "@vue/compiler-ssr" "3.4.37"
- "@vue/shared" "3.4.37"
- estree-walker "^2.0.2"
- magic-string "^0.30.10"
- postcss "^8.4.40"
- source-map-js "^1.2.0"
-
-"@vue/compiler-sfc@^3.4", "@vue/compiler-sfc@^3.4.27":
- version "3.4.31"
- resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.31.tgz#cc6bfccda17df8268cc5440842277f61623c591f"
- integrity sha512-einJxqEw8IIJxzmnxmJBuK2usI+lJonl53foq+9etB2HAzlPjAS/wa7r0uUpXw5ByX3/0uswVSrjNb17vJm1kQ==
- dependencies:
- "@babel/parser" "^7.24.7"
- "@vue/compiler-core" "3.4.31"
- "@vue/compiler-dom" "3.4.31"
- "@vue/compiler-ssr" "3.4.31"
- "@vue/shared" "3.4.31"
- estree-walker "^2.0.2"
- magic-string "^0.30.10"
- postcss "^8.4.38"
- source-map-js "^1.2.0"
-
-"@vue/compiler-ssr@3.4.31":
- version "3.4.31"
- resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.4.31.tgz#f62ffecdf15bacb883d0099780cf9a1e3654bfc4"
- integrity sha512-RtefmITAje3fJ8FSg1gwgDhdKhZVntIVbwupdyZDSifZTRMiWxWehAOTCc8/KZDnBOcYQ4/9VWxsTbd3wT0hAA==
- dependencies:
- "@vue/compiler-dom" "3.4.31"
- "@vue/shared" "3.4.31"
-
-"@vue/compiler-ssr@3.4.37":
- version "3.4.37"
- resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.4.37.tgz#b75e1c76c3184f86fa9f0ba4d61d13bc6afcbf8a"
- integrity sha512-TyAgYBWrHlFrt4qpdACh8e9Ms6C/AZQ6A6xLJaWrCL8GCX5DxMzxyeFAEMfU/VFr4tylHm+a2NpfJpcd7+20XA==
- dependencies:
- "@vue/compiler-dom" "3.4.37"
- "@vue/shared" "3.4.37"
-
-"@vue/devtools-api@^6.5.0", "@vue/devtools-api@^6.5.1":
- version "6.6.1"
- resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.1.tgz#7c14346383751d9f6ad4bea0963245b30220ef83"
- integrity sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==
-
-"@vue/devtools-api@^6.6.1":
- version "6.6.3"
- resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.3.tgz#b23a588154cba8986bba82b6e1d0248bde3fd1a0"
- integrity sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw==
-
-"@vue/eslint-config-prettier@^8.0.0":
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/@vue/eslint-config-prettier/-/eslint-config-prettier-8.0.0.tgz#de5cb77ed483b43683d17a788808a0fa4e7bd07e"
- integrity sha512-55dPqtC4PM/yBjhAr+yEw6+7KzzdkBuLmnhBrDfp4I48+wy+Giqqj9yUr5T2uD/BkBROjjmqnLZmXRdOx/VtQg==
- dependencies:
- eslint-config-prettier "^8.8.0"
- eslint-plugin-prettier "^5.0.0"
-
-"@vue/reactivity@3.4.27", "@vue/reactivity@^3.4.15":
- version "3.4.27"
- resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.4.27.tgz#6ece72331bf719953f5eaa95ec60b2b8d49e3791"
- integrity sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==
- dependencies:
- "@vue/shared" "3.4.27"
-
-"@vue/reactivity@3.4.37":
- version "3.4.37"
- resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.4.37.tgz#5a199563eaab51ed9f94ddf0a82f9179bcc01676"
- integrity sha512-UmdKXGx0BZ5kkxPqQr3PK3tElz6adTey4307NzZ3whZu19i5VavYal7u2FfOmAzlcDVgE8+X0HZ2LxLb/jgbYw==
- dependencies:
- "@vue/shared" "3.4.37"
-
-"@vue/runtime-core@3.4.37":
- version "3.4.37"
- resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.4.37.tgz#3fe734a666db7842bea4185a13f7697a2102b719"
- integrity sha512-MNjrVoLV/sirHZoD7QAilU1Ifs7m/KJv4/84QVbE6nyAZGQNVOa1HGxaOzp9YqCG+GpLt1hNDC4RbH+KtanV7w==
- dependencies:
- "@vue/reactivity" "3.4.37"
- "@vue/shared" "3.4.37"
-
-"@vue/runtime-core@^3.4.15":
- version "3.4.27"
- resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.4.27.tgz#1b6e1d71e4604ba7442dd25ed22e4a1fc6adbbda"
- integrity sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==
- dependencies:
- "@vue/reactivity" "3.4.27"
- "@vue/shared" "3.4.27"
-
-"@vue/runtime-dom@3.4.37":
- version "3.4.37"
- resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.4.37.tgz#219f84577027103de6ddc71351d8237c7c16adac"
- integrity sha512-Mg2EwgGZqtwKrqdL/FKMF2NEaOHuH+Ks9TQn3DHKyX//hQTYOun+7Tqp1eo0P4Ds+SjltZshOSRq6VsU0baaNg==
- dependencies:
- "@vue/reactivity" "3.4.37"
- "@vue/runtime-core" "3.4.37"
- "@vue/shared" "3.4.37"
- csstype "^3.1.3"
-
-"@vue/server-renderer@3.4.37":
- version "3.4.37"
- resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.4.37.tgz#d341425bb5395a3f6ed70572ea5c3edefab92f28"
- integrity sha512-jZ5FAHDR2KBq2FsRUJW6GKDOAG9lUTX8aBEGq4Vf6B/35I9fPce66BornuwmqmKgfiSlecwuOb6oeoamYMohkg==
- dependencies:
- "@vue/compiler-ssr" "3.4.37"
- "@vue/shared" "3.4.37"
-
-"@vue/shared@3.4.27":
- version "3.4.27"
- resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.27.tgz#f05e3cd107d157354bb4ae7a7b5fc9cf73c63b50"
- integrity sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==
-
-"@vue/shared@3.4.31":
- version "3.4.31"
- resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.31.tgz#af9981f57def2c3f080c14bf219314fc0dc808a0"
- integrity sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==
-
-"@vue/shared@3.4.37":
- version "3.4.37"
- resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.37.tgz#4f4c08a2e73da512a77b47165cf59ffbc1b5ade8"
- integrity sha512-nIh8P2fc3DflG8+5Uw8PT/1i17ccFn0xxN/5oE9RfV5SVnd7G0XEFRwakrnNFE/jlS95fpGXDVG5zDETS26nmg==
-
-"@vuedx/template-ast-types@0.7.1":
- version "0.7.1"
- resolved "https://registry.yarnpkg.com/@vuedx/template-ast-types/-/template-ast-types-0.7.1.tgz#ccc75786a4fe1d1910f6c8d93d150d44ee1dabdc"
- integrity sha512-Mqugk/F0lFN2u9bhimH6G1kSu2hhLi2WoqgCVxrMvgxm2kDc30DtdvVGRq+UgEmKVP61OudcMtZqkUoGQeFBUQ==
- dependencies:
- "@vue/compiler-core" "^3.0.0"
-
-"@vueup/vue-quill@^1.2.0":
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/@vueup/vue-quill/-/vue-quill-1.2.0.tgz#cd0d93559256d069f639723dd91c044e8162c72a"
- integrity sha512-kd5QPSHMDpycklojPXno2Kw2JSiKMYduKYQckTm1RJoVDA557MnyUXgcuuDpry4HY/Rny9nGNcK+m3AHk94wag==
- dependencies:
- quill "^1.3.7"
- quill-delta "^4.2.2"
-
-"@vueuse/core@^10.11.0":
- version "10.11.1"
- resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.11.1.tgz#15d2c0b6448d2212235b23a7ba29c27173e0c2c6"
- integrity sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==
- dependencies:
- "@types/web-bluetooth" "^0.0.20"
- "@vueuse/metadata" "10.11.1"
- "@vueuse/shared" "10.11.1"
- vue-demi ">=0.14.8"
-
-"@vueuse/core@^10.5.0":
- version "10.9.0"
- resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.9.0.tgz#7d779a95cf0189de176fee63cee4ba44b3c85d64"
- integrity sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==
- dependencies:
- "@types/web-bluetooth" "^0.0.20"
- "@vueuse/metadata" "10.9.0"
- "@vueuse/shared" "10.9.0"
- vue-demi ">=0.14.7"
-
-"@vueuse/core@^11.2.0":
- version "11.2.0"
- resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-11.2.0.tgz#3fc6c0963051bb154dc4c08061889405e3fc745d"
- integrity sha512-JIUwRcOqOWzcdu1dGlfW04kaJhW3EXnnjJJfLTtddJanymTL7lF1C0+dVVZ/siLfc73mWn+cGP1PE1PKPruRSA==
- dependencies:
- "@types/web-bluetooth" "^0.0.20"
- "@vueuse/metadata" "11.2.0"
- "@vueuse/shared" "11.2.0"
- vue-demi ">=0.14.10"
-
-"@vueuse/metadata@10.11.1":
- version "10.11.1"
- resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-10.11.1.tgz#209db7bb5915aa172a87510b6de2ca01cadbd2a7"
- integrity sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==
-
-"@vueuse/metadata@10.9.0":
- version "10.9.0"
- resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-10.9.0.tgz#769a1a9db65daac15cf98084cbf7819ed3758620"
- integrity sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==
-
-"@vueuse/metadata@11.2.0":
- version "11.2.0"
- resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-11.2.0.tgz#fd02cbbc7d08cb4592fceea0486559b89ae38643"
- integrity sha512-L0ZmtRmNx+ZW95DmrgD6vn484gSpVeRbgpWevFKXwqqQxW9hnSi2Ppuh2BzMjnbv4aJRiIw8tQatXT9uOB23dQ==
-
-"@vueuse/shared@10.11.1", "@vueuse/shared@^10.11.0":
- version "10.11.1"
- resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.11.1.tgz#62b84e3118ae6e1f3ff38f4fbe71b0c5d0f10938"
- integrity sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==
- dependencies:
- vue-demi ">=0.14.8"
-
-"@vueuse/shared@10.9.0", "@vueuse/shared@^10.5.0":
- version "10.9.0"
- resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.9.0.tgz#13af2a348de15d07b7be2fd0c7fc9853a69d8fe0"
- integrity sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==
- dependencies:
- vue-demi ">=0.14.7"
-
-"@vueuse/shared@11.2.0":
- version "11.2.0"
- resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-11.2.0.tgz#7fb2f3cade6b6c00ef97e613f187ee9bdcfb9a3a"
- integrity sha512-VxFjie0EanOudYSgMErxXfq6fo8vhr5ICI+BuE3I9FnX7ePllEsVrRQ7O6Q1TLgApeLuPKcHQxAXpP+KnlrJsg==
- dependencies:
- vue-demi ">=0.14.10"
-
-"@withtypes/mime@^0.1.2":
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/@withtypes/mime/-/mime-0.1.2.tgz#956883251b0786f2c898ed76a23594ea6d9939e0"
- integrity sha512-PB9BfZGzwblUONJY0LiOwsHCA6uV3DIPj/w9ReekdHxPOl0VdUFgI5s4avKycuuq9Gf5Nz2ZPA2O36GAUzlMPA==
- dependencies:
- mime "^3.0.0"
-
-JSONStream@~1.3.1:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
- integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==
- dependencies:
- jsonparse "^1.2.0"
- through ">=2.2.7 <3"
-
-abbrev@1, abbrev@~1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
- integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
-
-abbrev@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf"
- integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==
-
-acorn-jsx@^5.3.2:
- version "5.3.2"
- resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
- integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
-
-acorn@^8.11.3:
- version "8.12.1"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248"
- integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==
-
-acorn@^8.9.0:
- version "8.11.3"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
- integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
-
-add@^2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/add/-/add-2.0.6.tgz#248f0a9f6e5a528ef2295dbeec30532130ae2235"
- integrity sha512-j5QzrmsokwWWp6kUcJQySpbG+xfOBqqKnup3OIk1pz+kB/80SLorZ9V8zHFLO92Lcd+hbvq8bT+zOGoPkmBV0Q==
-
-agent-base@4, agent-base@^4.1.0, agent-base@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
- integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
- dependencies:
- es6-promisify "^5.0.0"
-
-agent-base@^7.0.2, agent-base@^7.1.0, agent-base@^7.1.1:
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317"
- integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==
- dependencies:
- debug "^4.3.4"
-
-agentkeepalive@^3.3.0:
- version "3.5.3"
- resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.3.tgz#c210afce942b4287e2df2fbfe6c0d57eda2ce634"
- integrity sha512-yqXL+k5rr8+ZRpOAntkaaRgWgE5o8ESAj5DyRmVTCSoZxXmqemb9Dd7T4i5UzwuERdLAJUy6XzR9zFVuf0kzkw==
- dependencies:
- humanize-ms "^1.2.1"
-
-aggregate-error@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
- integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
- dependencies:
- clean-stack "^2.0.0"
- indent-string "^4.0.0"
-
-ajv@^4.9.1:
- version "4.11.8"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
- integrity sha512-I/bSHSNEcFFqXLf91nchoNB9D1Kie3QKcWdchYUaoIg1+1bdWDkdfdlvdIOJbi9U8xR0y+MWc5D+won9v95WlQ==
- dependencies:
- co "^4.6.0"
- json-stable-stringify "^1.0.1"
-
-ajv@^6.12.3, ajv@^6.12.4:
- version "6.12.6"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
- integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
- dependencies:
- fast-deep-equal "^3.1.1"
- fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.4.1"
- uri-js "^4.2.2"
-
-ansi-align@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f"
- integrity sha512-TdlOggdA/zURfMYa7ABC66j+oqfMew58KpJMbUlH3bcZP1b+cBHIHDDn5uH9INsxrHBPjsqM0tDB4jPTF/vgJA==
- dependencies:
- string-width "^2.0.0"
-
-ansi-colors@^4.1.1:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b"
- integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==
-
-ansi-escapes@^4.3.0:
- version "4.3.2"
- resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
- integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
- dependencies:
- type-fest "^0.21.3"
-
-ansi-regex@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
- integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==
-
-ansi-regex@^3.0.0, ansi-regex@~3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1"
- integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==
-
-ansi-regex@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
- integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
-
-ansi-regex@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
- integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
-
-ansi-styles@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
- integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==
-
-ansi-styles@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
- integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
- dependencies:
- color-convert "^1.9.0"
-
-ansi-styles@^4.0.0, ansi-styles@^4.1.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
- integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
- dependencies:
- color-convert "^2.0.1"
-
-ansi-styles@^6.1.0:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
- integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
-
-ansicolors@~0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979"
- integrity sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==
-
-ansistyles@~0.1.3:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539"
- integrity sha512-6QWEyvMgIXX0eO972y7YPBLSBsq7UWKFAoNNTLGaOJ9bstcEL9sCbcjf96dVfNDdUsRoGOK82vWFJlKApXds7g==
-
-any-promise@^1.0.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
- integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
-
-anymatch@~3.1.2:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
- integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
- dependencies:
- normalize-path "^3.0.0"
- picomatch "^2.0.4"
-
-aproba@^1.0.3, aproba@^1.1.1:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
- integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
-
-aproba@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc"
- integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==
-
-aproba@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1"
- integrity sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==
-
-arch@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11"
- integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==
-
-archy@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
- integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==
-
-are-we-there-yet@~1.1.2:
- version "1.1.7"
- resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146"
- integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==
- dependencies:
- delegates "^1.0.0"
- readable-stream "^2.0.6"
-
-arg@^5.0.2:
- version "5.0.2"
- resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
- integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
-
-argparse@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
- integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
-
-aria-hidden@^1.2.3, aria-hidden@^1.2.4:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522"
- integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==
- dependencies:
- tslib "^2.0.0"
-
-asap@^2.0.0:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
- integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
-
-asn1@~0.2.3:
- version "0.2.6"
- resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d"
- integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==
- dependencies:
- safer-buffer "~2.1.0"
-
-assert-plus@1.0.0, assert-plus@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
- integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==
-
-assert-plus@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
- integrity sha512-u1L0ZLywRziOVjUhRxI0Qg9G+4RnFB9H/Rq40YWn0dieDgO7vAYeJz6jKAO6t/aruzlDFLAPkQTT87e+f8Imaw==
-
-astral-regex@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
- integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
-
-async@^3.2.0:
- version "3.2.5"
- resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66"
- integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==
-
-asynckit@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
- integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
-
-at-least-node@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
- integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
-
-autoprefixer@latest:
- version "10.4.19"
- resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.19.tgz#ad25a856e82ee9d7898c59583c1afeb3fa65f89f"
- integrity sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==
- dependencies:
- browserslist "^4.23.0"
- caniuse-lite "^1.0.30001599"
- fraction.js "^4.3.7"
- normalize-range "^0.1.2"
- picocolors "^1.0.0"
- postcss-value-parser "^4.2.0"
-
-aws-sign2@~0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
- integrity sha512-JnJpAS0p9RmixkOvW2XwDxxzs1bd4/VAGIl6Q0EC5YOo+p+hqIhtDhn/nmFnB/xUNXbLkpE2mOjgVIBRKD4xYw==
-
-aws-sign2@~0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
- integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==
-
-aws4@^1.2.1:
- version "1.13.0"
- resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.0.tgz#d9b802e9bb9c248d7be5f7f5ef178dc3684e9dcc"
- integrity sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==
-
-aws4@^1.8.0:
- version "1.12.0"
- resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3"
- integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==
-
-axios@^1.6.1:
- version "1.6.8"
- resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66"
- integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==
- dependencies:
- follow-redirects "^1.15.6"
- form-data "^4.0.0"
- proxy-from-env "^1.1.0"
-
-babel-plugin-macros@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1"
- integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
- dependencies:
- "@babel/runtime" "^7.12.5"
- cosmiconfig "^7.0.0"
- resolve "^1.19.0"
-
-balanced-match@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
- integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-
-base64-js@^1.3.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
- integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
-
-bcrypt-pbkdf@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
- integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==
- dependencies:
- tweetnacl "^0.14.3"
-
-bin-links@^4.0.1:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.4.tgz#c3565832b8e287c85f109a02a17027d152a58a63"
- integrity sha512-cMtq4W5ZsEwcutJrVId+a/tjt8GSbS+h0oNkdl6+6rBuEv8Ot33Bevj5KPm40t309zuhVic8NjpuL42QCiJWWA==
- dependencies:
- cmd-shim "^6.0.0"
- npm-normalize-package-bin "^3.0.0"
- read-cmd-shim "^4.0.0"
- write-file-atomic "^5.0.0"
-
-binary-extensions@^2.0.0, binary-extensions@^2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
- integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
-
-bl@^1.0.0:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7"
- integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==
- dependencies:
- readable-stream "^2.3.5"
- safe-buffer "^5.1.1"
-
-blob-util@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb"
- integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==
-
-block-stream@*:
- version "0.0.9"
- resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
- integrity sha512-OorbnJVPII4DuUKbjARAe8u8EfqOmkEEaSFIyoQ7OjTHn6kafxWl0wLgoZ2rXaYd7MyLcDaU4TmhfxtwgcccMQ==
- dependencies:
- inherits "~2.0.0"
-
-bluebird@3.7.2, bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.7.2:
- version "3.7.2"
- resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
- integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
-
-bluebird@~3.5.0:
- version "3.5.5"
- resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
- integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
-
-boolbase@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
- integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
-
-boom@2.x.x:
- version "2.10.1"
- resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
- integrity sha512-KbiZEa9/vofNcVJXGwdWWn25reQ3V3dHBWbS07FTF3/TOehLnm9GEhJV4T6ZvGPkShRpmUqYwnaCrkj0mRnP6Q==
- dependencies:
- hoek "2.x.x"
-
-boxen@^1.0.0, boxen@^1.2.1:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
- integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==
- dependencies:
- ansi-align "^2.0.0"
- camelcase "^4.0.0"
- chalk "^2.0.1"
- cli-boxes "^1.0.0"
- string-width "^2.0.0"
- term-size "^1.2.0"
- widest-line "^2.0.0"
-
-brace-expansion@^1.1.7:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
- integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
- dependencies:
- balanced-match "^1.0.0"
- concat-map "0.0.1"
-
-brace-expansion@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
- integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
- dependencies:
- balanced-match "^1.0.0"
-
-braces@^3.0.2, braces@~3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
- integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
- dependencies:
- fill-range "^7.0.1"
-
-browserslist@^4.22.2:
- version "4.23.1"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.1.tgz#ce4af0534b3d37db5c1a4ca98b9080f985041e96"
- integrity sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==
- dependencies:
- caniuse-lite "^1.0.30001629"
- electron-to-chromium "^1.4.796"
- node-releases "^2.0.14"
- update-browserslist-db "^1.0.16"
-
-browserslist@^4.23.0:
- version "4.23.0"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab"
- integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==
- dependencies:
- caniuse-lite "^1.0.30001587"
- electron-to-chromium "^1.4.668"
- node-releases "^2.0.14"
- update-browserslist-db "^1.0.13"
-
-buffer-alloc-unsafe@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
- integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
-
-buffer-alloc@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
- integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
- dependencies:
- buffer-alloc-unsafe "^1.1.0"
- buffer-fill "^1.0.0"
-
-buffer-crc32@~0.2.3:
- version "0.2.13"
- resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
- integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
-
-buffer-fill@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
- integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==
-
-buffer-from@^1.0.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
- integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
-
-buffer@^5.7.1:
- version "5.7.1"
- resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
- integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
- dependencies:
- base64-js "^1.3.1"
- ieee754 "^1.1.13"
-
-builtin-modules@^1.0.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
- integrity sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==
-
-builtins@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
- integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==
-
-c12@^1.10.0:
- version "1.11.1"
- resolved "https://registry.yarnpkg.com/c12/-/c12-1.11.1.tgz#d5244e95407af450a523e44eb57e5b87b82f8677"
- integrity sha512-KDU0TvSvVdaYcQKQ6iPHATGz/7p/KiVjPg4vQrB6Jg/wX9R0yl5RZxWm9IoZqaIHD2+6PZd81+KMGwRr/lRIUg==
- dependencies:
- chokidar "^3.6.0"
- confbox "^0.1.7"
- defu "^6.1.4"
- dotenv "^16.4.5"
- giget "^1.2.3"
- jiti "^1.21.6"
- mlly "^1.7.1"
- ohash "^1.1.3"
- pathe "^1.1.2"
- perfect-debounce "^1.0.0"
- pkg-types "^1.1.1"
- rc9 "^2.1.2"
-
-cacache@^10.0.0:
- version "10.0.4"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460"
- integrity sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==
- dependencies:
- bluebird "^3.5.1"
- chownr "^1.0.1"
- glob "^7.1.2"
- graceful-fs "^4.1.11"
- lru-cache "^4.1.1"
- mississippi "^2.0.0"
- mkdirp "^0.5.1"
- move-concurrently "^1.0.1"
- promise-inflight "^1.0.1"
- rimraf "^2.6.2"
- ssri "^5.2.4"
- unique-filename "^1.1.0"
- y18n "^4.0.0"
-
-cacache@^18.0.0, cacache@^18.0.2:
- version "18.0.3"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.3.tgz#864e2c18414e1e141ae8763f31e46c2cb96d1b21"
- integrity sha512-qXCd4rh6I07cnDqh8V48/94Tc/WSfj+o3Gn6NZ0aZovS255bUx8O13uKxRFd2eWG0xgsco7+YItQNPaa5E85hg==
- dependencies:
- "@npmcli/fs" "^3.1.0"
- fs-minipass "^3.0.0"
- glob "^10.2.2"
- lru-cache "^10.0.1"
- minipass "^7.0.3"
- minipass-collect "^2.0.1"
- minipass-flush "^1.0.5"
- minipass-pipeline "^1.2.4"
- p-map "^4.0.0"
- ssri "^10.0.0"
- tar "^6.1.11"
- unique-filename "^3.0.0"
-
-cacache@^9.2.9:
- version "9.3.0"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-9.3.0.tgz#9cd58f2dd0b8c8cacf685b7067b416d6d3cf9db1"
- integrity sha512-Vbi8J1XfC8v+FbQ6QkOtKXsHpPnB0i9uMeYFJoj40EbdOsEqWB3DPpNjfsnYBkqOPYA8UvrqH6FZPpBP0zdN7g==
- dependencies:
- bluebird "^3.5.0"
- chownr "^1.0.1"
- glob "^7.1.2"
- graceful-fs "^4.1.11"
- lru-cache "^4.1.1"
- mississippi "^1.3.0"
- mkdirp "^0.5.1"
- move-concurrently "^1.0.1"
- promise-inflight "^1.0.1"
- rimraf "^2.6.1"
- ssri "^4.1.6"
- unique-filename "^1.1.0"
- y18n "^3.2.1"
-
-cacache@~9.2.9:
- version "9.2.9"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-9.2.9.tgz#f9d7ffe039851ec94c28290662afa4dd4bb9e8dd"
- integrity sha512-ghg1j5OyTJ6qsrqU++dN23QiTDxb5AZCFGsF3oB+v9v/gY+F4X8L/0gdQMEjd+8Ot3D29M2etX5PKozHRn2JQw==
- dependencies:
- bluebird "^3.5.0"
- chownr "^1.0.1"
- glob "^7.1.2"
- graceful-fs "^4.1.11"
- lru-cache "^4.1.1"
- mississippi "^1.3.0"
- mkdirp "^0.5.1"
- move-concurrently "^1.0.1"
- promise-inflight "^1.0.1"
- rimraf "^2.6.1"
- ssri "^4.1.6"
- unique-filename "^1.1.0"
- y18n "^3.2.1"
-
-cachedir@^2.3.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.4.0.tgz#7fef9cf7367233d7c88068fe6e34ed0d355a610d"
- integrity sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==
-
-call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.7:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9"
- integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==
- dependencies:
- es-define-property "^1.0.0"
- es-errors "^1.3.0"
- function-bind "^1.1.2"
- get-intrinsic "^1.2.4"
- set-function-length "^1.2.1"
-
-call-limit@~1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/call-limit/-/call-limit-1.1.1.tgz#ef15f2670db3f1992557e2d965abc459e6e358d4"
- integrity sha512-5twvci5b9eRBw2wCfPtN0GmlR2/gadZqyFpPhOK6CvMFoFgA+USnZ6Jpu1lhG9h85pQ3Ouil3PfXWRD4EUaRiQ==
-
-callsites@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
- integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
-
-camelcase-css@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
- integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
-
-camelcase@^4.0.0, camelcase@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
- integrity sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==
-
-caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001599:
- version "1.0.30001617"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001617.tgz#809bc25f3f5027ceb33142a7d6c40759d7a901eb"
- integrity sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA==
-
-caniuse-lite@^1.0.30001629:
- version "1.0.30001640"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz#32c467d4bf1f1a0faa63fc793c2ba81169e7652f"
- integrity sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==
-
-capture-stack-trace@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.2.tgz#1c43f6b059d4249e7f3f8724f15f048b927d3a8a"
- integrity sha512-X/WM2UQs6VMHUtjUDnZTRI+i1crWteJySFzr9UpGoQa4WQffXVTTXuekjl7TjZRlcF2XfjgITT0HxZ9RnxeT0w==
-
-caseless@~0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
- integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==
-
-chalk@^1.0.0:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
- integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==
- dependencies:
- ansi-styles "^2.2.1"
- escape-string-regexp "^1.0.2"
- has-ansi "^2.0.0"
- strip-ansi "^3.0.0"
- supports-color "^2.0.0"
-
-chalk@^2.0.1, chalk@^2.4.2:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
- integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
-chalk@^4.0.0, chalk@^4.1.0:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
- integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
- dependencies:
- ansi-styles "^4.1.0"
- supports-color "^7.1.0"
-
-chalk@^5.3.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385"
- integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==
-
-check-more-types@2.24.0, check-more-types@^2.24.0:
- version "2.24.0"
- resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600"
- integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==
-
-"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3, chokidar@^3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
- integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
- dependencies:
- anymatch "~3.1.2"
- braces "~3.0.2"
- glob-parent "~5.1.2"
- is-binary-path "~2.1.0"
- is-glob "~4.0.1"
- normalize-path "~3.0.0"
- readdirp "~3.6.0"
- optionalDependencies:
- fsevents "~2.3.2"
-
-chownr@^1.0.1:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
- integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
-
-chownr@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
- integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
-
-chownr@~1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181"
- integrity sha512-cKnqUJAC8G6cuN1DiRRTifu+s1BlAQNtalzGphFEV0pl0p46dsxJD4l1AOlyKJeLZOFzo3c34R7F3djxaCu8Kw==
-
-ci-info@^1.5.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
- integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
-
-ci-info@^3.2.0:
- version "3.9.0"
- resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4"
- integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==
-
-ci-info@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.0.0.tgz#65466f8b280fc019b9f50a5388115d17a63a44f2"
- integrity sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==
-
-cidr-regex@^4.0.4:
- version "4.0.5"
- resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-4.0.5.tgz#c90181992feb60ce28b8cc7590970ab94ab1060a"
- integrity sha512-gljhROSwEnEvC+2lKqfkv1dU2v46h8Cwob19LlfGeGRMDLuwFD5+3D6+/vaa9/QrVLDASiSQ2OYQwzzjQ5I57A==
- dependencies:
- ip-regex "^5.0.0"
-
-citty@^0.1.6:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/citty/-/citty-0.1.6.tgz#0f7904da1ed4625e1a9ea7e0fa780981aab7c5e4"
- integrity sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==
- dependencies:
- consola "^3.2.3"
-
-class-variance-authority@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.0.tgz#1c3134d634d80271b1837452b06d821915954522"
- integrity sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==
- dependencies:
- clsx "2.0.0"
-
-clean-stack@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
- integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
-
-cli-boxes@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
- integrity sha512-3Fo5wu8Ytle8q9iCzS4D2MWVL2X7JVWRiS1BnXbTFDhS9c/REkM9vd1AmabsoZoY5/dGi5TT9iKL8Kb6DeBRQg==
-
-cli-columns@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-4.0.0.tgz#9fe4d65975238d55218c41bd2ed296a7fa555646"
- integrity sha512-XW2Vg+w+L9on9wtwKpyzluIPCWXjaBahI7mTcYjx+BVIYD9c3yqcv/yKC7CmdCZat4rq2yiE1UMSJC5ivKfMtQ==
- dependencies:
- string-width "^4.2.3"
- strip-ansi "^6.0.1"
-
-cli-cursor@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
- integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
- dependencies:
- restore-cursor "^3.1.0"
-
-cli-cursor@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea"
- integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==
- dependencies:
- restore-cursor "^4.0.0"
-
-cli-spinners@^2.9.2:
- version "2.9.2"
- resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41"
- integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==
-
-cli-table3@~0.6.1:
- version "0.6.5"
- resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f"
- integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==
- dependencies:
- string-width "^4.2.0"
- optionalDependencies:
- "@colors/colors" "1.5.0"
-
-cli-truncate@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7"
- integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==
- dependencies:
- slice-ansi "^3.0.0"
- string-width "^4.2.0"
-
-cliui@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
- integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==
- dependencies:
- string-width "^2.1.1"
- strip-ansi "^4.0.0"
- wrap-ansi "^2.0.0"
-
-clone@^1.0.2:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
- integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
-
-clone@^2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
- integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==
-
-clsx@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b"
- integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==
-
-clsx@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
- integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
-
-cmd-shim@^6.0.0:
- version "6.0.3"
- resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.3.tgz#c491e9656594ba17ac83c4bd931590a9d6e26033"
- integrity sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==
-
-cmd-shim@~2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb"
- integrity sha512-NLt0ntM0kvuSNrToO0RTFiNRHdioWsLW+OgDAEVDvIivsYwR+AjlzvLaMJ2Z+SNRpV3vdsDrHp1WI00eetDYzw==
- dependencies:
- graceful-fs "^4.1.2"
- mkdirp "~0.5.0"
-
-co@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
- integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==
-
-code-block-writer@^13.0.1:
- version "13.0.1"
- resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-13.0.1.tgz#52ac60ca6076d8700b88a45bd71e06a577158405"
- integrity sha512-c5or4P6erEA69TxaxTNcHUNcIn+oyxSRTOWV+pSYF+z4epXqNvwvJ70XPGjPNgue83oAFAPBRQYwpAJ/Hpe/Sg==
-
-code-point-at@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
- integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==
-
-codeflask@^1.4.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/codeflask/-/codeflask-1.4.1.tgz#c5229854e3f648377922a75f1145f7316030d3db"
- integrity sha512-4vb2IbE/iwvP0Uubhd2ixVeysm3KNC2pl7SoDaisxq1juhZzvap3qbaX7B2CtpQVvv5V9sjcQK8hO0eTcY0V9Q==
- dependencies:
- "@types/prismjs" "^1.9.1"
- prismjs "^1.14.0"
-
-color-convert@^1.9.0:
- version "1.9.3"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
- integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
- dependencies:
- color-name "1.1.3"
-
-color-convert@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
- integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
- dependencies:
- color-name "~1.1.4"
-
-color-name@1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
- integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
-
-color-name@~1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
- integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-
-colorette@^2.0.16:
- version "2.0.20"
- resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
- integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
-
-columnify@~1.5.4:
- version "1.5.4"
- resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb"
- integrity sha512-rFl+iXVT1nhLQPfGDw+3WcS8rmm7XsLKUmhsGE3ihzzpIikeGrTaZPIRKYWeLsLBypsHzjXIvYEltVUZS84XxQ==
- dependencies:
- strip-ansi "^3.0.0"
- wcwidth "^1.0.0"
-
-combined-stream@^1.0.5, combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.5, combined-stream@~1.0.6:
- version "1.0.8"
- resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
- integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
- dependencies:
- delayed-stream "~1.0.0"
-
-commander@2:
- version "2.20.3"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
- integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
-
-commander@7:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
- integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
-
-commander@^12.0.0:
- version "12.1.0"
- resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3"
- integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==
-
-commander@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
- integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
-
-commander@^6.2.1:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
- integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
-
-common-ancestor-path@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7"
- integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==
-
-common-tags@^1.8.0:
- version "1.8.2"
- resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6"
- integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==
-
-concat-map@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
- integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
-
-concat-stream@^1.5.0, concat-stream@^1.5.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
- integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
- dependencies:
- buffer-from "^1.0.0"
- inherits "^2.0.3"
- readable-stream "^2.2.2"
- typedarray "^0.0.6"
-
-confbox@^0.1.7:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.7.tgz#ccfc0a2bcae36a84838e83a3b7f770fb17d6c579"
- integrity sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==
-
-config-chain@~1.1.11:
- version "1.1.13"
- resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4"
- integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==
- dependencies:
- ini "^1.3.4"
- proto-list "~1.2.1"
-
-configstore@^3.0.0:
- version "3.1.5"
- resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.5.tgz#e9af331fadc14dabd544d3e7e76dc446a09a530f"
- integrity sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==
- dependencies:
- dot-prop "^4.2.1"
- graceful-fs "^4.1.2"
- make-dir "^1.0.0"
- unique-string "^1.0.0"
- write-file-atomic "^2.0.0"
- xdg-basedir "^3.0.0"
-
-consola@^3.2.3:
- version "3.2.3"
- resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f"
- integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==
-
-console-control-strings@^1.0.0, console-control-strings@~1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
- integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==
-
-convert-source-map@^1.5.0:
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f"
- integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
-
-convert-source-map@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
- integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
-
-copy-concurrently@^1.0.0:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
- integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==
- dependencies:
- aproba "^1.1.1"
- fs-write-stream-atomic "^1.0.8"
- iferr "^0.1.5"
- mkdirp "^0.5.1"
- rimraf "^2.5.4"
- run-queue "^1.0.0"
-
-core-util-is@1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
- integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==
-
-core-util-is@~1.0.0:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
- integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
-
-cosmiconfig@^7.0.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6"
- integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==
- dependencies:
- "@types/parse-json" "^4.0.0"
- import-fresh "^3.2.1"
- parse-json "^5.0.0"
- path-type "^4.0.0"
- yaml "^1.10.0"
-
-create-error-class@^3.0.0:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
- integrity sha512-gYTKKexFO3kh200H1Nit76sRwRtOY32vQd3jpAQKpLtZqyNsSQNfI4N7o3eP2wUjV35pTWKRYqFUDBvUha/Pkw==
- dependencies:
- capture-stack-trace "^1.0.0"
-
-crelt@^1.0.0:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.6.tgz#7cc898ea74e190fb6ef9dae57f8f81cf7302df72"
- integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==
-
-cropperjs@^1.6.1:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/cropperjs/-/cropperjs-1.6.2.tgz#d1a5d627d880581cca41b7901f06923500e4201b"
- integrity sha512-nhymn9GdnV3CqiEHJVai54TULFAE3VshJTXSqSJKa8yXAKyBKDWdhHarnlIPrshJ0WMFTGuFvG02YjLXfPiuOA==
-
-cross-spawn@^5.0.1:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
- integrity sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==
- dependencies:
- lru-cache "^4.0.1"
- shebang-command "^1.2.0"
- which "^1.2.9"
-
-cross-spawn@^6.0.0:
- version "6.0.5"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
- integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
- dependencies:
- nice-try "^1.0.4"
- path-key "^2.0.1"
- semver "^5.5.0"
- shebang-command "^1.2.0"
- which "^1.2.9"
-
-cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
- version "7.0.3"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
- integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
- dependencies:
- path-key "^3.1.0"
- shebang-command "^2.0.0"
- which "^2.0.1"
-
-cryptiles@2.x.x:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
- integrity sha512-FFN5KwpvvQTTS5hWPxrU8/QE4kQUc6uwZcrnlMBN82t1MgAtq8mnoDwINBly9Tdr02seeIIhtdF+UH1feBYGog==
- dependencies:
- boom "2.x.x"
-
-crypto-random-string@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
- integrity sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg==
-
-csscolorparser@~1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/csscolorparser/-/csscolorparser-1.0.3.tgz#b34f391eea4da8f3e98231e2ccd8df9c041f171b"
- integrity sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==
-
-cssesc@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
- integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
-
-csstype@^3.0.2, csstype@^3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
- integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
-
-cyclist@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.2.tgz#673b5f233bf34d8e602b949429f8171d9121bea3"
- integrity sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==
-
-cypress@^13.6.3:
- version "13.9.0"
- resolved "https://registry.yarnpkg.com/cypress/-/cypress-13.9.0.tgz#b529cfa8f8c39ba163ed0501a25bb5b09c143652"
- integrity sha512-atNjmYfHsvTuCaxTxLZr9xGoHz53LLui3266WWxXJHY7+N6OdwJdg/feEa3T+buez9dmUXHT1izCOklqG82uCQ==
- dependencies:
- "@cypress/request" "^3.0.0"
- "@cypress/xvfb" "^1.2.4"
- "@types/sinonjs__fake-timers" "8.1.1"
- "@types/sizzle" "^2.3.2"
- arch "^2.2.0"
- blob-util "^2.0.2"
- bluebird "^3.7.2"
- buffer "^5.7.1"
- cachedir "^2.3.0"
- chalk "^4.1.0"
- check-more-types "^2.24.0"
- cli-cursor "^3.1.0"
- cli-table3 "~0.6.1"
- commander "^6.2.1"
- common-tags "^1.8.0"
- dayjs "^1.10.4"
- debug "^4.3.4"
- enquirer "^2.3.6"
- eventemitter2 "6.4.7"
- execa "4.1.0"
- executable "^4.1.1"
- extract-zip "2.0.1"
- figures "^3.2.0"
- fs-extra "^9.1.0"
- getos "^3.2.1"
- is-ci "^3.0.1"
- is-installed-globally "~0.4.0"
- lazy-ass "^1.6.0"
- listr2 "^3.8.3"
- lodash "^4.17.21"
- log-symbols "^4.0.0"
- minimist "^1.2.8"
- ospath "^1.2.2"
- pretty-bytes "^5.6.0"
- process "^0.11.10"
- proxy-from-env "1.0.0"
- request-progress "^3.0.0"
- semver "^7.5.3"
- supports-color "^8.1.1"
- tmp "~0.2.1"
- untildify "^4.0.0"
- yauzl "^2.10.0"
-
-"d3-array@1 - 2":
- version "2.12.1"
- resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81"
- integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==
- dependencies:
- internmap "^1.0.0"
-
-"d3-array@1 - 3", "d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0:
- version "3.2.4"
- resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5"
- integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==
- dependencies:
- internmap "1 - 2"
-
-d3-axis@3:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322"
- integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==
-
-d3-brush@3:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c"
- integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==
- dependencies:
- d3-dispatch "1 - 3"
- d3-drag "2 - 3"
- d3-interpolate "1 - 3"
- d3-selection "3"
- d3-transition "3"
-
-d3-chord@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966"
- integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==
- dependencies:
- d3-path "1 - 3"
-
-d3-collection@^1.0.7:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e"
- integrity sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==
-
-"d3-color@1 - 3", d3-color@3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2"
- integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==
-
-d3-contour@4:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-4.0.2.tgz#bb92063bc8c5663acb2422f99c73cbb6c6ae3bcc"
- integrity sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==
- dependencies:
- d3-array "^3.2.0"
-
-d3-delaunay@6:
- version "6.0.4"
- resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz#98169038733a0a5babbeda55054f795bb9e4a58b"
- integrity sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==
- dependencies:
- delaunator "5"
-
-"d3-dispatch@1 - 3", d3-dispatch@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e"
- integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
-
-"d3-drag@2 - 3", d3-drag@3:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba"
- integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==
- dependencies:
- d3-dispatch "1 - 3"
- d3-selection "3"
-
-"d3-dsv@1 - 3", d3-dsv@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73"
- integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==
- dependencies:
- commander "7"
- iconv-lite "0.6"
- rw "1"
-
-"d3-ease@1 - 3", d3-ease@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4"
- integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==
-
-d3-fetch@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22"
- integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==
- dependencies:
- d3-dsv "1 - 3"
-
-d3-force@3:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4"
- integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==
- dependencies:
- d3-dispatch "1 - 3"
- d3-quadtree "1 - 3"
- d3-timer "1 - 3"
-
-"d3-format@1 - 3", d3-format@3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641"
- integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==
-
-d3-geo-projection@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/d3-geo-projection/-/d3-geo-projection-4.0.0.tgz#dc229e5ead78d31869a4e87cf1f45bd2716c48ca"
- integrity sha512-p0bK60CEzph1iqmnxut7d/1kyTmm3UWtPlwdkM31AU+LW+BXazd5zJdoCn7VFxNCHXRngPHRnsNn5uGjLRGndg==
- dependencies:
- commander "7"
- d3-array "1 - 3"
- d3-geo "1.12.0 - 3"
-
-"d3-geo@1.12.0 - 3", d3-geo@3:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.1.tgz#6027cf51246f9b2ebd64f99e01dc7c3364033a4d"
- integrity sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==
- dependencies:
- d3-array "2.5.0 - 3"
-
-d3-hierarchy@3:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6"
- integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==
-
-d3-interpolate-path@^2.2.3:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/d3-interpolate-path/-/d3-interpolate-path-2.3.0.tgz#ff919acb52968619f4b0dc5fa95653e581d5a0ca"
- integrity sha512-tZYtGXxBmbgHsIc9Wms6LS5u4w6KbP8C09a4/ZYc4KLMYYqub57rRBUgpUr2CIarIrJEpdAWWxWQvofgaMpbKQ==
-
-"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
- integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
- dependencies:
- d3-color "1 - 3"
-
-d3-path@1:
- version "1.0.9"
- resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf"
- integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==
-
-"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526"
- integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==
-
-d3-polygon@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398"
- integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==
-
-"d3-quadtree@1 - 3", d3-quadtree@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f"
- integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==
-
-d3-random@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4"
- integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==
-
-d3-sankey@^0.12.3:
- version "0.12.3"
- resolved "https://registry.yarnpkg.com/d3-sankey/-/d3-sankey-0.12.3.tgz#b3c268627bd72e5d80336e8de6acbfec9d15d01d"
- integrity sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==
- dependencies:
- d3-array "1 - 2"
- d3-shape "^1.2.0"
-
-d3-scale-chromatic@3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#34c39da298b23c20e02f1a4b239bd0f22e7f1314"
- integrity sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==
- dependencies:
- d3-color "1 - 3"
- d3-interpolate "1 - 3"
-
-d3-scale@4:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396"
- integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==
- dependencies:
- d3-array "2.10.0 - 3"
- d3-format "1 - 3"
- d3-interpolate "1.2.0 - 3"
- d3-time "2.1.1 - 3"
- d3-time-format "2 - 4"
-
-"d3-selection@2 - 3", d3-selection@3:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31"
- integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==
-
-d3-shape@3:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5"
- integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==
- dependencies:
- d3-path "^3.1.0"
-
-d3-shape@^1.2.0:
- version "1.3.7"
- resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7"
- integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==
- dependencies:
- d3-path "1"
-
-"d3-time-format@2 - 4", d3-time-format@4:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a"
- integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==
- dependencies:
- d3-time "1 - 3"
-
-"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7"
- integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==
- dependencies:
- d3-array "2 - 3"
-
-"d3-timer@1 - 3", d3-timer@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0"
- integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==
-
-"d3-transition@2 - 3", d3-transition@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f"
- integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==
- dependencies:
- d3-color "1 - 3"
- d3-dispatch "1 - 3"
- d3-ease "1 - 3"
- d3-interpolate "1 - 3"
- d3-timer "1 - 3"
-
-d3-zoom@3:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3"
- integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==
- dependencies:
- d3-dispatch "1 - 3"
- d3-drag "2 - 3"
- d3-interpolate "1 - 3"
- d3-selection "2 - 3"
- d3-transition "2 - 3"
-
-d3@^7.2.1:
- version "7.9.0"
- resolved "https://registry.yarnpkg.com/d3/-/d3-7.9.0.tgz#579e7acb3d749caf8860bd1741ae8d371070cd5d"
- integrity sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==
- dependencies:
- d3-array "3"
- d3-axis "3"
- d3-brush "3"
- d3-chord "3"
- d3-color "3"
- d3-contour "4"
- d3-delaunay "6"
- d3-dispatch "3"
- d3-drag "3"
- d3-dsv "3"
- d3-ease "3"
- d3-fetch "3"
- d3-force "3"
- d3-format "3"
- d3-geo "3"
- d3-hierarchy "3"
- d3-interpolate "3"
- d3-path "3"
- d3-polygon "3"
- d3-quadtree "3"
- d3-random "3"
- d3-scale "4"
- d3-scale-chromatic "3"
- d3-selection "3"
- d3-shape "3"
- d3-time "3"
- d3-time-format "4"
- d3-timer "3"
- d3-transition "3"
- d3-zoom "3"
-
-dashdash@^1.12.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
- integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==
- dependencies:
- assert-plus "^1.0.0"
-
-date-fns@^3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-3.6.0.tgz#f20ca4fe94f8b754951b24240676e8618c0206bf"
- integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==
-
-dayjs@^1.10.4:
- version "1.11.11"
- resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e"
- integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==
-
-debug@3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
- integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
- dependencies:
- ms "2.0.0"
-
-debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
- version "4.3.4"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
- integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
- dependencies:
- ms "2.1.2"
-
-debug@^3.1.0:
- version "3.2.7"
- resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
- integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
- dependencies:
- ms "^2.1.1"
-
-debug@^4.1.0:
- version "4.3.5"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e"
- integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==
- dependencies:
- ms "2.1.2"
-
-debuglog@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
- integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==
-
-decamelize@^1.1.1:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
- integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
-
-deep-equal@^1.0.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.2.tgz#78a561b7830eef3134c7f6f3a3d6af272a678761"
- integrity sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==
- dependencies:
- is-arguments "^1.1.1"
- is-date-object "^1.0.5"
- is-regex "^1.1.4"
- object-is "^1.1.5"
- object-keys "^1.1.1"
- regexp.prototype.flags "^1.5.1"
-
-deep-extend@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
- integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
-
-deep-is@^0.1.3:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
- integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
-
-defaults@^1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
- integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==
- dependencies:
- clone "^1.0.2"
-
-define-data-property@^1.0.1, define-data-property@^1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
- integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
- dependencies:
- es-define-property "^1.0.0"
- es-errors "^1.3.0"
- gopd "^1.0.1"
-
-define-properties@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
- integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==
- dependencies:
- define-data-property "^1.0.1"
- has-property-descriptors "^1.0.0"
- object-keys "^1.1.1"
-
-defu@^6.1.4:
- version "6.1.4"
- resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479"
- integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==
-
-delaunator@5:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.1.tgz#39032b08053923e924d6094fe2cde1a99cc51278"
- integrity sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==
- dependencies:
- robust-predicates "^3.0.2"
-
-delayed-stream@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
- integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
-
-delegates@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
- integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
-
-destr@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.3.tgz#7f9e97cb3d16dbdca7be52aca1644ce402cfe449"
- integrity sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==
-
-detect-indent@~5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
- integrity sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==
-
-"detype@npm:detypes@^0.8.0":
- version "0.8.0"
- resolved "https://registry.yarnpkg.com/detypes/-/detypes-0.8.0.tgz#178ec9438b4d7fd4d92abdc461b799103422a95b"
- integrity sha512-BlPqlSZSIPlMmivkswXVeGkS97RfLZ5KU3BSU443gQBY9K7Ake+qMltrKJoL5pXzhcjWtnzyl2fGAVRvjCzBtw==
- dependencies:
- "@babel/core" "^7.24.5"
- "@babel/preset-typescript" "^7.24.1"
- "@vue/compiler-dom" "^3.4.27"
- "@vue/compiler-sfc" "^3.4.27"
- "@vuedx/template-ast-types" "0.7.1"
- fast-glob "^3.3.2"
- prettier "^3.2.5"
- typescript "^5.4.5"
-
-dezalgo@^1.0.0, dezalgo@~1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81"
- integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==
- dependencies:
- asap "^2.0.0"
- wrappy "1"
-
-didyoumean@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
- integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
-
-diff@^5.1.0, diff@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531"
- integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==
-
-dlv@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
- integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
-
-doctrine@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
- integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
- dependencies:
- esutils "^2.0.2"
-
-dot-prop@^4.2.1:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4"
- integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==
- dependencies:
- is-obj "^1.0.0"
-
-dotenv@^16.4.5:
- version "16.4.5"
- resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
- integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==
-
-dotenv@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef"
- integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==
-
-duplexer3@^0.1.4:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e"
- integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==
-
-duplexer@~0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
- integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
-
-duplexify@^3.4.2, duplexify@^3.6.0:
- version "3.7.1"
- resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
- integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
- dependencies:
- end-of-stream "^1.0.0"
- inherits "^2.0.1"
- readable-stream "^2.0.0"
- stream-shift "^1.0.0"
-
-earcut@^2.2.4:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/earcut/-/earcut-2.2.4.tgz#6d02fd4d68160c114825d06890a92ecaae60343a"
- integrity sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==
-
-eastasianwidth@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
- integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
-
-ecc-jsbn@~0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
- integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==
- dependencies:
- jsbn "~0.1.0"
- safer-buffer "^2.1.0"
-
-editor@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742"
- integrity sha512-SoRmbGStwNYHgKfjOrX2L0mUvp9bUVv0uPppZSOMAntEbcFtoC3MKF5b3T6HQPXKIV+QGY3xPO3JK5it5lVkuw==
-
-electron-to-chromium@^1.4.668:
- version "1.4.763"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.763.tgz#64f2041ed496fd6fc710b9be806fe91da9334f91"
- integrity sha512-k4J8NrtJ9QrvHLRo8Q18OncqBCB7tIUyqxRcJnlonQ0ioHKYB988GcDFF3ZePmnb8eHEopDs/wPHR/iGAFgoUQ==
-
-electron-to-chromium@^1.4.796:
- version "1.4.816"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.816.tgz#3624649d1e7fde5cdbadf59d31a524245d8ee85f"
- integrity sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw==
-
-elkjs@^0.8.2:
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/elkjs/-/elkjs-0.8.2.tgz#c37763c5a3e24e042e318455e0147c912a7c248e"
- integrity sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==
-
-emoji-regex@^10.3.0:
- version "10.3.0"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23"
- integrity sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==
-
-emoji-regex@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
- integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
-
-emoji-regex@^9.2.2:
- version "9.2.2"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
- integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
-
-encoding@^0.1.11, encoding@^0.1.13:
- version "0.1.13"
- resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
- integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
- dependencies:
- iconv-lite "^0.6.2"
-
-end-of-stream@^1.0.0, end-of-stream@^1.1.0:
- version "1.4.4"
- resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
- integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
- dependencies:
- once "^1.4.0"
-
-enquirer@^2.3.6:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56"
- integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==
- dependencies:
- ansi-colors "^4.1.1"
- strip-ansi "^6.0.1"
-
-entities@^4.4.0, entities@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
- integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
-
-entities@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/entities/-/entities-5.0.0.tgz#b2ab51fe40d995817979ec79dd621154c3c0f62b"
- integrity sha512-BeJFvFRJddxobhvEdm5GqHzRV/X+ACeuw0/BuuxsCh1EUZcAIz8+kYmBp/LrQuloy6K1f3a0M7+IhmZ7QnkISA==
-
-env-paths@^2.2.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
- integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
-
-err-code@^1.0.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960"
- integrity sha512-CJAN+O0/yA1CKfRn9SXOGctSpEM7DCon/r/5r2eXFMY2zCCJBasFhcM5I+1kh3Ap11FsQCX+vGHceNPvpWKhoA==
-
-err-code@^2.0.2:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
- integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
-
-"errno@>=0.1.1 <0.2.0-0":
- version "0.1.8"
- resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
- integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==
- dependencies:
- prr "~1.0.1"
-
-error-ex@^1.3.1:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
- integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
- dependencies:
- is-arrayish "^0.2.1"
-
-es-define-property@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
- integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==
- dependencies:
- get-intrinsic "^1.2.4"
-
-es-errors@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
- integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
-
-es6-promise@^4.0.3:
- version "4.2.8"
- resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
- integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
-
-es6-promisify@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
- integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==
- dependencies:
- es6-promise "^4.0.3"
-
-esbuild@^0.21.3:
- version "0.21.5"
- resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d"
- integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==
- optionalDependencies:
- "@esbuild/aix-ppc64" "0.21.5"
- "@esbuild/android-arm" "0.21.5"
- "@esbuild/android-arm64" "0.21.5"
- "@esbuild/android-x64" "0.21.5"
- "@esbuild/darwin-arm64" "0.21.5"
- "@esbuild/darwin-x64" "0.21.5"
- "@esbuild/freebsd-arm64" "0.21.5"
- "@esbuild/freebsd-x64" "0.21.5"
- "@esbuild/linux-arm" "0.21.5"
- "@esbuild/linux-arm64" "0.21.5"
- "@esbuild/linux-ia32" "0.21.5"
- "@esbuild/linux-loong64" "0.21.5"
- "@esbuild/linux-mips64el" "0.21.5"
- "@esbuild/linux-ppc64" "0.21.5"
- "@esbuild/linux-riscv64" "0.21.5"
- "@esbuild/linux-s390x" "0.21.5"
- "@esbuild/linux-x64" "0.21.5"
- "@esbuild/netbsd-x64" "0.21.5"
- "@esbuild/openbsd-x64" "0.21.5"
- "@esbuild/sunos-x64" "0.21.5"
- "@esbuild/win32-arm64" "0.21.5"
- "@esbuild/win32-ia32" "0.21.5"
- "@esbuild/win32-x64" "0.21.5"
-
-escalade@^3.1.2:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
- integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
-
-escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
- integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
-
-escape-string-regexp@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
- integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
-
-eslint-config-prettier@^8.8.0:
- version "8.10.0"
- resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11"
- integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==
-
-eslint-plugin-cypress@^2.15.1:
- version "2.15.2"
- resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.15.2.tgz#f22e12fad4c434edad7b298ef92bac8fa087ffa0"
- integrity sha512-CtcFEQTDKyftpI22FVGpx8bkpKyYXBlNge6zSo0pl5/qJvBAnzaD76Vu2AsP16d6mTj478Ldn2mhgrWV+Xr0vQ==
- dependencies:
- globals "^13.20.0"
-
-eslint-plugin-prettier@^5.0.0:
- version "5.1.3"
- resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz#17cfade9e732cef32b5f5be53bd4e07afd8e67e1"
- integrity sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==
- dependencies:
- prettier-linter-helpers "^1.0.0"
- synckit "^0.8.6"
-
-eslint-plugin-vue@^9.17.0:
- version "9.26.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.26.0.tgz#bf7f5cce62c8f878059b91edae44d22974133af5"
- integrity sha512-eTvlxXgd4ijE1cdur850G6KalZqk65k1JKoOI2d1kT3hr8sPD07j1q98FRFdNnpxBELGPWxZmInxeHGF/GxtqQ==
- dependencies:
- "@eslint-community/eslint-utils" "^4.4.0"
- globals "^13.24.0"
- natural-compare "^1.4.0"
- nth-check "^2.1.1"
- postcss-selector-parser "^6.0.15"
- semver "^7.6.0"
- vue-eslint-parser "^9.4.2"
- xml-name-validator "^4.0.0"
-
-eslint-scope@^7.1.1, eslint-scope@^7.2.2:
- version "7.2.2"
- resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f"
- integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
- dependencies:
- esrecurse "^4.3.0"
- estraverse "^5.2.0"
-
-eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3:
- version "3.4.3"
- resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
- integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
-
-eslint@^8.49.0:
- version "8.57.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668"
- integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==
- dependencies:
- "@eslint-community/eslint-utils" "^4.2.0"
- "@eslint-community/regexpp" "^4.6.1"
- "@eslint/eslintrc" "^2.1.4"
- "@eslint/js" "8.57.0"
- "@humanwhocodes/config-array" "^0.11.14"
- "@humanwhocodes/module-importer" "^1.0.1"
- "@nodelib/fs.walk" "^1.2.8"
- "@ungap/structured-clone" "^1.2.0"
- ajv "^6.12.4"
- chalk "^4.0.0"
- cross-spawn "^7.0.2"
- debug "^4.3.2"
- doctrine "^3.0.0"
- escape-string-regexp "^4.0.0"
- eslint-scope "^7.2.2"
- eslint-visitor-keys "^3.4.3"
- espree "^9.6.1"
- esquery "^1.4.2"
- esutils "^2.0.2"
- fast-deep-equal "^3.1.3"
- file-entry-cache "^6.0.1"
- find-up "^5.0.0"
- glob-parent "^6.0.2"
- globals "^13.19.0"
- graphemer "^1.4.0"
- ignore "^5.2.0"
- imurmurhash "^0.1.4"
- is-glob "^4.0.0"
- is-path-inside "^3.0.3"
- js-yaml "^4.1.0"
- json-stable-stringify-without-jsonify "^1.0.1"
- levn "^0.4.1"
- lodash.merge "^4.6.2"
- minimatch "^3.1.2"
- natural-compare "^1.4.0"
- optionator "^0.9.3"
- strip-ansi "^6.0.1"
- text-table "^0.2.0"
-
-espree@^9.3.1, espree@^9.6.0, espree@^9.6.1:
- version "9.6.1"
- resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
- integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==
- dependencies:
- acorn "^8.9.0"
- acorn-jsx "^5.3.2"
- eslint-visitor-keys "^3.4.1"
-
-esquery@^1.4.0, esquery@^1.4.2:
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
- integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
- dependencies:
- estraverse "^5.1.0"
-
-esrecurse@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
- integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
- dependencies:
- estraverse "^5.2.0"
-
-estraverse@^5.1.0, estraverse@^5.2.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
- integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
-
-estree-walker@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
- integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
-
-esutils@^2.0.2:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
- integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
-
-event-stream@=3.3.4:
- version "3.3.4"
- resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
- integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==
- dependencies:
- duplexer "~0.1.1"
- from "~0"
- map-stream "~0.1.0"
- pause-stream "0.0.11"
- split "0.3"
- stream-combiner "~0.0.4"
- through "~2.3.1"
-
-eventemitter2@6.4.7:
- version "6.4.7"
- resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d"
- integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==
-
-eventemitter3@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-2.0.3.tgz#b5e1079b59fb5e1ba2771c0a993be060a58c99ba"
- integrity sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==
-
-execa@4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
- integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
- dependencies:
- cross-spawn "^7.0.0"
- get-stream "^5.0.0"
- human-signals "^1.1.1"
- is-stream "^2.0.0"
- merge-stream "^2.0.0"
- npm-run-path "^4.0.0"
- onetime "^5.1.0"
- signal-exit "^3.0.2"
- strip-final-newline "^2.0.0"
-
-execa@5.1.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
- integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
- 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"
-
-execa@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
- integrity sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==
- dependencies:
- cross-spawn "^5.0.1"
- get-stream "^3.0.0"
- is-stream "^1.1.0"
- npm-run-path "^2.0.0"
- p-finally "^1.0.0"
- signal-exit "^3.0.0"
- strip-eof "^1.0.0"
-
-execa@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
- integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
- dependencies:
- cross-spawn "^6.0.0"
- get-stream "^4.0.0"
- is-stream "^1.1.0"
- npm-run-path "^2.0.0"
- p-finally "^1.0.0"
- signal-exit "^3.0.0"
- strip-eof "^1.0.0"
-
-execa@^8.0.1:
- version "8.0.1"
- resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c"
- integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==
- dependencies:
- cross-spawn "^7.0.3"
- get-stream "^8.0.1"
- human-signals "^5.0.0"
- is-stream "^3.0.0"
- merge-stream "^2.0.0"
- npm-run-path "^5.1.0"
- onetime "^6.0.0"
- signal-exit "^4.1.0"
- strip-final-newline "^3.0.0"
-
-executable@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c"
- integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==
- dependencies:
- pify "^2.2.0"
-
-exponential-backoff@^3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6"
- integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==
-
-extend@^3.0.2, extend@~3.0.0, extend@~3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
- integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-
-extract-zip@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
- integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
- dependencies:
- debug "^4.1.1"
- get-stream "^5.1.0"
- yauzl "^2.10.0"
- optionalDependencies:
- "@types/yauzl" "^2.9.1"
-
-extsprintf@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
- integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==
-
-extsprintf@^1.2.0:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07"
- integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
-
-fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
- integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
-
-fast-diff@1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
- integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==
-
-fast-diff@1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
- integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
-
-fast-diff@^1.1.2:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0"
- integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==
-
-fast-glob@^3.3.0, fast-glob@^3.3.2:
- version "3.3.2"
- resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
- integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
- 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"
-
-fast-json-stable-stringify@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
- integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
-
-fast-levenshtein@^2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
- integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
-
-fastest-levenshtein@^1.0.16:
- version "1.0.16"
- resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5"
- integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==
-
-fastq@^1.6.0:
- version "1.17.1"
- resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47"
- integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==
- dependencies:
- reusify "^1.0.4"
-
-fd-slicer@~1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
- integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==
- dependencies:
- pend "~1.2.0"
-
-figures@^3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
- integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
- dependencies:
- escape-string-regexp "^1.0.5"
-
-file-entry-cache@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
- integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
- dependencies:
- flat-cache "^3.0.4"
-
-fill-range@^7.0.1:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
- integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
- dependencies:
- to-regex-range "^5.0.1"
-
-find-root@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
- integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
-
-find-up@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
- integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==
- dependencies:
- locate-path "^2.0.0"
-
-find-up@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
- integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
- dependencies:
- locate-path "^6.0.0"
- path-exists "^4.0.0"
-
-flat-cache@^3.0.4:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee"
- integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==
- dependencies:
- flatted "^3.2.9"
- keyv "^4.5.3"
- rimraf "^3.0.2"
-
-flatted@^3.2.9:
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
- integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
-
-flush-write-stream@^1.0.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
- integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==
- dependencies:
- inherits "^2.0.3"
- readable-stream "^2.3.6"
-
-follow-redirects@^1.15.6:
- version "1.15.6"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
- integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
-
-foreground-child@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d"
- integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==
- dependencies:
- cross-spawn "^7.0.0"
- signal-exit "^4.0.1"
-
-forever-agent@~0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
- integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==
-
-form-data@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
- integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
- dependencies:
- asynckit "^0.4.0"
- combined-stream "^1.0.8"
- mime-types "^2.1.12"
-
-form-data@~2.1.1:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
- integrity sha512-8HWGSLAPr+AG0hBpsqi5Ob8HrLStN/LWeqhpFl14d7FJgHK48TmgLoALPz69XSUR65YJzDfLUX/BM8+MLJLghQ==
- dependencies:
- asynckit "^0.4.0"
- combined-stream "^1.0.5"
- mime-types "^2.1.12"
-
-form-data@~2.3.2:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
- integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
- dependencies:
- asynckit "^0.4.0"
- combined-stream "^1.0.6"
- mime-types "^2.1.12"
-
-fraction.js@^4.3.7:
- version "4.3.7"
- resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
- integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
-
-from2@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/from2/-/from2-1.3.0.tgz#88413baaa5f9a597cfde9221d86986cd3c061dfd"
- integrity sha512-1eKYoECvhpM4IT70THQV8XNfmZoIlnROymbwOSazfmQO3kK+zCV+LSqUDzl7gDo3MZddCFeVa9Zg3Hi6FXqcgg==
- dependencies:
- inherits "~2.0.1"
- readable-stream "~1.1.10"
-
-from2@^2.1.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
- integrity sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==
- dependencies:
- inherits "^2.0.1"
- readable-stream "^2.0.0"
-
-from@~0:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
- integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==
-
-fs-constants@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
- integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
-
-fs-extra@^11.2.0:
- version "11.2.0"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b"
- integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==
- dependencies:
- graceful-fs "^4.2.0"
- jsonfile "^6.0.1"
- universalify "^2.0.0"
-
-fs-extra@^9.1.0:
- version "9.1.0"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
- integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
- dependencies:
- at-least-node "^1.0.0"
- graceful-fs "^4.2.0"
- jsonfile "^6.0.1"
- universalify "^2.0.0"
-
-fs-minipass@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
- integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
- dependencies:
- minipass "^3.0.0"
-
-fs-minipass@^3.0.0, fs-minipass@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54"
- integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==
- dependencies:
- minipass "^7.0.3"
-
-fs-vacuum@~1.2.10:
- version "1.2.10"
- resolved "https://registry.yarnpkg.com/fs-vacuum/-/fs-vacuum-1.2.10.tgz#b7629bec07a4031a2548fdf99f5ecf1cc8b31e36"
- integrity sha512-bwbv1FcWYwxN1F08I1THN8nS4Qe/pGq0gM8dy1J34vpxxp3qgZKJPPaqex36RyZO0sD2J+2ocnbwC2d/OjYICQ==
- dependencies:
- graceful-fs "^4.1.2"
- path-is-inside "^1.0.1"
- rimraf "^2.5.2"
-
-fs-write-stream-atomic@^1.0.8, fs-write-stream-atomic@~1.0.10:
- version "1.0.10"
- resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
- integrity sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==
- dependencies:
- graceful-fs "^4.1.2"
- iferr "^0.1.5"
- imurmurhash "^0.1.4"
- readable-stream "1 || 2"
-
-fs.realpath@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
- integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
-
-fsevents@~2.3.2, fsevents@~2.3.3:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
- integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
-
-fstream-ignore@^1.0.0:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105"
- integrity sha512-VVRuOs41VUqptEGiR0N5ZoWEcfGvbGRqLINyZAhHRnF3DH5wrqjNkYr3VbRoZnI41BZgO7zIVdiobc13TVI1ow==
- dependencies:
- fstream "^1.0.0"
- inherits "2"
- minimatch "^3.0.0"
-
-fstream-npm@~1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/fstream-npm/-/fstream-npm-1.2.1.tgz#08c4a452f789dcbac4c89a4563c902b2c862fd5b"
- integrity sha512-iBHpm/LmD1qw0TlHMAqVd9rwdU6M+EHRUnPkXpRi5G/Hf0FIFH+oZFryodAU2MFNfGRh/CzhUFlMKV3pdeOTDw==
- dependencies:
- fstream-ignore "^1.0.0"
- inherits "2"
-
-fstream@^1.0.0, fstream@^1.0.12, fstream@~1.0.11:
- version "1.0.12"
- resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
- integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
- dependencies:
- graceful-fs "^4.1.2"
- inherits "~2.0.0"
- mkdirp ">=0.5 0"
- rimraf "2"
-
-function-bind@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
- integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
-
-functions-have-names@^1.2.3:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
- integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
-
-gauge@~2.7.3:
- version "2.7.4"
- resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
- integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==
- dependencies:
- aproba "^1.0.3"
- console-control-strings "^1.0.0"
- has-unicode "^2.0.0"
- object-assign "^4.1.0"
- signal-exit "^3.0.0"
- string-width "^1.0.1"
- strip-ansi "^3.0.1"
- wide-align "^1.1.0"
-
-genfun@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/genfun/-/genfun-4.0.1.tgz#ed10041f2e4a7f1b0a38466d17a5c3e27df1dfc1"
- integrity sha512-48yv1eDS5Qrz6cbSDBBik0u7jCgC/eA9eZrl9MIN1LfKzFTuGt6EHgr31YM8yT9cjb5BplXb4Iz3VtOYmgt8Jg==
-
-gensync@^1.0.0-beta.2:
- version "1.0.0-beta.2"
- resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
- integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
-
-geojson-vt@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/geojson-vt/-/geojson-vt-3.2.1.tgz#f8adb614d2c1d3f6ee7c4265cad4bbf3ad60c8b7"
- integrity sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==
-
-geojson@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/geojson/-/geojson-0.5.0.tgz#3cd6c96399be65b56ee55596116fe9191ce701c0"
- integrity sha512-/Bx5lEn+qRF4TfQ5aLu6NH+UKtvIv7Lhc487y/c8BdludrCTpiWf9wyI0RTyqg49MFefIAvFDuEi5Dfd/zgNxQ==
-
-get-caller-file@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
- integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
-
-get-east-asian-width@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz#5e6ebd9baee6fb8b7b6bd505221065f0cd91f64e"
- integrity sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==
-
-get-intrinsic@^1.1.3, get-intrinsic@^1.2.4:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
- integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
- dependencies:
- es-errors "^1.3.0"
- function-bind "^1.1.2"
- has-proto "^1.0.1"
- has-symbols "^1.0.3"
- hasown "^2.0.0"
-
-get-stream@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
- integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==
-
-get-stream@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
- integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
- dependencies:
- pump "^3.0.0"
-
-get-stream@^5.0.0, get-stream@^5.1.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
- integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
- dependencies:
- pump "^3.0.0"
-
-get-stream@^6.0.0, get-stream@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
- integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
-
-get-stream@^8.0.1:
- version "8.0.1"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2"
- integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==
-
-getos@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5"
- integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==
- dependencies:
- async "^3.2.0"
-
-getpass@^0.1.1:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
- integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==
- dependencies:
- assert-plus "^1.0.0"
-
-giget@^1.2.3:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/giget/-/giget-1.2.3.tgz#ef6845d1140e89adad595f7f3bb60aa31c672cb6"
- integrity sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==
- dependencies:
- citty "^0.1.6"
- consola "^3.2.3"
- defu "^6.1.4"
- node-fetch-native "^1.6.3"
- nypm "^0.3.8"
- ohash "^1.1.3"
- pathe "^1.1.2"
- tar "^6.2.0"
-
-gl-matrix@^3.4.3:
- version "3.4.3"
- resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.4.3.tgz#fc1191e8320009fd4d20e9339595c6041ddc22c9"
- integrity sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==
-
-glob-parent@^5.1.2, glob-parent@~5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
- integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
- dependencies:
- is-glob "^4.0.1"
-
-glob-parent@^6.0.2:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
- integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
- dependencies:
- is-glob "^4.0.3"
-
-glob@^10.2.2, glob@^10.3.10, glob@^10.3.12:
- version "10.3.15"
- resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.15.tgz#e72bc61bc3038c90605f5dd48543dc67aaf3b50d"
- integrity sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==
- dependencies:
- foreground-child "^3.1.0"
- jackspeak "^2.3.6"
- minimatch "^9.0.1"
- minipass "^7.0.4"
- path-scurry "^1.11.0"
-
-glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3:
- version "7.2.3"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
- integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.1.1"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-glob@~7.1.2:
- version "7.1.7"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
- integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.0.4"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-global-dirs@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
- integrity sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==
- dependencies:
- ini "^1.3.4"
-
-global-dirs@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485"
- integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==
- dependencies:
- ini "2.0.0"
-
-global-prefix@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97"
- integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==
- dependencies:
- ini "^1.3.5"
- kind-of "^6.0.2"
- which "^1.3.1"
-
-globals@^11.1.0:
- version "11.12.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
- integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
-
-globals@^13.19.0, globals@^13.20.0, globals@^13.24.0:
- version "13.24.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171"
- integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==
- dependencies:
- type-fest "^0.20.2"
-
-gopd@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
- integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
- dependencies:
- get-intrinsic "^1.1.3"
-
-got@^6.7.1:
- version "6.7.1"
- resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
- integrity sha512-Y/K3EDuiQN9rTZhBvPRWMLXIKdeD1Rj0nzunfoi0Yyn5WBEbzxXKU9Ub2X41oZBagVWOBU3MuDonFMgPWQFnwg==
- dependencies:
- create-error-class "^3.0.0"
- duplexer3 "^0.1.4"
- get-stream "^3.0.0"
- is-redirect "^1.0.0"
- is-retry-allowed "^1.0.0"
- is-stream "^1.0.0"
- lowercase-keys "^1.0.0"
- safe-buffer "^5.0.1"
- timed-out "^4.0.0"
- unzip-response "^2.0.1"
- url-parse-lax "^1.0.0"
-
-graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.6:
- version "4.2.11"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
- integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
-
-graceful-fs@~4.1.11:
- version "4.1.15"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
- integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
-
-graphemer@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
- integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
-
-har-schema@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
- integrity sha512-f8xf2GOR6Rgwc9FPTLNzgwB+JQ2/zMauYXSWmX5YV5acex6VomT0ocSuwR7BfXo5MpHi+jL+saaux2fwsGJDKQ==
-
-har-schema@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
- integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==
-
-har-validator@~4.2.1:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
- integrity sha512-5Gbp6RAftMYYV3UEI4c4Vv3+a4dQ7taVyvHt+/L6kRt+f4HX1GweAk5UDWN0SvdVnRBzGQ6OG89pGaD9uSFnVw==
- dependencies:
- ajv "^4.9.1"
- har-schema "^1.0.5"
-
-har-validator@~5.1.3:
- version "5.1.5"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
- integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
- dependencies:
- ajv "^6.12.3"
- har-schema "^2.0.0"
-
-has-ansi@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
- integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==
- dependencies:
- ansi-regex "^2.0.0"
-
-has-flag@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
- integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
-
-has-flag@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
- integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
-
-has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
- integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
- dependencies:
- es-define-property "^1.0.0"
-
-has-proto@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd"
- integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==
-
-has-symbols@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
- integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
-
-has-tostringtag@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
- integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
- dependencies:
- has-symbols "^1.0.3"
-
-has-unicode@^2.0.0, has-unicode@~2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
- integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==
-
-hasown@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
- integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
- dependencies:
- function-bind "^1.1.2"
-
-hawk@~3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
- integrity sha512-X8xbmTc1cbPXcQV4WkLcRMALuyoxhfpFATmyuCxJPOAvrDS4DNnsTAOmKUxMTOWU6TzrTOkxPKwIx5ZOpJVSrg==
- dependencies:
- boom "2.x.x"
- cryptiles "2.x.x"
- hoek "2.x.x"
- sntp "1.x.x"
-
-hoek@2.x.x:
- version "2.16.3"
- resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
- integrity sha512-V6Yw1rIcYV/4JsnggjBU0l4Kr+EXhpwqXRusENU1Xx6ro00IHPHYNynCuBTOZAPlr3AAmLvchH9I7N/VUdvOwQ==
-
-hosted-git-info@^2.1.4, hosted-git-info@^2.4.2, hosted-git-info@^2.7.1:
- version "2.8.9"
- resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
- integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
-
-hosted-git-info@^7.0.0, hosted-git-info@^7.0.1:
- version "7.0.2"
- resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.2.tgz#9b751acac097757667f30114607ef7b661ff4f17"
- integrity sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==
- dependencies:
- lru-cache "^10.0.1"
-
-hosted-git-info@~2.5.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
- integrity sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==
-
-http-cache-semantics@^3.8.0:
- version "3.8.1"
- resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
- integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==
-
-http-cache-semantics@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
- integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
-
-http-proxy-agent@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
- integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
- dependencies:
- agent-base "4"
- debug "3.1.0"
-
-http-proxy-agent@^7.0.0:
- version "7.0.2"
- resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e"
- integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==
- dependencies:
- agent-base "^7.1.0"
- debug "^4.3.4"
-
-http-signature@~1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
- integrity sha512-iUn0NcRULlDGtqNLN1Jxmzayk8ogm7NToldASyZBpM2qggbphjXzNOiw3piN8tgz+e/DRs6X5gAzFwTI6BCRcg==
- dependencies:
- assert-plus "^0.2.0"
- jsprim "^1.2.2"
- sshpk "^1.7.0"
-
-http-signature@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
- integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==
- dependencies:
- assert-plus "^1.0.0"
- jsprim "^1.2.2"
- sshpk "^1.7.0"
-
-http-signature@~1.3.6:
- version "1.3.6"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9"
- integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==
- dependencies:
- assert-plus "^1.0.0"
- jsprim "^2.0.2"
- sshpk "^1.14.1"
-
-https-proxy-agent@^2.1.0:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
- integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
- dependencies:
- agent-base "^4.3.0"
- debug "^3.1.0"
-
-https-proxy-agent@^7.0.1:
- version "7.0.4"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz#8e97b841a029ad8ddc8731f26595bad868cb4168"
- integrity sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==
- dependencies:
- agent-base "^7.0.2"
- debug "4"
-
-https-proxy-agent@^7.0.4:
- version "7.0.5"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2"
- integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==
- dependencies:
- agent-base "^7.0.2"
- debug "4"
-
-human-signals@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
- integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
-
-human-signals@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
- integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
-
-human-signals@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28"
- integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==
-
-humanize-ms@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
- integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==
- dependencies:
- ms "^2.0.0"
-
-iconv-lite@0.6, iconv-lite@^0.6.2:
- version "0.6.3"
- resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
- integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
- dependencies:
- safer-buffer ">= 2.1.2 < 3.0.0"
-
-ieee754@^1.1.12, ieee754@^1.1.13:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
- integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
-
-iferr@^0.1.5, iferr@~0.1.5:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
- integrity sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==
-
-ignore-walk@^6.0.4:
- version "6.0.5"
- resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-6.0.5.tgz#ef8d61eab7da169078723d1f82833b36e200b0dd"
- integrity sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==
- dependencies:
- minimatch "^9.0.0"
-
-ignore@^5.2.0:
- version "5.3.1"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef"
- integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==
-
-immutable@^4.0.0:
- version "4.3.6"
- resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.6.tgz#6a05f7858213238e587fb83586ffa3b4b27f0447"
- integrity sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==
-
-import-fresh@^3.2.1:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
- integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
- dependencies:
- parent-module "^1.0.0"
- resolve-from "^4.0.0"
-
-import-lazy@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
- integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==
-
-imurmurhash@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
- integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
-
-indent-string@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
- integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
-
-inflight@^1.0.4, inflight@~1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
- integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
- dependencies:
- once "^1.3.0"
- wrappy "1"
-
-inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
- integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-
-ini@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
- integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
-
-ini@^1.3.4, ini@^1.3.5, ini@~1.3.0, ini@~1.3.4:
- version "1.3.8"
- resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
- integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
-
-ini@^4.1.2:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.2.tgz#7f646dbd9caea595e61f88ef60bfff8b01f8130a"
- integrity sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==
-
-init-package-json@^6.0.2:
- version "6.0.3"
- resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-6.0.3.tgz#2552fba75b6eed2495dc97f44183e2e5a5bcf8b0"
- integrity sha512-Zfeb5ol+H+eqJWHTaGca9BovufyGeIfr4zaaBorPmJBMrJ+KBnN+kQx2ZtXdsotUTgldHmHQV44xvUWOUA7E2w==
- dependencies:
- "@npmcli/package-json" "^5.0.0"
- npm-package-arg "^11.0.0"
- promzard "^1.0.0"
- read "^3.0.1"
- semver "^7.3.5"
- validate-npm-package-license "^3.0.4"
- validate-npm-package-name "^5.0.0"
-
-init-package-json@~1.10.1:
- version "1.10.3"
- resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.3.tgz#45ffe2f610a8ca134f2bd1db5637b235070f6cbe"
- integrity sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==
- dependencies:
- glob "^7.1.1"
- npm-package-arg "^4.0.0 || ^5.0.0 || ^6.0.0"
- promzard "^0.3.0"
- read "~1.0.1"
- read-package-json "1 || 2"
- semver "2.x || 3.x || 4 || 5"
- validate-npm-package-license "^3.0.1"
- validate-npm-package-name "^3.0.0"
-
-install@^0.13.0:
- version "0.13.0"
- resolved "https://registry.yarnpkg.com/install/-/install-0.13.0.tgz#6af6e9da9dd0987de2ab420f78e60d9c17260776"
- integrity sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==
-
-"internmap@1 - 2":
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009"
- integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==
-
-internmap@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95"
- integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==
-
-invert-kv@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
- integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
-
-ip-address@^9.0.5:
- version "9.0.5"
- resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a"
- integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==
- dependencies:
- jsbn "1.1.0"
- sprintf-js "^1.1.3"
-
-ip-regex@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-5.0.0.tgz#cd313b2ae9c80c07bd3851e12bf4fa4dc5480632"
- integrity sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==
-
-ip@^1.1.4:
- version "1.1.9"
- resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396"
- integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==
-
-is-arguments@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
- integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==
- dependencies:
- call-bind "^1.0.2"
- has-tostringtag "^1.0.0"
-
-is-arrayish@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
- integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
-
-is-binary-path@~2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
- integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
- dependencies:
- binary-extensions "^2.0.0"
-
-is-builtin-module@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
- integrity sha512-C2wz7Juo5pUZTFQVer9c+9b4qw3I5T/CHQxQyhVu7BJel6C22FmsLIWsdseYyOw6xz9Pqy9eJWSkQ7+3iN1HVw==
- dependencies:
- builtin-modules "^1.0.0"
-
-is-ci@^1.0.10:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
- integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
- dependencies:
- ci-info "^1.5.0"
-
-is-ci@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867"
- integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==
- dependencies:
- ci-info "^3.2.0"
-
-is-cidr@^5.0.5:
- version "5.0.5"
- resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-5.0.5.tgz#6898e3e84a320cecaa505654b33463399baf9e8e"
- integrity sha512-zDlCvz2v8dBpumuGD4/fc7wzFKY6UYOvFW29JWSstdJoByGN3TKwS0tFA9VWc7DM01VOVOn/DaR84D8Mihp9Rg==
- dependencies:
- cidr-regex "^4.0.4"
-
-is-core-module@^2.13.0, is-core-module@^2.8.1:
- version "2.13.1"
- resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
- integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
- dependencies:
- hasown "^2.0.0"
-
-is-date-object@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
- integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==
- dependencies:
- has-tostringtag "^1.0.0"
-
-is-extglob@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
- integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
-
-is-fullwidth-code-point@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
- integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==
- dependencies:
- number-is-nan "^1.0.0"
-
-is-fullwidth-code-point@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
- integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==
-
-is-fullwidth-code-point@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
- integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
-
-is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
- integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
- dependencies:
- is-extglob "^2.1.1"
-
-is-installed-globally@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80"
- integrity sha512-ERNhMg+i/XgDwPIPF3u24qpajVreaiSuvpb1Uu0jugw7KKcxGyCX8cgp8P5fwTmAuXku6beDHHECdKArjlg7tw==
- dependencies:
- global-dirs "^0.1.0"
- is-path-inside "^1.0.0"
-
-is-installed-globally@~0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520"
- integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==
- dependencies:
- global-dirs "^3.0.0"
- is-path-inside "^3.0.2"
-
-is-interactive@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90"
- integrity sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==
-
-is-lambda@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
- integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==
-
-is-npm@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
- integrity sha512-9r39FIr3d+KD9SbX0sfMsHzb5PP3uimOiwr3YupUaUFG4W0l1U57Rx3utpttV7qz5U3jmrO5auUa04LU9pyHsg==
-
-is-number@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
- integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
-
-is-obj@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
- integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==
-
-is-path-inside@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
- integrity sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==
- dependencies:
- path-is-inside "^1.0.1"
-
-is-path-inside@^3.0.2, is-path-inside@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
- integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
-
-is-redirect@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
- integrity sha512-cr/SlUEe5zOGmzvj9bUyC4LVvkNVAXu4GytXLNMr1pny+a65MpQ9IJzFHD5vi7FyJgb4qt27+eS3TuQnqB+RQw==
-
-is-regex@^1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
- integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
- dependencies:
- call-bind "^1.0.2"
- has-tostringtag "^1.0.0"
-
-is-retry-allowed@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4"
- integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==
-
-is-stream@^1.0.0, is-stream@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
- integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==
-
-is-stream@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
- integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
-
-is-stream@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac"
- integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==
-
-is-typedarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
- integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==
-
-is-unicode-supported@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
- integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
-
-is-unicode-supported@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714"
- integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==
-
-is-unicode-supported@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz#fdf32df9ae98ff6ab2cedc155a5a6e895701c451"
- integrity sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==
-
-isarray@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
- integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==
-
-isarray@^2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
- integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
-
-isarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
- integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
-
-isexe@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
- integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
-
-isexe@^3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d"
- integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==
-
-isstream@~0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
- integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==
-
-jackspeak@^2.3.6:
- version "2.3.6"
- resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8"
- integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==
- dependencies:
- "@isaacs/cliui" "^8.0.2"
- optionalDependencies:
- "@pkgjs/parseargs" "^0.11.0"
-
-jiti@^1.21.0:
- version "1.21.0"
- resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
- integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
-
-jiti@^1.21.6:
- version "1.21.6"
- resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268"
- integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==
-
-joi@^17.11.0:
- version "17.13.1"
- resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.1.tgz#9c7b53dc3b44dd9ae200255cc3b398874918a6ca"
- integrity sha512-vaBlIKCyo4FCUtCm7Eu4QZd/q02bWcxfUO6YSXAZOWF6gzcLBeba8kwotUdYJjDLW8Cz8RywsSOqiNJZW0mNvg==
- dependencies:
- "@hapi/hoek" "^9.3.0"
- "@hapi/topo" "^5.1.0"
- "@sideway/address" "^4.1.5"
- "@sideway/formula" "^3.0.1"
- "@sideway/pinpoint" "^2.0.0"
-
-js-tokens@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
- integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-
-js-yaml@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
- integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
- dependencies:
- argparse "^2.0.1"
-
-jsbn@1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040"
- integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==
-
-jsbn@~0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
- integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==
-
-jsesc@^2.5.1:
- version "2.5.2"
- resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
- integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
-
-json-buffer@3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
- integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
-
-json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
- integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
-
-json-parse-even-better-errors@^2.3.0:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
- integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
-
-json-parse-even-better-errors@^3.0.0, json-parse-even-better-errors@^3.0.1:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz#b43d35e89c0f3be6b5fbbe9dc6c82467b30c28da"
- integrity sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==
-
-json-schema-traverse@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
- integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
-
-json-schema@0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
- integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
-
-json-stable-stringify-without-jsonify@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
- integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
-
-json-stable-stringify@^1.0.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz#52d4361b47d49168bcc4e564189a42e5a7439454"
- integrity sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==
- dependencies:
- call-bind "^1.0.5"
- isarray "^2.0.5"
- jsonify "^0.0.1"
- object-keys "^1.1.1"
-
-json-stringify-nice@^1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz#2c937962b80181d3f317dd39aa323e14f5a60a67"
- integrity sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==
-
-json-stringify-safe@~5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
- integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
-
-json5@^2.2.2, json5@^2.2.3:
- version "2.2.3"
- resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
- integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
-
-jsonfile@^6.0.1:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
- integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
- dependencies:
- universalify "^2.0.0"
- optionalDependencies:
- graceful-fs "^4.1.6"
-
-jsonify@^0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978"
- integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==
-
-jsonparse@^1.2.0, jsonparse@^1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
- integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
-
-jsprim@^1.2.2:
- version "1.4.2"
- resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb"
- integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==
- dependencies:
- assert-plus "1.0.0"
- extsprintf "1.3.0"
- json-schema "0.4.0"
- verror "1.10.0"
-
-jsprim@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d"
- integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==
- dependencies:
- assert-plus "1.0.0"
- extsprintf "1.3.0"
- json-schema "0.4.0"
- verror "1.10.0"
-
-just-diff-apply@^5.2.0:
- version "5.5.0"
- resolved "https://registry.yarnpkg.com/just-diff-apply/-/just-diff-apply-5.5.0.tgz#771c2ca9fa69f3d2b54e7c3f5c1dfcbcc47f9f0f"
- integrity sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==
-
-just-diff@^6.0.0:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/just-diff/-/just-diff-6.0.2.tgz#03b65908543ac0521caf6d8eb85035f7d27ea285"
- integrity sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==
-
-kdbush@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-3.0.0.tgz#f8484794d47004cc2d85ed3a79353dbe0abc2bf0"
- integrity sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==
-
-keyv@^4.5.3:
- version "4.5.4"
- resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
- integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
- dependencies:
- json-buffer "3.0.1"
-
-kind-of@^6.0.2:
- version "6.0.3"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
- integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
-
-kleur@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
- integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
-
-latest-version@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15"
- integrity sha512-Be1YRHWWlZaSsrz2U+VInk+tO0EwLIyV+23RhWLINJYwg/UIikxjlj3MhH37/6/EDCAusjajvMkMMUXRaMWl/w==
- dependencies:
- package-json "^4.0.0"
-
-lazy-ass@1.6.0, lazy-ass@^1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513"
- integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==
-
-lazy-property@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/lazy-property/-/lazy-property-1.0.0.tgz#84ddc4b370679ba8bd4cdcfa4c06b43d57111147"
- integrity sha512-O52TK7FHpBPzdtvc5GoF0EPLQIBMqrAupANPGBidPkrDpl9IXlzuma3T+m0o0OpkRVPmTu3SDoT7985lw4KbNQ==
-
-lcid@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
- integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
- dependencies:
- invert-kv "^2.0.0"
-
-leaflet@1.7.1:
- version "1.7.1"
- resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.7.1.tgz#10d684916edfe1bf41d688a3b97127c0322a2a19"
- integrity sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw==
-
-lettersanitizer@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/lettersanitizer/-/lettersanitizer-1.0.5.tgz#6ca7dc5688f199793f12aa599c34a4cea5b61378"
- integrity sha512-OEJjdlRE96uKB0VfMi4nb3hBctYl1Ss6DQg9SPXRpGcjaBjcmDaibp0ZIdQu1TPwMAEvWC8xRqIcTAooElSDIg==
-
-levn@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
- integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
- dependencies:
- prelude-ls "^1.2.1"
- type-check "~0.4.0"
-
-libnpmaccess@^8.0.1:
- version "8.0.5"
- resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-8.0.5.tgz#ef14fecab8385669e91d6be27971ae448064211f"
- integrity sha512-E6dwnlk39LNlveG++BZmPA63aOnfQ+VL59Dp5S9Tp8ifkl66iFQtGgZ183JkX6BUI4URlYdtt+EJxxTpkV+m4g==
- dependencies:
- npm-package-arg "^11.0.2"
- npm-registry-fetch "^17.0.0"
-
-libnpmdiff@^6.0.3:
- version "6.1.1"
- resolved "https://registry.yarnpkg.com/libnpmdiff/-/libnpmdiff-6.1.1.tgz#7d19707bbfef9a5e30f11445a03044d545138f59"
- integrity sha512-oMIRnApo1tI/nD0fWjf9DAudrkAI+7G2go1y9gd0MKLmlMnZ6Tp44T6vvWgH2iTLzSax745l0zr2twfzSUutZg==
- dependencies:
- "@npmcli/arborist" "^7.2.1"
- "@npmcli/installed-package-contents" "^2.1.0"
- binary-extensions "^2.3.0"
- diff "^5.1.0"
- minimatch "^9.0.4"
- npm-package-arg "^11.0.2"
- pacote "^18.0.1"
- tar "^6.2.1"
-
-libnpmexec@^8.0.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/libnpmexec/-/libnpmexec-8.1.0.tgz#9273575a385827918cd2a75559800a7048f5f69b"
- integrity sha512-ZU2J7bcr9VGjld4g+mRTcIsZWwnuqiENxifcXLCXhh7uvjpRn67zV9+RLhVfYcAZkibDKnYCczNCVNhuPx4PKg==
- dependencies:
- "@npmcli/arborist" "^7.2.1"
- "@npmcli/run-script" "^8.1.0"
- ci-info "^4.0.0"
- npm-package-arg "^11.0.2"
- pacote "^18.0.1"
- proc-log "^4.2.0"
- read "^3.0.1"
- read-package-json-fast "^3.0.2"
- semver "^7.3.7"
- walk-up-path "^3.0.1"
-
-libnpmfund@^5.0.1:
- version "5.0.9"
- resolved "https://registry.yarnpkg.com/libnpmfund/-/libnpmfund-5.0.9.tgz#af650c139bc5023ae7171bbeb8d694e4b77b6791"
- integrity sha512-OkzHaMutdBx5KLaIo11oOUrnd3wq0rID82pZL+tle9e4YkLU8Vz2t/hiLDo4w9I3sTETqcGD3U9DKFK0xZu+8g==
- dependencies:
- "@npmcli/arborist" "^7.2.1"
-
-libnpmhook@^10.0.0:
- version "10.0.4"
- resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-10.0.4.tgz#88f7325fcaec0eb33cb11574f0264df059146a2a"
- integrity sha512-es/OEs25sjld/rZacdPLyT8gV637LezZBgwWBUoXgSQ3mPj+fV6flfgWt9se9l7qtK4D+YaTMKRlXxAdU5S/Cg==
- dependencies:
- aproba "^2.0.0"
- npm-registry-fetch "^17.0.0"
-
-libnpmorg@^6.0.1:
- version "6.0.5"
- resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-6.0.5.tgz#98a7cc2a75eabf4b445b25028b758629f54c76c5"
- integrity sha512-VPyye2JYLZXGnnGU1guOgtzwp08KI2dzcNEYfdjBbaMYm98HwmkWyXjfXcXQm+p06FRCmBDrVwXk3FaSLopcYw==
- dependencies:
- aproba "^2.0.0"
- npm-registry-fetch "^17.0.0"
-
-libnpmpack@^7.0.0:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/libnpmpack/-/libnpmpack-7.0.1.tgz#1aa358df9c9b88b9c2730161e6abeaec98cf98d2"
- integrity sha512-/Q2eVsJG3/5wivozBote/wpIHZvDAXHY7N5FFKKJMitZ1kZeF2lUZuBdCjNAatuzcfOSO1kcp13EIFXWiN9v9w==
- dependencies:
- "@npmcli/arborist" "^7.2.1"
- "@npmcli/run-script" "^8.1.0"
- npm-package-arg "^11.0.2"
- pacote "^18.0.1"
-
-libnpmpublish@^9.0.2:
- version "9.0.7"
- resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-9.0.7.tgz#cbb49224be3ed0bc463fa16520601c9fe6bf6cb4"
- integrity sha512-RGqpwlV6kaeTGDtcDSdBVjglW6HBMdJCLwWusGdfWUx94+QDJoH5dK+xeSyvZ/FcczX7aTHE9ZOoA0/y+ybfyA==
- dependencies:
- ci-info "^4.0.0"
- normalize-package-data "^6.0.0"
- npm-package-arg "^11.0.2"
- npm-registry-fetch "^17.0.0"
- proc-log "^4.2.0"
- semver "^7.3.7"
- sigstore "^2.2.0"
- ssri "^10.0.5"
-
-libnpmsearch@^7.0.0:
- version "7.0.4"
- resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-7.0.4.tgz#d3ce8d351007b1eec9b8157ccf41d61a5640cd04"
- integrity sha512-CdVupvMB61WrY07noIb7uVzO/NegsFIyPakyY7j0LE1RXNhbuCA3xBLIZZouDOb8Lg89HBOwYDhI8pdEaimq5g==
- dependencies:
- npm-registry-fetch "^17.0.0"
-
-libnpmteam@^6.0.0:
- version "6.0.4"
- resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-6.0.4.tgz#8725a1d83acdec22c45598c75695d63ea5fc0508"
- integrity sha512-HwOxPhuYsp9SjB/2YaeubzNJsSxobl8vqJvlli+gCAFGgBEcZLBSg/8FXkKsaZmim13Yd18Rz4DUhQUSuOwD5g==
- dependencies:
- aproba "^2.0.0"
- npm-registry-fetch "^17.0.0"
-
-libnpmversion@^6.0.0:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/libnpmversion/-/libnpmversion-6.0.1.tgz#9f2edc1fd402cd46114eefdecdee94dc0c6f6972"
- integrity sha512-uKnItKLfd9YNEP7NhPTytNY1atY1kZ+rAa+FkfExMBUtZa4beeBR10kcHx8ZaGVHtCyaQo64uiVlxUdQ5QwkTg==
- dependencies:
- "@npmcli/git" "^5.0.6"
- "@npmcli/run-script" "^8.1.0"
- json-parse-even-better-errors "^3.0.0"
- proc-log "^4.2.0"
- semver "^7.3.7"
-
-libnpx@10.2.2:
- version "10.2.2"
- resolved "https://registry.yarnpkg.com/libnpx/-/libnpx-10.2.2.tgz#5a4171b9b92dd031463ef66a4af9f5cbd6b09572"
- integrity sha512-ujaYToga1SAX5r7FU5ShMFi88CWpY75meNZtr6RtEyv4l2ZK3+Wgvxq2IqlwWBiDZOqhumdeiocPS1aKrCMe3A==
- dependencies:
- dotenv "^5.0.1"
- npm-package-arg "^6.0.0"
- rimraf "^2.6.2"
- safe-buffer "^5.1.0"
- update-notifier "^2.3.0"
- which "^1.3.0"
- y18n "^4.0.0"
- yargs "^11.0.0"
-
-lilconfig@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
- integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
-
-lilconfig@^3.0.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.1.tgz#9d8a246fa753106cfc205fd2d77042faca56e5e3"
- integrity sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==
-
-lines-and-columns@^1.1.6:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
- integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
-
-linkify-it@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421"
- integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==
- dependencies:
- uc.micro "^2.0.0"
-
-linkifyjs@^4.1.0:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-4.1.3.tgz#0edbc346428a7390a23ea2e5939f76112c9ae07f"
- integrity sha512-auMesunaJ8yfkHvK4gfg1K0SaKX/6Wn9g2Aac/NwX+l5VdmFZzo/hdPGxEOETj+ryRa4/fiOPjeeKURSAJx1sg==
-
-listr2@^3.8.3:
- version "3.14.0"
- resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e"
- integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==
- dependencies:
- cli-truncate "^2.1.0"
- colorette "^2.0.16"
- log-update "^4.0.0"
- p-map "^4.0.0"
- rfdc "^1.3.0"
- rxjs "^7.5.1"
- through "^2.3.8"
- wrap-ansi "^7.0.0"
-
-locate-path@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
- integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==
- dependencies:
- p-locate "^2.0.0"
- path-exists "^3.0.0"
-
-locate-path@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
- integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
- dependencies:
- p-locate "^5.0.0"
-
-lockfile@~1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609"
- integrity sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==
- dependencies:
- signal-exit "^3.0.2"
-
-lodash-es@^4.17.21:
- version "4.17.21"
- resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
- integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
-
-lodash._baseuniq@~4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
- integrity sha512-Ja1YevpHZctlI5beLA7oc5KNDhGcPixFhcqSiORHNsp/1QTv7amAXzw+gu4YOvErqVlMVyIJGgtzeepCnnur0A==
- dependencies:
- lodash._createset "~4.0.0"
- lodash._root "~3.0.0"
-
-lodash._createset@~4.0.0:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
- integrity sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA==
-
-lodash._root@~3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
- integrity sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ==
-
-lodash.castarray@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115"
- integrity sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==
-
-lodash.clonedeep@^4.5.0, lodash.clonedeep@~4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
- integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==
-
-lodash.isequal@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
- integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
-
-lodash.isplainobject@^4.0.6:
- version "4.0.6"
- resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
- integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
-
-lodash.merge@^4.6.2:
- version "4.6.2"
- resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
- integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
-
-lodash.once@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
- integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
-
-lodash.union@~4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
- integrity sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==
-
-lodash.uniq@~4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
- integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==
-
-lodash.without@~4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac"
- integrity sha512-M3MefBwfDhgKgINVuBJCO1YR3+gf6s9HNJsIiZ/Ru77Ws6uTb9eBuvrkpzO+9iLoAaRodGuq7tyrPCx+74QYGQ==
-
-lodash@^4.17.21:
- version "4.17.21"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
- integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-
-log-symbols@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
- integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
- dependencies:
- chalk "^4.1.0"
- is-unicode-supported "^0.1.0"
-
-log-symbols@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-6.0.0.tgz#bb95e5f05322651cac30c0feb6404f9f2a8a9439"
- integrity sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==
- dependencies:
- chalk "^5.3.0"
- is-unicode-supported "^1.3.0"
-
-log-update@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1"
- integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==
- dependencies:
- ansi-escapes "^4.3.0"
- cli-cursor "^3.1.0"
- slice-ansi "^4.0.0"
- wrap-ansi "^6.2.0"
-
-lowercase-keys@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
- integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
-
-lru-cache@^10.0.1, lru-cache@^10.2.0:
- version "10.2.2"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878"
- integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==
-
-lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@~4.1.1:
- version "4.1.5"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
- integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
- dependencies:
- pseudomap "^1.0.2"
- yallist "^2.1.2"
-
-lru-cache@^5.1.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
- integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
- dependencies:
- yallist "^3.0.2"
-
-lucide-vue-next@^0.378.0:
- version "0.378.0"
- resolved "https://registry.yarnpkg.com/lucide-vue-next/-/lucide-vue-next-0.378.0.tgz#118fab81a4e345926e737204a3f9b83cd6ab662b"
- integrity sha512-tz2IUhdOf1q0x1mPOTZEJZYfXVLreQorO2ax4M+CxGOTgCNgXH3cljIWWfJ4jUvxn5rbkFlGPbl9EIfIelZBRA==
-
-magic-string@^0.30.10:
- version "0.30.10"
- resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e"
- integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==
- dependencies:
- "@jridgewell/sourcemap-codec" "^1.4.15"
-
-make-dir@^1.0.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
- integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
- dependencies:
- pify "^3.0.0"
-
-make-fetch-happen@^13.0.0, make-fetch-happen@^13.0.1:
- version "13.0.1"
- resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz#273ba2f78f45e1f3a6dca91cede87d9fa4821e36"
- integrity sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==
- dependencies:
- "@npmcli/agent" "^2.0.0"
- cacache "^18.0.0"
- http-cache-semantics "^4.1.1"
- is-lambda "^1.0.1"
- minipass "^7.0.2"
- minipass-fetch "^3.0.0"
- minipass-flush "^1.0.5"
- minipass-pipeline "^1.2.4"
- negotiator "^0.6.3"
- proc-log "^4.2.0"
- promise-retry "^2.0.1"
- ssri "^10.0.0"
-
-make-fetch-happen@^2.4.13:
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-2.6.0.tgz#8474aa52198f6b1ae4f3094c04e8370d35ea8a38"
- integrity sha512-FFq0lNI0ax+n9IWzWpH8A4JdgYiAp2DDYIZ3rsaav8JDe8I+72CzK6PQW/oom15YDZpV5bYW/9INd6nIJ2ZfZw==
- dependencies:
- agentkeepalive "^3.3.0"
- cacache "^10.0.0"
- http-cache-semantics "^3.8.0"
- http-proxy-agent "^2.0.0"
- https-proxy-agent "^2.1.0"
- lru-cache "^4.1.1"
- mississippi "^1.2.0"
- node-fetch-npm "^2.0.2"
- promise-retry "^1.1.1"
- socks-proxy-agent "^3.0.1"
- ssri "^5.0.0"
-
-map-age-cleaner@^0.1.1:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
- integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
- dependencies:
- p-defer "^1.0.0"
-
-map-stream@~0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
- integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==
-
-maplibre-gl@^2.1.9:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/maplibre-gl/-/maplibre-gl-2.4.0.tgz#2b53dbf526626bf4ee92ad4f33f13ef09e5af182"
- integrity sha512-csNFylzntPmHWidczfgCZpvbTSmhaWvLRj9e1ezUDBEPizGgshgm3ea1T5TCNEEBq0roauu7BPuRZjA3wO4KqA==
- dependencies:
- "@mapbox/geojson-rewind" "^0.5.2"
- "@mapbox/jsonlint-lines-primitives" "^2.0.2"
- "@mapbox/mapbox-gl-supported" "^2.0.1"
- "@mapbox/point-geometry" "^0.1.0"
- "@mapbox/tiny-sdf" "^2.0.5"
- "@mapbox/unitbezier" "^0.0.1"
- "@mapbox/vector-tile" "^1.3.1"
- "@mapbox/whoots-js" "^3.1.0"
- "@types/geojson" "^7946.0.10"
- "@types/mapbox__point-geometry" "^0.1.2"
- "@types/mapbox__vector-tile" "^1.3.0"
- "@types/pbf" "^3.0.2"
- csscolorparser "~1.0.3"
- earcut "^2.2.4"
- geojson-vt "^3.2.1"
- gl-matrix "^3.4.3"
- global-prefix "^3.0.0"
- murmurhash-js "^1.0.0"
- pbf "^3.2.1"
- potpack "^1.0.2"
- quickselect "^2.0.0"
- supercluster "^7.1.5"
- tinyqueue "^2.0.3"
- vt-pbf "^3.1.3"
-
-markdown-it@^14.0.0:
- version "14.1.0"
- resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45"
- integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==
- dependencies:
- argparse "^2.0.1"
- entities "^4.4.0"
- linkify-it "^5.0.0"
- mdurl "^2.0.0"
- punycode.js "^2.3.1"
- uc.micro "^2.1.0"
-
-mdurl@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0"
- integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==
-
-mem@^4.0.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
- integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
- dependencies:
- map-age-cleaner "^0.1.1"
- mimic-fn "^2.0.0"
- p-is-promise "^2.0.0"
-
-merge-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
- integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
-
-merge2@^1.3.0:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
- integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
-
-micromatch@^4.0.4, micromatch@^4.0.5:
- version "4.0.5"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
- integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
- dependencies:
- braces "^3.0.2"
- picomatch "^2.3.1"
-
-mime-db@1.52.0:
- version "1.52.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
- integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
-
-mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.7:
- version "2.1.35"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
- integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
- dependencies:
- mime-db "1.52.0"
-
-mime@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7"
- integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==
-
-mimic-fn@^2.0.0, mimic-fn@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
- integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
-
-mimic-fn@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc"
- integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==
-
-minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
- integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
- dependencies:
- brace-expansion "^1.1.7"
-
-minimatch@^9.0.0, minimatch@^9.0.1, minimatch@^9.0.4:
- version "9.0.4"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51"
- integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==
- dependencies:
- brace-expansion "^2.0.1"
-
-minimatch@^9.0.3:
- version "9.0.5"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
- integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
- dependencies:
- brace-expansion "^2.0.1"
-
-minimist@^1.2.0, minimist@^1.2.6, minimist@^1.2.8:
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
- integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
-
-minipass-collect@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-2.0.1.tgz#1621bc77e12258a12c60d34e2276ec5c20680863"
- integrity sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==
- dependencies:
- minipass "^7.0.3"
-
-minipass-fetch@^3.0.0:
- version "3.0.5"
- resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.5.tgz#f0f97e40580affc4a35cc4a1349f05ae36cb1e4c"
- integrity sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==
- dependencies:
- minipass "^7.0.3"
- minipass-sized "^1.0.3"
- minizlib "^2.1.2"
- optionalDependencies:
- encoding "^0.1.13"
-
-minipass-flush@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373"
- integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==
- dependencies:
- minipass "^3.0.0"
-
-minipass-json-stream@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz#7edbb92588fbfc2ff1db2fc10397acb7b6b44aa7"
- integrity sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==
- dependencies:
- jsonparse "^1.3.1"
- minipass "^3.0.0"
-
-minipass-pipeline@^1.2.4:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c"
- integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==
- dependencies:
- minipass "^3.0.0"
-
-minipass-sized@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70"
- integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==
- dependencies:
- minipass "^3.0.0"
-
-minipass@^3.0.0:
- version "3.3.6"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
- integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
- dependencies:
- yallist "^4.0.0"
-
-minipass@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
- integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
-
-"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.2, minipass@^7.0.3, minipass@^7.0.4:
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.1.tgz#f7f85aff59aa22f110b20e27692465cf3bf89481"
- integrity sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==
-
-minizlib@^2.1.1, minizlib@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
- integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
- dependencies:
- minipass "^3.0.0"
- yallist "^4.0.0"
-
-mississippi@^1.2.0, mississippi@^1.3.0, mississippi@~1.3.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-1.3.1.tgz#2a8bb465e86550ac8b36a7b6f45599171d78671e"
- integrity sha512-/6rB8YXFbAtsUVRphIRQqB0+9c7VaPHCjVtvto+JqwVxgz8Zz+I+f68/JgQ+Pb4VlZb2svA9OtdXnHHsZz7ltg==
- dependencies:
- concat-stream "^1.5.0"
- duplexify "^3.4.2"
- end-of-stream "^1.1.0"
- flush-write-stream "^1.0.0"
- from2 "^2.1.0"
- parallel-transform "^1.1.0"
- pump "^1.0.0"
- pumpify "^1.3.3"
- stream-each "^1.1.0"
- through2 "^2.0.0"
-
-mississippi@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f"
- integrity sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==
- dependencies:
- concat-stream "^1.5.0"
- duplexify "^3.4.2"
- end-of-stream "^1.1.0"
- flush-write-stream "^1.0.0"
- from2 "^2.1.0"
- parallel-transform "^1.1.0"
- pump "^2.0.1"
- pumpify "^1.3.3"
- stream-each "^1.1.0"
- through2 "^2.0.0"
-
-mitt@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1"
- integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
-
-"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
- version "0.5.6"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
- integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
- dependencies:
- minimist "^1.2.6"
-
-mkdirp@^1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
- integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-
-mkdirp@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
- integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==
-
-mlly@^1.7.1:
- version "1.7.1"
- resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.1.tgz#e0336429bb0731b6a8e887b438cbdae522c8f32f"
- integrity sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==
- dependencies:
- acorn "^8.11.3"
- pathe "^1.1.2"
- pkg-types "^1.1.1"
- ufo "^1.5.3"
-
-move-concurrently@^1.0.1, move-concurrently@~1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
- integrity sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==
- dependencies:
- aproba "^1.1.1"
- copy-concurrently "^1.0.0"
- fs-write-stream-atomic "^1.0.8"
- mkdirp "^0.5.1"
- rimraf "^2.5.4"
- run-queue "^1.0.3"
-
-ms@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
- integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
-
-ms@2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
- integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-
-ms@^2.0.0, ms@^2.1.1, ms@^2.1.2:
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
- integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
-
-murmurhash-js@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/murmurhash-js/-/murmurhash-js-1.0.0.tgz#b06278e21fc6c37fa5313732b0412bcb6ae15f51"
- integrity sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==
-
-mute-stream@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e"
- integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==
-
-mute-stream@~0.0.4:
- version "0.0.8"
- resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
- integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
-
-mz@^2.7.0:
- version "2.7.0"
- resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
- integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
- dependencies:
- any-promise "^1.0.0"
- object-assign "^4.0.1"
- thenify-all "^1.0.0"
-
-nanoid@^3.3.7:
- version "3.3.7"
- resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
- integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
-
-nanoid@^5.0.6, nanoid@^5.0.7:
- version "5.0.7"
- resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-5.0.7.tgz#6452e8c5a816861fd9d2b898399f7e5fd6944cc6"
- integrity sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==
-
-natural-compare@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
- integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
-
-negotiator@^0.6.3:
- version "0.6.3"
- resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
- integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
-
-nice-try@^1.0.4:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
- integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
-
-node-fetch-native@^1.6.3:
- version "1.6.4"
- resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.4.tgz#679fc8fd8111266d47d7e72c379f1bed9acff06e"
- integrity sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==
-
-node-fetch-npm@^2.0.2:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz#6507d0e17a9ec0be3bec516958a497cec54bf5a4"
- integrity sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==
- dependencies:
- encoding "^0.1.11"
- json-parse-better-errors "^1.0.0"
- safe-buffer "^5.1.1"
-
-node-gyp@^10.0.0, node-gyp@^10.1.0:
- version "10.1.0"
- resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-10.1.0.tgz#75e6f223f2acb4026866c26a2ead6aab75a8ca7e"
- integrity sha512-B4J5M1cABxPc5PwfjhbV5hoy2DP9p8lFXASnEN6hugXOa61416tnTZ29x9sSwAd0o99XNIcpvDDy1swAExsVKA==
- dependencies:
- env-paths "^2.2.0"
- exponential-backoff "^3.1.1"
- glob "^10.3.10"
- graceful-fs "^4.2.6"
- make-fetch-happen "^13.0.0"
- nopt "^7.0.0"
- proc-log "^3.0.0"
- semver "^7.3.5"
- tar "^6.1.2"
- which "^4.0.0"
-
-node-gyp@~3.6.2:
- version "3.6.3"
- resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.3.tgz#369fcb09146ae2167f25d8d23d8b49cc1a110d8d"
- integrity sha512-7789TDMqJpv5iHxn1cAESCBEC/sBHAFxAvgXAcvzWenEWl0qf6E2Kk/Xwdl5ZclktUJzxJPVa27OMkBvaHKqCQ==
- dependencies:
- fstream "^1.0.0"
- glob "^7.0.3"
- graceful-fs "^4.1.2"
- minimatch "^3.0.2"
- mkdirp "^0.5.0"
- nopt "2 || 3"
- npmlog "0 || 1 || 2 || 3 || 4"
- osenv "0"
- request ">=2.9.0 <2.82.0"
- rimraf "2"
- semver "~5.3.0"
- tar "^2.0.0"
- which "1"
-
-node-releases@^2.0.14:
- version "2.0.14"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
- integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
-
-"nopt@2 || 3":
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
- integrity sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==
- dependencies:
- abbrev "1"
-
-nopt@^7.0.0, nopt@^7.2.0:
- version "7.2.1"
- resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.1.tgz#1cac0eab9b8e97c9093338446eddd40b2c8ca1e7"
- integrity sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==
- dependencies:
- abbrev "^2.0.0"
-
-nopt@~4.0.1:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
- integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==
- dependencies:
- abbrev "1"
- osenv "^0.1.4"
-
-normalize-package-data@^2.0.0, normalize-package-data@^2.4.0, "normalize-package-data@~1.0.1 || ^2.0.0":
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
- integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
- dependencies:
- hosted-git-info "^2.1.4"
- resolve "^1.10.0"
- semver "2 || 3 || 4 || 5"
- validate-npm-package-license "^3.0.1"
-
-normalize-package-data@^6.0.0:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-6.0.1.tgz#fa69e9452210f0fabf4d79ee08d0c2870c51ed88"
- integrity sha512-6rvCfeRW+OEZagAB4lMLSNuTNYZWLVtKccK79VSTf//yTY5VOCgcpH80O+bZK8Neps7pUnd5G+QlMg1yV/2iZQ==
- dependencies:
- hosted-git-info "^7.0.0"
- is-core-module "^2.8.1"
- semver "^7.3.5"
- validate-npm-package-license "^3.0.4"
-
-normalize-package-data@~2.4.0:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.2.tgz#6b2abd85774e51f7936f1395e45acb905dc849b2"
- integrity sha512-YcMnjqeoUckXTPKZSAsPjUPLxH85XotbpqK3w4RyCwdFQSU5FxxBys8buehkSfg0j9fKvV1hn7O0+8reEgkAiw==
- dependencies:
- hosted-git-info "^2.1.4"
- is-builtin-module "^1.0.0"
- semver "2 || 3 || 4 || 5"
- validate-npm-package-license "^3.0.1"
-
-normalize-path@^3.0.0, normalize-path@~3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
- integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
-
-normalize-range@^0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
- integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
-
-npm-audit-report@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-5.0.0.tgz#83ac14aeff249484bde81eff53c3771d5048cf95"
- integrity sha512-EkXrzat7zERmUhHaoren1YhTxFwsOu5jypE84k6632SXTHcQE1z8V51GC6GVZt8LxkC+tbBcKMUBZAgk8SUSbw==
-
-npm-bundled@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-3.0.1.tgz#cca73e15560237696254b10170d8f86dad62da25"
- integrity sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==
- dependencies:
- npm-normalize-package-bin "^3.0.0"
-
-npm-cache-filename@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz#ded306c5b0bfc870a9e9faf823bc5f283e05ae11"
- integrity sha512-5v2y1KG06izpGvZJDSBR5q1Ej+NaPDO05yAAWBJE6+3eiId0R176Gz3Qc2vEmJnE+VGul84g6Qpq8fXzD82/JA==
-
-npm-install-checks@^6.0.0, npm-install-checks@^6.2.0, npm-install-checks@^6.3.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-6.3.0.tgz#046552d8920e801fa9f919cad569545d60e826fe"
- integrity sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==
- dependencies:
- semver "^7.1.1"
-
-npm-install-checks@~3.0.0:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-3.0.2.tgz#ab2e32ad27baa46720706908e5b14c1852de44d9"
- integrity sha512-E4kzkyZDIWoin6uT5howP8VDvkM+E8IQDcHAycaAxMbwkqhIg5eEYALnXOl3Hq9MrkdQB/2/g1xwBINXdKSRkg==
- dependencies:
- semver "^2.3.0 || 3.x || 4 || 5"
-
-npm-normalize-package-bin@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
- integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==
-
-npm-normalize-package-bin@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz#25447e32a9a7de1f51362c61a559233b89947832"
- integrity sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==
-
-npm-package-arg@^11.0.0, npm-package-arg@^11.0.2:
- version "11.0.2"
- resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-11.0.2.tgz#1ef8006c4a9e9204ddde403035f7ff7d718251ca"
- integrity sha512-IGN0IAwmhDJwy13Wc8k+4PEbTPhpJnMtfR53ZbOyjkvmEcLS4nCwp6mvMWjS5sUjeiW3mpx6cHmuhKEu9XmcQw==
- dependencies:
- hosted-git-info "^7.0.0"
- proc-log "^4.0.0"
- semver "^7.3.5"
- validate-npm-package-name "^5.0.0"
-
-"npm-package-arg@^3.0.0 || ^4.0.0 || ^5.0.0", npm-package-arg@^5.1.2, npm-package-arg@~5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-5.1.2.tgz#fb18d17bb61e60900d6312619919bd753755ab37"
- integrity sha512-wJBsrf0qpypPT7A0LART18hCdyhpCMxeTtcb0X4IZO2jsP6Om7EHN1d9KSKiqD+KVH030RVNpWS9thk+pb7wzA==
- dependencies:
- hosted-git-info "^2.4.2"
- osenv "^0.1.4"
- semver "^5.1.0"
- validate-npm-package-name "^3.0.0"
-
-"npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0:
- version "6.1.1"
- resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.1.tgz#02168cb0a49a2b75bf988a28698de7b529df5cb7"
- integrity sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==
- dependencies:
- hosted-git-info "^2.7.1"
- osenv "^0.1.5"
- semver "^5.6.0"
- validate-npm-package-name "^3.0.0"
-
-npm-packlist@^8.0.0:
- version "8.0.2"
- resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-8.0.2.tgz#5b8d1d906d96d21c85ebbeed2cf54147477c8478"
- integrity sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==
- dependencies:
- ignore-walk "^6.0.4"
-
-npm-pick-manifest@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-1.0.4.tgz#a5ee6510c1fe7221c0bc0414e70924c14045f7e8"
- integrity sha512-MKxNdeyOZysPRTTbHtW0M5Fw38Jo/3ARsoGw5qjCfS+XGjvNB/Gb4qtAZUFmKPM2mVum+eX559eHvKywU856BQ==
- dependencies:
- npm-package-arg "^5.1.2"
- semver "^5.3.0"
-
-npm-pick-manifest@^9.0.0:
- version "9.0.1"
- resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-9.0.1.tgz#c90658bd726fe5bca9d2869f3e99359b8fcda046"
- integrity sha512-Udm1f0l2nXb3wxDpKjfohwgdFUSV50UVwzEIpDXVsbDMXVIEF81a/i0UhuQbhrPMMmdiq3+YMFLFIRVLs3hxQw==
- dependencies:
- npm-install-checks "^6.0.0"
- npm-normalize-package-bin "^3.0.0"
- npm-package-arg "^11.0.0"
- semver "^7.3.5"
-
-npm-profile@^9.0.2:
- version "9.0.2"
- resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-9.0.2.tgz#848328529932828fd3a33dcbf0d5fbe36d1e3eb6"
- integrity sha512-4S/fd/PNyGgjaGolsdUJFsnfEb+AxJzrrZC3I9qbTYZJ3PJy8T46tIWXA4pBoaeiGh2M2GRvK1K/xMQe1Xgbvw==
- dependencies:
- npm-registry-fetch "^17.0.0"
- proc-log "^4.0.0"
-
-npm-registry-client@~8.4.0:
- version "8.4.0"
- resolved "https://registry.yarnpkg.com/npm-registry-client/-/npm-registry-client-8.4.0.tgz#d52b901685647fc62a4c03eafecb6ceaa5018d4c"
- integrity sha512-PVNfqq0lyRdFnE//nDmn3CC9uqTsr8Bya9KPLIevlXMfkP0m4RpCVyFFk0W1Gfx436kKwyhLA6J+lV+rgR81gQ==
- dependencies:
- concat-stream "^1.5.2"
- graceful-fs "^4.1.6"
- normalize-package-data "~1.0.1 || ^2.0.0"
- npm-package-arg "^3.0.0 || ^4.0.0 || ^5.0.0"
- once "^1.3.3"
- request "^2.74.0"
- retry "^0.10.0"
- semver "2 >=2.2.1 || 3.x || 4 || 5"
- slide "^1.1.3"
- ssri "^4.1.2"
- optionalDependencies:
- npmlog "2 || ^3.1.0 || ^4.0.0"
-
-npm-registry-fetch@^17.0.0:
- version "17.0.1"
- resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-17.0.1.tgz#c13cfd4c022713f09d23af5fba8b6ec59a17609e"
- integrity sha512-fLu9MTdZTlJAHUek/VLklE6EpIiP3VZpTiuN7OOMCt2Sd67NCpSEetMaxHHEZiZxllp8ZLsUpvbEszqTFEc+wA==
- dependencies:
- "@npmcli/redact" "^2.0.0"
- make-fetch-happen "^13.0.0"
- minipass "^7.0.2"
- minipass-fetch "^3.0.0"
- minipass-json-stream "^1.0.1"
- minizlib "^2.1.2"
- npm-package-arg "^11.0.0"
- proc-log "^4.0.0"
-
-npm-run-path@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
- integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==
- dependencies:
- path-key "^2.0.0"
-
-npm-run-path@^4.0.0, npm-run-path@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
- integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
- dependencies:
- path-key "^3.0.0"
-
-npm-run-path@^5.1.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f"
- integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==
- dependencies:
- path-key "^4.0.0"
-
-npm-user-validate@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-2.0.1.tgz#097afbf0a2351e2a8f478f1ba07960b368f2a25c"
- integrity sha512-d17PKaF2h8LSGFl5j4b1gHOJt1fgH7YUcCm1kNSJvaLWWKXlBsuUvx0bBEkr0qhsVA9XP5LtRZ83hdlhm2QkgA==
-
-npm-user-validate@~1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.1.tgz#31428fc5475fe8416023f178c0ab47935ad8c561"
- integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw==
-
-npm@5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/npm/-/npm-5.1.0.tgz#cf8201e044018e9c89532041c90094541982b2c0"
- integrity sha512-pt5ClxEmY/dLpb60SmGQQBKi3nB6Ljx1FXmpoCUdAULlGqGVn2uCyXxPCWFbcuHGthT7qGiaGa1wOfs/UjGYMw==
- dependencies:
- JSONStream "~1.3.1"
- abbrev "~1.1.0"
- ansi-regex "~3.0.0"
- ansicolors "~0.3.2"
- ansistyles "~0.1.3"
- aproba "~1.1.2"
- archy "~1.0.0"
- bluebird "~3.5.0"
- cacache "~9.2.9"
- call-limit "~1.1.0"
- chownr "~1.0.1"
- cmd-shim "~2.0.2"
- columnify "~1.5.4"
- config-chain "~1.1.11"
- detect-indent "~5.0.0"
- dezalgo "~1.0.3"
- editor "~1.0.0"
- fs-vacuum "~1.2.10"
- fs-write-stream-atomic "~1.0.10"
- fstream "~1.0.11"
- fstream-npm "~1.2.1"
- glob "~7.1.2"
- graceful-fs "~4.1.11"
- has-unicode "~2.0.1"
- hosted-git-info "~2.5.0"
- iferr "~0.1.5"
- inflight "~1.0.6"
- inherits "~2.0.3"
- ini "~1.3.4"
- init-package-json "~1.10.1"
- lazy-property "~1.0.0"
- lockfile "~1.0.3"
- lodash._baseuniq "~4.6.0"
- lodash.clonedeep "~4.5.0"
- lodash.union "~4.6.0"
- lodash.uniq "~4.5.0"
- lodash.without "~4.4.0"
- lru-cache "~4.1.1"
- mississippi "~1.3.0"
- mkdirp "~0.5.1"
- move-concurrently "~1.0.1"
- node-gyp "~3.6.2"
- nopt "~4.0.1"
- normalize-package-data "~2.4.0"
- npm-cache-filename "~1.0.2"
- npm-install-checks "~3.0.0"
- npm-package-arg "~5.1.2"
- npm-registry-client "~8.4.0"
- npm-user-validate "~1.0.0"
- npmlog "~4.1.2"
- once "~1.4.0"
- opener "~1.4.3"
- osenv "~0.1.4"
- pacote "~2.7.38"
- path-is-inside "~1.0.2"
- promise-inflight "~1.0.1"
- read "~1.0.7"
- read-cmd-shim "~1.0.1"
- read-installed "~4.0.3"
- read-package-json "~2.0.9"
- read-package-tree "~5.1.6"
- readable-stream "~2.3.2"
- request "~2.81.0"
- retry "~0.10.1"
- rimraf "~2.6.1"
- safe-buffer "~5.1.1"
- semver "~5.3.0"
- sha "~2.0.1"
- slide "~1.1.6"
- sorted-object "~2.0.1"
- sorted-union-stream "~2.1.3"
- ssri "~4.1.6"
- strip-ansi "~4.0.0"
- tar "~2.2.1"
- text-table "~0.2.0"
- uid-number "0.0.6"
- umask "~1.1.0"
- unique-filename "~1.1.0"
- unpipe "~1.0.0"
- update-notifier "~2.2.0"
- uuid "~3.1.0"
- validate-npm-package-name "~3.0.0"
- which "~1.2.14"
- worker-farm "~1.3.1"
- wrappy "~1.0.2"
- write-file-atomic "~2.1.0"
-
-npm@^10.4.0:
- version "10.7.0"
- resolved "https://registry.yarnpkg.com/npm/-/npm-10.7.0.tgz#c87e0bbb7a53422670e423d0198120760f67c3b7"
- integrity sha512-FXylyYSXNjgXx3l82BT8RSQvCoGIQ3h8YdRFGKNvo3Pv/bKscK4pdWkx/onwTpHDqGw+oeLf4Rxln9WVyxAxlQ==
- dependencies:
- "@isaacs/string-locale-compare" "^1.1.0"
- "@npmcli/arborist" "^7.2.1"
- "@npmcli/config" "^8.0.2"
- "@npmcli/fs" "^3.1.0"
- "@npmcli/map-workspaces" "^3.0.6"
- "@npmcli/package-json" "^5.1.0"
- "@npmcli/promise-spawn" "^7.0.1"
- "@npmcli/redact" "^2.0.0"
- "@npmcli/run-script" "^8.1.0"
- "@sigstore/tuf" "^2.3.2"
- abbrev "^2.0.0"
- archy "~1.0.0"
- cacache "^18.0.2"
- chalk "^5.3.0"
- ci-info "^4.0.0"
- cli-columns "^4.0.0"
- fastest-levenshtein "^1.0.16"
- fs-minipass "^3.0.3"
- glob "^10.3.12"
- graceful-fs "^4.2.11"
- hosted-git-info "^7.0.1"
- ini "^4.1.2"
- init-package-json "^6.0.2"
- is-cidr "^5.0.5"
- json-parse-even-better-errors "^3.0.1"
- libnpmaccess "^8.0.1"
- libnpmdiff "^6.0.3"
- libnpmexec "^8.0.0"
- libnpmfund "^5.0.1"
- libnpmhook "^10.0.0"
- libnpmorg "^6.0.1"
- libnpmpack "^7.0.0"
- libnpmpublish "^9.0.2"
- libnpmsearch "^7.0.0"
- libnpmteam "^6.0.0"
- libnpmversion "^6.0.0"
- make-fetch-happen "^13.0.1"
- minimatch "^9.0.4"
- minipass "^7.0.4"
- minipass-pipeline "^1.2.4"
- ms "^2.1.2"
- node-gyp "^10.1.0"
- nopt "^7.2.0"
- normalize-package-data "^6.0.0"
- npm-audit-report "^5.0.0"
- npm-install-checks "^6.3.0"
- npm-package-arg "^11.0.2"
- npm-pick-manifest "^9.0.0"
- npm-profile "^9.0.2"
- npm-registry-fetch "^17.0.0"
- npm-user-validate "^2.0.0"
- p-map "^4.0.0"
- pacote "^18.0.3"
- parse-conflict-json "^3.0.1"
- proc-log "^4.2.0"
- qrcode-terminal "^0.12.0"
- read "^3.0.1"
- semver "^7.6.0"
- spdx-expression-parse "^4.0.0"
- ssri "^10.0.5"
- supports-color "^9.4.0"
- tar "^6.2.1"
- text-table "~0.2.0"
- tiny-relative-date "^1.3.0"
- treeverse "^3.0.0"
- validate-npm-package-name "^5.0.0"
- which "^4.0.0"
- write-file-atomic "^5.0.1"
-
-"npmlog@0 || 1 || 2 || 3 || 4", "npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@~4.1.2:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
- integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
- dependencies:
- are-we-there-yet "~1.1.2"
- console-control-strings "~1.1.0"
- gauge "~2.7.3"
- set-blocking "~2.0.0"
-
-npx@^10.2.2:
- version "10.2.2"
- resolved "https://registry.yarnpkg.com/npx/-/npx-10.2.2.tgz#de4be1b76e6bcbf750486925b34a07eed1db01b4"
- integrity sha512-eImmySusyeWphzs5iNh791XbZnZG0FSNvM4KSah34pdQQIDsdTDhIwg1sjN3AIVcjGLpbQ/YcfqHPshKZQK1fA==
- dependencies:
- libnpx "10.2.2"
- npm "5.1.0"
-
-nth-check@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
- integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==
- dependencies:
- boolbase "^1.0.0"
-
-number-is-nan@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
- integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==
-
-nypm@^0.3.8:
- version "0.3.9"
- resolved "https://registry.yarnpkg.com/nypm/-/nypm-0.3.9.tgz#ab74c55075737466847611aa33c3c67741c01d8f"
- integrity sha512-BI2SdqqTHg2d4wJh8P9A1W+bslg33vOE9IZDY6eR2QC+Pu1iNBVZUqczrd43rJb+fMzHU7ltAYKsEFY/kHMFcw==
- dependencies:
- citty "^0.1.6"
- consola "^3.2.3"
- execa "^8.0.1"
- pathe "^1.1.2"
- pkg-types "^1.1.1"
- ufo "^1.5.3"
-
-oauth-sign@~0.8.1:
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
- integrity sha512-VlF07iu3VV3+BTXj43Nmp6Irt/G7j/NgEctUS6IweH1RGhURjjCc2NWtzXFPXXWWfc7hgbXQdtiQu2LGp6MxUg==
-
-oauth-sign@~0.9.0:
- version "0.9.0"
- resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
- integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-
-object-assign@^4.0.1, object-assign@^4.1.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
- integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
-
-object-hash@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
- integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
-
-object-inspect@^1.13.1:
- version "1.13.1"
- resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
- integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
-
-object-is@^1.1.5:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07"
- integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==
- dependencies:
- call-bind "^1.0.7"
- define-properties "^1.2.1"
-
-object-keys@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
- integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
-
-ofetch@^1.3.4:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.4.tgz#7ea65ced3c592ec2b9906975ae3fe1d26a56f635"
- integrity sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==
- dependencies:
- destr "^2.0.3"
- node-fetch-native "^1.6.3"
- ufo "^1.5.3"
-
-ohash@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/ohash/-/ohash-1.1.3.tgz#f12c3c50bfe7271ce3fd1097d42568122ccdcf07"
- integrity sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==
-
-once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0, once@~1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
- integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
- dependencies:
- wrappy "1"
-
-onetime@^5.1.0, onetime@^5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
- integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
- dependencies:
- mimic-fn "^2.1.0"
-
-onetime@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4"
- integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==
- dependencies:
- mimic-fn "^4.0.0"
-
-opener@~1.4.3:
- version "1.4.3"
- resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
- integrity sha512-4Im9TrPJcjAYyGR5gBe3yZnBzw5n3Bfh1ceHHGNOpMurINKc6RdSIPXMyon4BZacJbJc36lLkhipioGbWh5pwg==
-
-optionator@^0.9.3:
- version "0.9.4"
- resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734"
- integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==
- dependencies:
- deep-is "^0.1.3"
- fast-levenshtein "^2.0.6"
- levn "^0.4.1"
- prelude-ls "^1.2.1"
- type-check "^0.4.0"
- word-wrap "^1.2.5"
-
-ora@^8.0.1:
- version "8.0.1"
- resolved "https://registry.yarnpkg.com/ora/-/ora-8.0.1.tgz#6dcb9250a629642cbe0d2df3a6331ad6f7a2af3e"
- integrity sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==
- dependencies:
- chalk "^5.3.0"
- cli-cursor "^4.0.0"
- cli-spinners "^2.9.2"
- is-interactive "^2.0.0"
- is-unicode-supported "^2.0.0"
- log-symbols "^6.0.0"
- stdin-discarder "^0.2.1"
- string-width "^7.0.0"
- strip-ansi "^7.1.0"
-
-orderedmap@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-2.1.1.tgz#61481269c44031c449915497bf5a4ad273c512d2"
- integrity sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==
-
-os-homedir@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
- integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==
-
-os-locale@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
- integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
- dependencies:
- execa "^1.0.0"
- lcid "^2.0.0"
- mem "^4.0.0"
-
-os-tmpdir@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
- integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
-
-osenv@0, osenv@^0.1.4, osenv@^0.1.5, osenv@~0.1.4:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
- integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
- dependencies:
- os-homedir "^1.0.0"
- os-tmpdir "^1.0.0"
-
-ospath@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b"
- integrity sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==
-
-p-defer@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
- integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==
-
-p-finally@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
- integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
-
-p-is-promise@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
- integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
-
-p-limit@^1.1.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
- integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
- dependencies:
- p-try "^1.0.0"
-
-p-limit@^3.0.2:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
- integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
- dependencies:
- yocto-queue "^0.1.0"
-
-p-locate@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
- integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==
- dependencies:
- p-limit "^1.1.0"
-
-p-locate@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
- integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
- dependencies:
- p-limit "^3.0.2"
-
-p-map@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
- integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
- dependencies:
- aggregate-error "^3.0.0"
-
-p-try@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
- integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==
-
-package-json@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed"
- integrity sha512-q/R5GrMek0vzgoomq6rm9OX+3PQve8sLwTirmK30YB3Cu0Bbt9OX9M/SIUnroN5BGJkzwGsFwDaRGD9EwBOlCA==
- dependencies:
- got "^6.7.1"
- registry-auth-token "^3.0.1"
- registry-url "^3.0.3"
- semver "^5.1.0"
-
-pacote@^18.0.0, pacote@^18.0.1, pacote@^18.0.3:
- version "18.0.6"
- resolved "https://registry.yarnpkg.com/pacote/-/pacote-18.0.6.tgz#ac28495e24f4cf802ef911d792335e378e86fac7"
- integrity sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==
- dependencies:
- "@npmcli/git" "^5.0.0"
- "@npmcli/installed-package-contents" "^2.0.1"
- "@npmcli/package-json" "^5.1.0"
- "@npmcli/promise-spawn" "^7.0.0"
- "@npmcli/run-script" "^8.0.0"
- cacache "^18.0.0"
- fs-minipass "^3.0.0"
- minipass "^7.0.2"
- npm-package-arg "^11.0.0"
- npm-packlist "^8.0.0"
- npm-pick-manifest "^9.0.0"
- npm-registry-fetch "^17.0.0"
- proc-log "^4.0.0"
- promise-retry "^2.0.1"
- sigstore "^2.2.0"
- ssri "^10.0.0"
- tar "^6.1.11"
-
-pacote@~2.7.38:
- version "2.7.38"
- resolved "https://registry.yarnpkg.com/pacote/-/pacote-2.7.38.tgz#5091f8774298c26c3eca24606037f1bb73db74c1"
- integrity sha512-XxHUyHQB7QCVBxoXeVu0yKxT+2PvJucsc0+1E+6f95lMUxEAYERgSAc71ckYXrYr35Ew3xFU/LrhdIK21GQFFA==
- dependencies:
- bluebird "^3.5.0"
- cacache "^9.2.9"
- glob "^7.1.2"
- lru-cache "^4.1.1"
- make-fetch-happen "^2.4.13"
- minimatch "^3.0.4"
- mississippi "^1.2.0"
- normalize-package-data "^2.4.0"
- npm-package-arg "^5.1.2"
- npm-pick-manifest "^1.0.4"
- osenv "^0.1.4"
- promise-inflight "^1.0.1"
- promise-retry "^1.1.1"
- protoduck "^4.0.0"
- safe-buffer "^5.1.1"
- semver "^5.3.0"
- ssri "^4.1.6"
- tar-fs "^1.15.3"
- tar-stream "^1.5.4"
- unique-filename "^1.1.0"
- which "^1.2.12"
-
-parallel-transform@^1.1.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc"
- integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==
- dependencies:
- cyclist "^1.0.1"
- inherits "^2.0.3"
- readable-stream "^2.1.5"
-
-parchment@^1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/parchment/-/parchment-1.1.4.tgz#aeded7ab938fe921d4c34bc339ce1168bc2ffde5"
- integrity sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==
-
-parent-module@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
- integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
- dependencies:
- callsites "^3.0.0"
-
-parse-conflict-json@^3.0.0, parse-conflict-json@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/parse-conflict-json/-/parse-conflict-json-3.0.1.tgz#67dc55312781e62aa2ddb91452c7606d1969960c"
- integrity sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw==
- dependencies:
- json-parse-even-better-errors "^3.0.0"
- just-diff "^6.0.0"
- just-diff-apply "^5.2.0"
-
-parse-json@^5.0.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
- integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
- 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"
-
-parse-unit@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/parse-unit/-/parse-unit-1.0.1.tgz#7e1bb6d5bef3874c28e392526a2541170291eecf"
- integrity sha512-hrqldJHokR3Qj88EIlV/kAyAi/G5R2+R56TBANxNMy0uPlYcttx0jnMW6Yx5KsKPSbC3KddM/7qQm3+0wEXKxg==
-
-path-browserify@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
- integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==
-
-path-exists@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
- integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==
-
-path-exists@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
- integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
-
-path-is-absolute@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
- integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
-
-path-is-inside@^1.0.1, path-is-inside@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
- integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==
-
-path-key@^2.0.0, path-key@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
- integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==
-
-path-key@^3.0.0, path-key@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
- integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
-
-path-key@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18"
- integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
-
-path-parse@^1.0.7:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
- integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
-
-path-scurry@^1.11.0:
- version "1.11.1"
- resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
- integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
- dependencies:
- lru-cache "^10.2.0"
- minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
-
-path-type@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
- integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
-
-pathe@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
- integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
-
-pause-stream@0.0.11:
- version "0.0.11"
- resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
- integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==
- dependencies:
- through "~2.3"
-
-pbf@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/pbf/-/pbf-3.2.1.tgz#b4c1b9e72af966cd82c6531691115cc0409ffe2a"
- integrity sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==
- dependencies:
- ieee754 "^1.1.12"
- resolve-protobuf-schema "^2.1.0"
-
-pend@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
- integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
-
-perfect-debounce@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz#9c2e8bc30b169cc984a58b7d5b28049839591d2a"
- integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==
-
-performance-now@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
- integrity sha512-YHk5ez1hmMR5LOkb9iJkLKqoBlL7WD5M8ljC75ZfzXriuBIVNuecaXuU7e+hOwyqf24Wxhh7Vxgt7Hnw9288Tg==
-
-performance-now@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
- integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==
-
-picocolors@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
- integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
-
-picocolors@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1"
- integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
-
-picocolors@^1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
- integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
-
-picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
- integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
-
-pify@^2.2.0, pify@^2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
- integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
-
-pify@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
- integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==
-
-pinia@^2.1.7:
- version "2.1.7"
- resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.1.7.tgz#4cf5420d9324ca00b7b4984d3fbf693222115bbc"
- integrity sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==
- dependencies:
- "@vue/devtools-api" "^6.5.0"
- vue-demi ">=0.14.5"
-
-pirates@^4.0.1:
- version "4.0.6"
- resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
- integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==
-
-pkg-types@^1.1.1:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.1.3.tgz#161bb1242b21daf7795036803f28e30222e476e3"
- integrity sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==
- dependencies:
- confbox "^0.1.7"
- mlly "^1.7.1"
- pathe "^1.1.2"
-
-postcss-import@^15.1.0:
- version "15.1.0"
- resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70"
- integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==
- dependencies:
- postcss-value-parser "^4.0.0"
- read-cache "^1.0.0"
- resolve "^1.1.7"
-
-postcss-js@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2"
- integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==
- dependencies:
- camelcase-css "^2.0.1"
-
-postcss-load-config@^4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3"
- integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==
- dependencies:
- lilconfig "^3.0.0"
- yaml "^2.3.4"
-
-postcss-nested@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c"
- integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==
- dependencies:
- postcss-selector-parser "^6.0.11"
-
-postcss-selector-parser@6.0.10:
- version "6.0.10"
- resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
- integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
- dependencies:
- cssesc "^3.0.0"
- util-deprecate "^1.0.2"
-
-postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.15:
- version "6.0.16"
- resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz#3b88b9f5c5abd989ef4e2fc9ec8eedd34b20fb04"
- integrity sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==
- dependencies:
- cssesc "^3.0.0"
- util-deprecate "^1.0.2"
-
-postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
- integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
-
-postcss@^8.4.23, postcss@^8.4.38:
- version "8.4.38"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e"
- integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==
- dependencies:
- nanoid "^3.3.7"
- picocolors "^1.0.0"
- source-map-js "^1.2.0"
-
-postcss@^8.4.40:
- version "8.4.41"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.41.tgz#d6104d3ba272d882fe18fc07d15dc2da62fa2681"
- integrity sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==
- dependencies:
- nanoid "^3.3.7"
- picocolors "^1.0.1"
- source-map-js "^1.2.0"
-
-postcss@^8.4.43:
- version "8.4.47"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365"
- integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==
- dependencies:
- nanoid "^3.3.7"
- picocolors "^1.1.0"
- source-map-js "^1.2.1"
-
-potpack@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.2.tgz#23b99e64eb74f5741ffe7656b5b5c4ddce8dfc14"
- integrity sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==
-
-prelude-ls@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
- integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
-
-prepend-http@^1.0.1:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
- integrity sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==
-
-prettier-linter-helpers@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
- integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
- dependencies:
- fast-diff "^1.1.2"
-
-prettier@^3.0.3:
- version "3.2.5"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368"
- integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==
-
-prettier@^3.2.5:
- version "3.3.2"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a"
- integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==
-
-pretty-bytes@^5.6.0:
- version "5.6.0"
- resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
- integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
-
-prismjs@^1.14.0:
- version "1.29.0"
- resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12"
- integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==
-
-proc-log@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8"
- integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==
-
-proc-log@^4.0.0, proc-log@^4.1.0, proc-log@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-4.2.0.tgz#b6f461e4026e75fdfe228b265e9f7a00779d7034"
- integrity sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==
-
-process-nextick-args@~2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
- integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
-
-process@^0.11.10:
- version "0.11.10"
- resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
- integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
-
-proggy@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/proggy/-/proggy-2.0.0.tgz#154bb0e41d3125b518ef6c79782455c2c47d94e1"
- integrity sha512-69agxLtnI8xBs9gUGqEnK26UfiexpHy+KUpBQWabiytQjnn5wFY8rklAi7GRfABIuPNnQ/ik48+LGLkYYJcy4A==
-
-promise-all-reject-late@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz#f8ebf13483e5ca91ad809ccc2fcf25f26f8643c2"
- integrity sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==
-
-promise-call-limit@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/promise-call-limit/-/promise-call-limit-3.0.1.tgz#3570f7a3f2aaaf8e703623a552cd74749688cf19"
- integrity sha512-utl+0x8gIDasV5X+PI5qWEPqH6fJS0pFtQ/4gZ95xfEFb/89dmh+/b895TbFDBLiafBvxD/PGTKfvxl4kH/pQg==
-
-promise-inflight@^1.0.1, promise-inflight@~1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
- integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==
-
-promise-retry@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d"
- integrity sha512-StEy2osPr28o17bIW776GtwO6+Q+M9zPiZkYfosciUUMYqjhU/ffwRAH0zN2+uvGyUsn8/YICIHRzLbPacpZGw==
- dependencies:
- err-code "^1.0.0"
- retry "^0.10.0"
-
-promise-retry@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22"
- integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==
- dependencies:
- err-code "^2.0.2"
- retry "^0.12.0"
-
-prompts@^2.4.2:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
- integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
- dependencies:
- kleur "^3.0.3"
- sisteransi "^1.0.5"
-
-promzard@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee"
- integrity sha512-JZeYqd7UAcHCwI+sTOeUDYkvEU+1bQ7iE0UT1MgB/tERkAPkesW46MrpIySzODi+owTjZtiF8Ay5j9m60KmMBw==
- dependencies:
- read "1"
-
-promzard@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/promzard/-/promzard-1.0.2.tgz#2226e7c6508b1da3471008ae17066a7c3251e660"
- integrity sha512-2FPputGL+mP3jJ3UZg/Dl9YOkovB7DX0oOr+ck5QbZ5MtORtds8k/BZdn+02peDLI8/YWbmzx34k5fA+fHvCVQ==
- dependencies:
- read "^3.0.1"
-
-prosemirror-changeset@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/prosemirror-changeset/-/prosemirror-changeset-2.2.1.tgz#dae94b63aec618fac7bb9061648e6e2a79988383"
- integrity sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==
- dependencies:
- prosemirror-transform "^1.0.0"
-
-prosemirror-collab@^1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz#0e8c91e76e009b53457eb3b3051fb68dad029a33"
- integrity sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==
- dependencies:
- prosemirror-state "^1.0.0"
-
-prosemirror-commands@^1.0.0, prosemirror-commands@^1.5.2:
- version "1.5.2"
- resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.5.2.tgz#e94aeea52286f658cd984270de9b4c3fff580852"
- integrity sha512-hgLcPaakxH8tu6YvVAaILV2tXYsW3rAdDR8WNkeKGcgeMVQg3/TMhPdVoh7iAmfgVjZGtcOSjKiQaoeKjzd2mQ==
- dependencies:
- prosemirror-model "^1.0.0"
- prosemirror-state "^1.0.0"
- prosemirror-transform "^1.0.0"
-
-prosemirror-dropcursor@^1.8.1:
- version "1.8.1"
- resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.1.tgz#49b9fb2f583e0d0f4021ff87db825faa2be2832d"
- integrity sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==
- dependencies:
- prosemirror-state "^1.0.0"
- prosemirror-transform "^1.1.0"
- prosemirror-view "^1.1.0"
-
-prosemirror-gapcursor@^1.3.2:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz#5fa336b83789c6199a7341c9493587e249215cb4"
- integrity sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==
- dependencies:
- prosemirror-keymap "^1.0.0"
- prosemirror-model "^1.0.0"
- prosemirror-state "^1.0.0"
- prosemirror-view "^1.0.0"
-
-prosemirror-history@^1.0.0, prosemirror-history@^1.3.2:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/prosemirror-history/-/prosemirror-history-1.4.0.tgz#1edbce630aaf21b808e5a5cd798a09976ecb1827"
- integrity sha512-UUiGzDVcqo1lovOPdi9YxxUps3oBFWAIYkXLu3Ot+JPv1qzVogRbcizxK3LhHmtaUxclohgiOVesRw5QSlMnbQ==
- dependencies:
- prosemirror-state "^1.2.2"
- prosemirror-transform "^1.0.0"
- prosemirror-view "^1.31.0"
- rope-sequence "^1.3.0"
-
-prosemirror-inputrules@^1.3.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/prosemirror-inputrules/-/prosemirror-inputrules-1.4.0.tgz#ef1519bb2cb0d1e0cec74bad1a97f1c1555068bb"
- integrity sha512-6ygpPRuTJ2lcOXs9JkefieMst63wVJBgHZGl5QOytN7oSZs3Co/BYbc3Yx9zm9H37Bxw8kVzCnDsihsVsL4yEg==
- dependencies:
- prosemirror-state "^1.0.0"
- prosemirror-transform "^1.0.0"
-
-prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2, prosemirror-keymap@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz#14a54763a29c7b2704f561088ccf3384d14eb77e"
- integrity sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==
- dependencies:
- prosemirror-state "^1.0.0"
- w3c-keyname "^2.2.0"
-
-prosemirror-markdown@^1.12.0:
- version "1.12.0"
- resolved "https://registry.yarnpkg.com/prosemirror-markdown/-/prosemirror-markdown-1.12.0.tgz#d2de09d37897abf7adb6293d925ff132dac5b0a6"
- integrity sha512-6F5HS8Z0HDYiS2VQDZzfZP6A0s/I0gbkJy8NCzzDMtcsz3qrfqyroMMeoSjAmOhDITyon11NbXSzztfKi+frSQ==
- dependencies:
- markdown-it "^14.0.0"
- prosemirror-model "^1.0.0"
-
-prosemirror-menu@^1.2.4:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/prosemirror-menu/-/prosemirror-menu-1.2.4.tgz#3cfdc7c06d10f9fbd1bce29082c498bd11a0a79a"
- integrity sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==
- dependencies:
- crelt "^1.0.0"
- prosemirror-commands "^1.0.0"
- prosemirror-history "^1.0.0"
- prosemirror-state "^1.0.0"
-
-prosemirror-model@^1.0.0, prosemirror-model@^1.19.0, prosemirror-model@^1.19.4, prosemirror-model@^1.20.0, prosemirror-model@^1.21.0, prosemirror-model@^1.8.1:
- version "1.21.0"
- resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.21.0.tgz#2d69ed04b4e7c441c3eb87c1c964fab4f9b217df"
- integrity sha512-zLpS1mVCZLA7VTp82P+BfMiYVPcX1/z0Mf3gsjKZtzMWubwn2pN7CceMV0DycjlgE5JeXPR7UF4hJPbBV98oWA==
- dependencies:
- orderedmap "^2.0.0"
-
-prosemirror-schema-basic@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.2.tgz#6695f5175e4628aab179bf62e5568628b9cfe6c7"
- integrity sha512-/dT4JFEGyO7QnNTe9UaKUhjDXbTNkiWTq/N4VpKaF79bBjSExVV2NXmJpcM7z/gD7mbqNjxbmWW5nf1iNSSGnw==
- dependencies:
- prosemirror-model "^1.19.0"
-
-prosemirror-schema-list@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.3.0.tgz#05374702cf35a3ba5e7ec31079e355a488d52519"
- integrity sha512-Hz/7gM4skaaYfRPNgr421CU4GSwotmEwBVvJh5ltGiffUJwm7C8GfN/Bc6DR1EKEp5pDKhODmdXXyi9uIsZl5A==
- dependencies:
- prosemirror-model "^1.0.0"
- prosemirror-state "^1.0.0"
- prosemirror-transform "^1.7.3"
-
-prosemirror-state@^1.0.0, prosemirror-state@^1.2.2, prosemirror-state@^1.3.1, prosemirror-state@^1.4.3:
- version "1.4.3"
- resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.4.3.tgz#94aecf3ffd54ec37e87aa7179d13508da181a080"
- integrity sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==
- dependencies:
- prosemirror-model "^1.0.0"
- prosemirror-transform "^1.0.0"
- prosemirror-view "^1.27.0"
-
-prosemirror-tables@^1.3.5:
- version "1.3.7"
- resolved "https://registry.yarnpkg.com/prosemirror-tables/-/prosemirror-tables-1.3.7.tgz#9d296bd432d2bc7dca90f14e5c3b5c5f61277f7a"
- integrity sha512-oEwX1wrziuxMtwFvdDWSFHVUWrFJWt929kVVfHvtTi8yvw+5ppxjXZkMG/fuTdFo+3DXyIPSKfid+Be1npKXDA==
- dependencies:
- prosemirror-keymap "^1.1.2"
- prosemirror-model "^1.8.1"
- prosemirror-state "^1.3.1"
- prosemirror-transform "^1.2.1"
- prosemirror-view "^1.13.3"
-
-prosemirror-trailing-node@^2.0.7:
- version "2.0.8"
- resolved "https://registry.yarnpkg.com/prosemirror-trailing-node/-/prosemirror-trailing-node-2.0.8.tgz#233ddcbda72de06f9b5d758d2a65a8cac482ea10"
- integrity sha512-ujRYhSuhQb1Jsarh1IHqb2KoSnRiD7wAMDGucP35DN7j5af6X7B18PfdPIrbwsPTqIAj0fyOvxbuPsWhNvylmA==
- dependencies:
- "@remirror/core-constants" "^2.0.2"
- escape-string-regexp "^4.0.0"
-
-prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1, prosemirror-transform@^1.7.3, prosemirror-transform@^1.8.0:
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.9.0.tgz#81fd1fbd887929a95369e6dd3d240c23c19313f8"
- integrity sha512-5UXkr1LIRx3jmpXXNKDhv8OyAOeLTGuXNwdVfg8x27uASna/wQkr9p6fD3eupGOi4PLJfbezxTyi/7fSJypXHg==
- dependencies:
- prosemirror-model "^1.21.0"
-
-prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.27.0, prosemirror-view@^1.31.0, prosemirror-view@^1.32.7:
- version "1.33.6"
- resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.33.6.tgz#85804eb922411af8e300a07f4f376722b15900b9"
- integrity sha512-zRLUNgLIQfd8IfGprsXxWTjdA8xEAFJe8cDNrOptj6Mop9sj+BMeVbJvceyAYCm5G2dOdT2prctH7K9dfnpIMw==
- dependencies:
- prosemirror-model "^1.20.0"
- prosemirror-state "^1.0.0"
- prosemirror-transform "^1.1.0"
-
-proto-list@~1.2.1:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
- integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==
-
-protocol-buffers-schema@^3.3.1:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz#77bc75a48b2ff142c1ad5b5b90c94cd0fa2efd03"
- integrity sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==
-
-protoduck@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-4.0.0.tgz#fe4874d8c7913366cfd9ead12453a22cd3657f8e"
- integrity sha512-9sxuz0YTU/68O98xuDn8NBxTVH9EuMhrBTxZdiBL0/qxRmWhB/5a8MagAebDa+98vluAZTs8kMZibCdezbRCeQ==
- dependencies:
- genfun "^4.0.1"
-
-proxy-from-env@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee"
- integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==
-
-proxy-from-env@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
- integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
-
-prr@~1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
- integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==
-
-ps-tree@1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd"
- integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==
- dependencies:
- event-stream "=3.3.4"
-
-pseudomap@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
- integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==
-
-psl@^1.1.28, psl@^1.1.33:
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
- integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==
-
-pump@^1.0.0:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954"
- integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==
- dependencies:
- end-of-stream "^1.1.0"
- once "^1.3.1"
-
-pump@^2.0.0, pump@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
- integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
- dependencies:
- end-of-stream "^1.1.0"
- once "^1.3.1"
-
-pump@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
- integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
- dependencies:
- end-of-stream "^1.1.0"
- once "^1.3.1"
-
-pumpify@^1.3.3:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce"
- integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==
- dependencies:
- duplexify "^3.6.0"
- inherits "^2.0.3"
- pump "^2.0.0"
-
-punycode.js@^2.3.1:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7"
- integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==
-
-punycode@^1.4.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
- integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==
-
-punycode@^2.1.0, punycode@^2.1.1:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
- integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
-
-qrcode-terminal@^0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819"
- integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==
-
-qs@6.10.4:
- version "6.10.4"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.4.tgz#6a3003755add91c0ec9eacdc5f878b034e73f9e7"
- integrity sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==
- dependencies:
- side-channel "^1.0.4"
-
-qs@^6.12.1:
- version "6.12.1"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.1.tgz#39422111ca7cbdb70425541cba20c7d7b216599a"
- integrity sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==
- dependencies:
- side-channel "^1.0.6"
-
-qs@~6.4.0:
- version "6.4.1"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.1.tgz#2bad97710a5b661c366b378b1e3a44a592ff45e6"
- integrity sha512-LQy1Q1fcva/UsnP/6Iaa4lVeM49WiOitu2T4hZCyA/elLKu37L99qcBJk4VCCk+rdLvnMzfKyiN3SZTqdAZGSQ==
-
-qs@~6.5.2:
- version "6.5.3"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
- integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
-
-querystringify@^2.1.1:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
- integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
-
-queue-microtask@^1.2.2:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
- integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
-
-quickselect@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-2.0.0.tgz#f19680a486a5eefb581303e023e98faaf25dd018"
- integrity sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==
-
-quill-delta@^3.6.2:
- version "3.6.3"
- resolved "https://registry.yarnpkg.com/quill-delta/-/quill-delta-3.6.3.tgz#b19fd2b89412301c60e1ff213d8d860eac0f1032"
- integrity sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==
- dependencies:
- deep-equal "^1.0.1"
- extend "^3.0.2"
- fast-diff "1.1.2"
-
-quill-delta@^4.2.2:
- version "4.2.2"
- resolved "https://registry.yarnpkg.com/quill-delta/-/quill-delta-4.2.2.tgz#015397d046e0a3bed087cd8a51f98c11a1b8f351"
- integrity sha512-qjbn82b/yJzOjstBgkhtBjN2TNK+ZHP/BgUQO+j6bRhWQQdmj2lH6hXG7+nwwLF41Xgn//7/83lxs9n2BkTtTg==
- dependencies:
- fast-diff "1.2.0"
- lodash.clonedeep "^4.5.0"
- lodash.isequal "^4.5.0"
-
-quill@^1.3.7:
- version "1.3.7"
- resolved "https://registry.yarnpkg.com/quill/-/quill-1.3.7.tgz#da5b2f3a2c470e932340cdbf3668c9f21f9286e8"
- integrity sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==
- dependencies:
- clone "^2.1.1"
- deep-equal "^1.0.1"
- eventemitter3 "^2.0.3"
- extend "^3.0.2"
- parchment "^1.1.4"
- quill-delta "^3.6.2"
-
-radix-vue@^1.7.3:
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/radix-vue/-/radix-vue-1.8.5.tgz#d16118470f318706a3b18726dbebcf9a67d111e8"
- integrity sha512-aWRa/tc5EHS2U4h8YTovRtwSMt+Sbk4QRekNTpkshCWlq353mpGBsp0ME/4seOxWn7JKze8NA3pDx/AQuH2tMw==
- dependencies:
- "@floating-ui/dom" "^1.6.5"
- "@floating-ui/vue" "^1.0.6"
- "@internationalized/date" "^3.5.4"
- "@internationalized/number" "^3.5.3"
- "@tanstack/vue-virtual" "^3.5.0"
- "@vueuse/core" "^10.5.0"
- "@vueuse/shared" "^10.5.0"
- aria-hidden "^1.2.3"
- defu "^6.1.4"
- fast-deep-equal "^3.1.3"
- nanoid "^5.0.6"
-
-radix-vue@latest:
- version "1.9.3"
- resolved "https://registry.yarnpkg.com/radix-vue/-/radix-vue-1.9.3.tgz#4fa171a570a366730114bbd065531b2ce6037359"
- integrity sha512-9pewcgzghM+B+FO1h9mMsZa/csVH6hElpN1sqmG4/qoeieiDG0i4nhMjS7p2UOz11EEdVm7eLandHSPyx7hYhg==
- dependencies:
- "@floating-ui/dom" "^1.6.7"
- "@floating-ui/vue" "^1.1.0"
- "@internationalized/date" "^3.5.4"
- "@internationalized/number" "^3.5.3"
- "@tanstack/vue-virtual" "^3.8.1"
- "@vueuse/core" "^10.11.0"
- "@vueuse/shared" "^10.11.0"
- aria-hidden "^1.2.4"
- defu "^6.1.4"
- fast-deep-equal "^3.1.3"
- nanoid "^5.0.7"
-
-rc9@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/rc9/-/rc9-2.1.2.tgz#6282ff638a50caa0a91a31d76af4a0b9cbd1080d"
- integrity sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==
- dependencies:
- defu "^6.1.4"
- destr "^2.0.3"
-
-rc@^1.0.1, rc@^1.1.6:
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
- integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
- dependencies:
- deep-extend "^0.6.0"
- ini "~1.3.0"
- minimist "^1.2.0"
- strip-json-comments "~2.0.1"
-
-read-cache@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
- integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
- dependencies:
- pify "^2.3.0"
-
-read-cmd-shim@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz#640a08b473a49043e394ae0c7a34dd822c73b9bb"
- integrity sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==
-
-read-cmd-shim@~1.0.1:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16"
- integrity sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==
- dependencies:
- graceful-fs "^4.1.2"
-
-read-installed@~4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/read-installed/-/read-installed-4.0.3.tgz#ff9b8b67f187d1e4c29b9feb31f6b223acd19067"
- integrity sha512-O03wg/IYuV/VtnK2h/KXEt9VIbMUFbk3ERG0Iu4FhLZw0EP0T9znqrYDGn6ncbEsXUFaUjiVAWXHzxwt3lhRPQ==
- dependencies:
- debuglog "^1.0.1"
- read-package-json "^2.0.0"
- readdir-scoped-modules "^1.0.0"
- semver "2 || 3 || 4 || 5"
- slide "~1.1.3"
- util-extend "^1.0.1"
- optionalDependencies:
- graceful-fs "^4.1.2"
-
-read-package-json-fast@^3.0.0, read-package-json-fast@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz#394908a9725dc7a5f14e70c8e7556dff1d2b1049"
- integrity sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==
- dependencies:
- json-parse-even-better-errors "^3.0.0"
- npm-normalize-package-bin "^3.0.0"
-
-"read-package-json@1 || 2", read-package-json@^2.0.0:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.2.tgz#6992b2b66c7177259feb8eaac73c3acd28b9222a"
- integrity sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==
- dependencies:
- glob "^7.1.1"
- json-parse-even-better-errors "^2.3.0"
- normalize-package-data "^2.0.0"
- npm-normalize-package-bin "^1.0.0"
-
-read-package-json@~2.0.9:
- version "2.0.13"
- resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.13.tgz#2e82ebd9f613baa6d2ebe3aa72cefe3f68e41f4a"
- integrity sha512-/1dZ7TRZvGrYqE0UAfN6qQb5GYBsNcqS1C0tNK601CFOJmtHI7NIGXwetEPU/OtoFHZL3hDxm4rolFFVE9Bnmg==
- dependencies:
- glob "^7.1.1"
- json-parse-better-errors "^1.0.1"
- normalize-package-data "^2.0.0"
- slash "^1.0.0"
- optionalDependencies:
- graceful-fs "^4.1.2"
-
-read-package-tree@~5.1.6:
- version "5.1.6"
- resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.1.6.tgz#4f03e83d0486856fb60d97c94882841c2a7b1b7a"
- integrity sha512-FCX1aT3GWyY658wzDICef4p+n0dB+ENRct8E/Qyvppj6xVpOYerBHfUu7OP5Rt1/393Tdglguf5ju5DEX4wZNg==
- dependencies:
- debuglog "^1.0.1"
- dezalgo "^1.0.0"
- once "^1.3.0"
- read-package-json "^2.0.0"
- readdir-scoped-modules "^1.0.0"
-
-read@1, read@~1.0.1, read@~1.0.7:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4"
- integrity sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==
- dependencies:
- mute-stream "~0.0.4"
-
-read@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/read/-/read-3.0.1.tgz#926808f0f7c83fa95f1ef33c0e2c09dbb28fd192"
- integrity sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==
- dependencies:
- mute-stream "^1.0.0"
-
-"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.2, readable-stream@~2.3.6:
- version "2.3.8"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
- integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.3"
- isarray "~1.0.0"
- process-nextick-args "~2.0.0"
- safe-buffer "~5.1.1"
- string_decoder "~1.1.1"
- util-deprecate "~1.0.1"
-
-readable-stream@~1.1.10:
- version "1.1.14"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
- integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "0.0.1"
- string_decoder "~0.10.x"
-
-readdir-scoped-modules@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309"
- integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==
- dependencies:
- debuglog "^1.0.1"
- dezalgo "^1.0.0"
- graceful-fs "^4.1.2"
- once "^1.3.0"
-
-readdirp@~3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
- integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
- dependencies:
- picomatch "^2.2.1"
-
-regenerator-runtime@^0.14.0:
- version "0.14.1"
- resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
- integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
-
-regexp.prototype.flags@^1.5.1:
- version "1.5.3"
- resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42"
- integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==
- dependencies:
- call-bind "^1.0.7"
- define-properties "^1.2.1"
- es-errors "^1.3.0"
- set-function-name "^2.0.2"
-
-registry-auth-token@^3.0.1:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e"
- integrity sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==
- dependencies:
- rc "^1.1.6"
- safe-buffer "^5.0.1"
-
-registry-url@^3.0.3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942"
- integrity sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==
- dependencies:
- rc "^1.0.1"
-
-request-progress@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe"
- integrity sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==
- dependencies:
- throttleit "^1.0.0"
-
-"request@>=2.9.0 <2.82.0", request@~2.81.0:
- version "2.81.0"
- resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
- integrity sha512-IZnsR7voF0miGSu29EXPRgPTuEsI/+aibNSBbN1pplrfartF5wDYGADz3iD9vmBVf2r00rckWZf8BtS5kk7Niw==
- dependencies:
- aws-sign2 "~0.6.0"
- aws4 "^1.2.1"
- caseless "~0.12.0"
- combined-stream "~1.0.5"
- extend "~3.0.0"
- forever-agent "~0.6.1"
- form-data "~2.1.1"
- har-validator "~4.2.1"
- hawk "~3.1.3"
- http-signature "~1.1.0"
- is-typedarray "~1.0.0"
- isstream "~0.1.2"
- json-stringify-safe "~5.0.1"
- mime-types "~2.1.7"
- oauth-sign "~0.8.1"
- performance-now "^0.2.0"
- qs "~6.4.0"
- safe-buffer "^5.0.1"
- stringstream "~0.0.4"
- tough-cookie "~2.3.0"
- tunnel-agent "^0.6.0"
- uuid "^3.0.0"
-
-request@^2.74.0:
- version "2.88.2"
- resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
- integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
- dependencies:
- aws-sign2 "~0.7.0"
- aws4 "^1.8.0"
- caseless "~0.12.0"
- combined-stream "~1.0.6"
- extend "~3.0.2"
- forever-agent "~0.6.1"
- form-data "~2.3.2"
- har-validator "~5.1.3"
- http-signature "~1.2.0"
- is-typedarray "~1.0.0"
- isstream "~0.1.2"
- json-stringify-safe "~5.0.1"
- mime-types "~2.1.19"
- oauth-sign "~0.9.0"
- performance-now "^2.1.0"
- qs "~6.5.2"
- safe-buffer "^5.1.2"
- tough-cookie "~2.5.0"
- tunnel-agent "^0.6.0"
- uuid "^3.3.2"
-
-require-directory@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
- integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
-
-require-main-filename@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
- integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==
-
-requires-port@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
- integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
-
-resolve-from@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
- integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
-
-resolve-protobuf-schema@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758"
- integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==
- dependencies:
- protocol-buffers-schema "^3.3.1"
-
-resolve@^1.1.7, resolve@^1.10.0, resolve@^1.19.0, resolve@^1.22.2:
- version "1.22.8"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
- integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
- dependencies:
- is-core-module "^2.13.0"
- path-parse "^1.0.7"
- supports-preserve-symlinks-flag "^1.0.0"
-
-restore-cursor@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
- integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
- dependencies:
- onetime "^5.1.0"
- signal-exit "^3.0.2"
-
-restore-cursor@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9"
- integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==
- dependencies:
- onetime "^5.1.0"
- signal-exit "^3.0.2"
-
-retry@^0.10.0, retry@~0.10.1:
- version "0.10.1"
- resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
- integrity sha512-ZXUSQYTHdl3uS7IuCehYfMzKyIDBNoAuUblvy5oGO5UJSUTmStUUVPXbA9Qxd173Bgre53yCQczQuHgRWAdvJQ==
-
-retry@^0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
- integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==
-
-reusify@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
- integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
-
-rfdc@^1.3.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f"
- integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==
-
-rimraf@2, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2:
- version "2.7.1"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
- integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
- dependencies:
- glob "^7.1.3"
-
-rimraf@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
- integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
- dependencies:
- glob "^7.1.3"
-
-rimraf@~2.6.1:
- version "2.6.3"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
- integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
- dependencies:
- glob "^7.1.3"
-
-robust-predicates@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771"
- integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==
-
-rollup@^4.20.0:
- version "4.24.0"
- resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.24.0.tgz#c14a3576f20622ea6a5c9cad7caca5e6e9555d05"
- integrity sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==
- dependencies:
- "@types/estree" "1.0.6"
- optionalDependencies:
- "@rollup/rollup-android-arm-eabi" "4.24.0"
- "@rollup/rollup-android-arm64" "4.24.0"
- "@rollup/rollup-darwin-arm64" "4.24.0"
- "@rollup/rollup-darwin-x64" "4.24.0"
- "@rollup/rollup-linux-arm-gnueabihf" "4.24.0"
- "@rollup/rollup-linux-arm-musleabihf" "4.24.0"
- "@rollup/rollup-linux-arm64-gnu" "4.24.0"
- "@rollup/rollup-linux-arm64-musl" "4.24.0"
- "@rollup/rollup-linux-powerpc64le-gnu" "4.24.0"
- "@rollup/rollup-linux-riscv64-gnu" "4.24.0"
- "@rollup/rollup-linux-s390x-gnu" "4.24.0"
- "@rollup/rollup-linux-x64-gnu" "4.24.0"
- "@rollup/rollup-linux-x64-musl" "4.24.0"
- "@rollup/rollup-win32-arm64-msvc" "4.24.0"
- "@rollup/rollup-win32-ia32-msvc" "4.24.0"
- "@rollup/rollup-win32-x64-msvc" "4.24.0"
- fsevents "~2.3.2"
-
-rope-sequence@^1.3.0:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.3.4.tgz#df85711aaecd32f1e756f76e43a415171235d425"
- integrity sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==
-
-run-parallel@^1.1.9:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
- integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
- dependencies:
- queue-microtask "^1.2.2"
-
-run-queue@^1.0.0, run-queue@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
- integrity sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==
- dependencies:
- aproba "^1.1.1"
-
-rw@1:
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
- integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==
-
-rxjs@^7.5.1, rxjs@^7.8.1:
- version "7.8.1"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543"
- integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==
- dependencies:
- tslib "^2.1.0"
-
-safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
- integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
-
-safe-buffer@~5.1.0, safe-buffer@~5.1.1:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
- integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-
-"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
- integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-
-sass@^1.70.0:
- version "1.77.1"
- resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.1.tgz#018cdfb206afd14724030c02e9fefd8f30a76cd0"
- integrity sha512-OMEyfirt9XEfyvocduUIOlUSkWOXS/LAt6oblR/ISXCTukyavjex+zQNm51pPCOiFKY1QpWvEH1EeCkgyV3I6w==
- dependencies:
- chokidar ">=3.0.0 <4.0.0"
- immutable "^4.0.0"
- source-map-js ">=0.6.2 <2.0.0"
-
-semver-diff@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
- integrity sha512-gL8F8L4ORwsS0+iQ34yCYv///jsOq0ZL7WP55d1HnJ32o7tyFYEFQZQA22mrLIacZdU6xecaBBZ+uEiffGNyXw==
- dependencies:
- semver "^5.0.3"
-
-"semver@2 >=2.2.1 || 3.x || 4 || 5", "semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", "semver@^2.3.0 || 3.x || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0, semver@^5.6.0:
- version "5.7.2"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
- integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
-
-semver@^6.3.1:
- version "6.3.1"
- resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
- integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
-
-semver@^7.1.1, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7, semver@^7.5.3, semver@^7.6.0:
- version "7.6.2"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
- integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
-
-semver@~5.3.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
- integrity sha512-mfmm3/H9+67MCVix1h+IXTpDwL6710LyHuk7+cWC9T1mE0qz4iHhh6r4hU2wrIT9iTsAAC2XQRvfblL028cpLw==
-
-set-blocking@^2.0.0, set-blocking@~2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
- integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
-
-set-function-length@^1.2.1:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
- integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
- dependencies:
- define-data-property "^1.1.4"
- es-errors "^1.3.0"
- function-bind "^1.1.2"
- get-intrinsic "^1.2.4"
- gopd "^1.0.1"
- has-property-descriptors "^1.0.2"
-
-set-function-name@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985"
- integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==
- dependencies:
- define-data-property "^1.1.4"
- es-errors "^1.3.0"
- functions-have-names "^1.2.3"
- has-property-descriptors "^1.0.2"
-
-sha@~2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/sha/-/sha-2.0.1.tgz#6030822fbd2c9823949f8f72ed6411ee5cf25aae"
- integrity sha512-Lj/GiNro+/4IIvhDvTo2HDqTmQkbqgg/O3lbkM5lMgagriGPpWamxtq1KJPx7mCvyF1/HG6Hs7zaYaj4xpfXbA==
- dependencies:
- graceful-fs "^4.1.2"
- readable-stream "^2.0.2"
-
-shadcn-vue@latest:
- version "0.10.5"
- resolved "https://registry.yarnpkg.com/shadcn-vue/-/shadcn-vue-0.10.5.tgz#51a2ecafe262238d5e8936a9fdd64f6d4d3e2c9d"
- integrity sha512-YMFbQrYTBhbHbOrVOuPoIia445dTzBvZEnadfwUypt0I5jERw8PL2Pt/0N251NqJtJj+o8Geaq+rHFNTWoJ+NA==
- dependencies:
- "@babel/core" "^7.24.4"
- "@babel/parser" "^7.24.4"
- "@vue/compiler-sfc" "^3.4"
- c12 "^1.10.0"
- commander "^12.0.0"
- consola "^3.2.3"
- detype "npm:detypes@^0.8.0"
- diff "^5.2.0"
- fs-extra "^11.2.0"
- https-proxy-agent "^7.0.4"
- lodash-es "^4.17.21"
- magic-string "^0.30.10"
- nypm "^0.3.8"
- ofetch "^1.3.4"
- ora "^8.0.1"
- pathe "^1.1.2"
- prompts "^2.4.2"
- radix-vue "^1.7.3"
- ts-morph "^22.0.0"
- tsconfig-paths "^4.2.0"
- zod "^3.23.3"
-
-shebang-command@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
- integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==
- dependencies:
- shebang-regex "^1.0.0"
-
-shebang-command@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
- integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
- dependencies:
- shebang-regex "^3.0.0"
-
-shebang-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
- integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==
-
-shebang-regex@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
- integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
-
-side-channel@^1.0.4, side-channel@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
- integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==
- dependencies:
- call-bind "^1.0.7"
- es-errors "^1.3.0"
- get-intrinsic "^1.2.4"
- object-inspect "^1.13.1"
-
-signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
- version "3.0.7"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
- integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
-
-signal-exit@^4.0.1, signal-exit@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
- integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
-
-sigstore@^2.2.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-2.3.0.tgz#c56b32818d4dc989f6ea3c0897f4d9bff5d14bed"
- integrity sha512-q+o8L2ebiWD1AxD17eglf1pFrl9jtW7FHa0ygqY6EKvibK8JHyq9Z26v9MZXeDiw+RbfOJ9j2v70M10Hd6E06A==
- dependencies:
- "@sigstore/bundle" "^2.3.1"
- "@sigstore/core" "^1.0.0"
- "@sigstore/protobuf-specs" "^0.3.1"
- "@sigstore/sign" "^2.3.0"
- "@sigstore/tuf" "^2.3.1"
- "@sigstore/verify" "^1.2.0"
-
-sisteransi@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
- integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
-
-slash@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
- integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==
-
-slice-ansi@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787"
- integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==
- dependencies:
- ansi-styles "^4.0.0"
- astral-regex "^2.0.0"
- is-fullwidth-code-point "^3.0.0"
-
-slice-ansi@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
- integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
- dependencies:
- ansi-styles "^4.0.0"
- astral-regex "^2.0.0"
- is-fullwidth-code-point "^3.0.0"
-
-slide@^1.1.3, slide@^1.1.5, slide@~1.1.3, slide@~1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
- integrity sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==
-
-smart-buffer@^1.0.13:
- version "1.1.15"
- resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16"
- integrity sha512-1+8bxygjTsNfvQe0/0pNBesTOlSHtOeG6b6LYbvsZCCHDKYZ40zcQo6YTnZBWrBSLWOCbrHljLdEmGMYebu7aQ==
-
-smart-buffer@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
- integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
-
-sntp@1.x.x:
- version "1.0.9"
- resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
- integrity sha512-7bgVOAnPj3XjrKY577S+puCKGCRlUrcrEdsMeRXlg9Ghf5df/xNi6sONUa43WrHUd3TjJBF7O04jYoiY0FVa0A==
- dependencies:
- hoek "2.x.x"
-
-socks-proxy-agent@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz#2eae7cf8e2a82d34565761539a7f9718c5617659"
- integrity sha512-ZwEDymm204mTzvdqyUqOdovVr2YRd2NYskrYrF2LXyZ9qDiMAoFESGK8CRphiO7rtbo2Y757k2Nia3x2hGtalA==
- dependencies:
- agent-base "^4.1.0"
- socks "^1.1.10"
-
-socks-proxy-agent@^8.0.3:
- version "8.0.3"
- resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz#6b2da3d77364fde6292e810b496cb70440b9b89d"
- integrity sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==
- dependencies:
- agent-base "^7.1.1"
- debug "^4.3.4"
- socks "^2.7.1"
-
-socks@^1.1.10:
- version "1.1.10"
- resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.10.tgz#5b8b7fc7c8f341c53ed056e929b7bf4de8ba7b5a"
- integrity sha512-ArX4vGPULWjKDKgUnW8YzfI2uXW7kzgkJuB0GnFBA/PfT3exrrOk+7Wk2oeb894Qf20u1PWv9LEgrO0Z82qAzA==
- dependencies:
- ip "^1.1.4"
- smart-buffer "^1.0.13"
-
-socks@^2.7.1:
- version "2.8.3"
- resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.3.tgz#1ebd0f09c52ba95a09750afe3f3f9f724a800cb5"
- integrity sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==
- dependencies:
- ip-address "^9.0.5"
- smart-buffer "^4.2.0"
-
-sorted-object@~2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/sorted-object/-/sorted-object-2.0.1.tgz#7d631f4bd3a798a24af1dffcfbfe83337a5df5fc"
- integrity sha512-oKAAs26HeTu3qbawzUGCkTOBv/5MRrcuJyRWwbfEnWdpXnXsj+WEM3HTvarV73tMcf9uBEZNZoNDVRL62VLxzA==
-
-sorted-union-stream@~2.1.3:
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/sorted-union-stream/-/sorted-union-stream-2.1.3.tgz#c7794c7e077880052ff71a8d4a2dbb4a9a638ac7"
- integrity sha512-RaKskQJZkmVREIwyAFho1RRU+sKjDdg51Crvxg2VxmIyiIrNhPNoJD/by5/pklWBXAZoO6LfAAGv8xd47p9TnQ==
- dependencies:
- from2 "^1.3.0"
- stream-iterate "^1.1.0"
-
-"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2, source-map-js@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
- integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
-
-source-map-js@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
- integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
-
-source-map@^0.5.7:
- version "0.5.7"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
- integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
-
-spdx-correct@^3.0.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c"
- integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==
- dependencies:
- spdx-expression-parse "^3.0.0"
- spdx-license-ids "^3.0.0"
-
-spdx-exceptions@^2.1.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66"
- integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==
-
-spdx-expression-parse@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
- integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
- dependencies:
- spdx-exceptions "^2.1.0"
- spdx-license-ids "^3.0.0"
-
-spdx-expression-parse@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz#a23af9f3132115465dac215c099303e4ceac5794"
- integrity sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==
- dependencies:
- spdx-exceptions "^2.1.0"
- spdx-license-ids "^3.0.0"
-
-spdx-license-ids@^3.0.0:
- version "3.0.17"
- resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c"
- integrity sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==
-
-split@0.3:
- version "0.3.3"
- resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
- integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==
- dependencies:
- through "2"
-
-sprintf-js@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
- integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==
-
-sshpk@^1.14.1, sshpk@^1.7.0:
- version "1.18.0"
- resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028"
- integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==
- dependencies:
- asn1 "~0.2.3"
- assert-plus "^1.0.0"
- bcrypt-pbkdf "^1.0.0"
- dashdash "^1.12.0"
- ecc-jsbn "~0.1.1"
- getpass "^0.1.1"
- jsbn "~0.1.0"
- safer-buffer "^2.0.2"
- tweetnacl "~0.14.0"
-
-ssri@^10.0.0, ssri@^10.0.5:
- version "10.0.6"
- resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.6.tgz#a8aade2de60ba2bce8688e3fa349bad05c7dc1e5"
- integrity sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==
- dependencies:
- minipass "^7.0.3"
-
-ssri@^4.1.2, ssri@^4.1.6, ssri@~4.1.6:
- version "4.1.6"
- resolved "https://registry.yarnpkg.com/ssri/-/ssri-4.1.6.tgz#0cb49b6ac84457e7bdd466cb730c3cb623e9a25b"
- integrity sha512-WUbCdgSAMQjTFZRWvSPpauryvREEA+Krn19rx67UlJEJx/M192ZHxMmJXjZ4tkdFm+Sb0SXGlENeQVlA5wY7kA==
- dependencies:
- safe-buffer "^5.1.0"
-
-ssri@^5.0.0, ssri@^5.2.4:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06"
- integrity sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==
- dependencies:
- safe-buffer "^5.1.1"
-
-start-server-and-test@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-2.0.3.tgz#15c53c85e23cba7698b498b8a2598cab95f3f802"
- integrity sha512-QsVObjfjFZKJE6CS6bSKNwWZCKBG6975/jKRPPGFfFh+yOQglSeGXiNWjzgQNXdphcBI9nXbyso9tPfX4YAUhg==
- dependencies:
- arg "^5.0.2"
- bluebird "3.7.2"
- check-more-types "2.24.0"
- debug "4.3.4"
- execa "5.1.1"
- lazy-ass "1.6.0"
- ps-tree "1.2.0"
- wait-on "7.2.0"
-
-stdin-discarder@^0.2.1:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.2.2.tgz#390037f44c4ae1a1ae535c5fe38dc3aba8d997be"
- integrity sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==
-
-stream-combiner@~0.0.4:
- version "0.0.4"
- resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
- integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==
- dependencies:
- duplexer "~0.1.1"
-
-stream-each@^1.1.0:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae"
- integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==
- dependencies:
- end-of-stream "^1.1.0"
- stream-shift "^1.0.0"
-
-stream-iterate@^1.1.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/stream-iterate/-/stream-iterate-1.2.0.tgz#2bd7c77296c1702a46488b8ad41f79865eecd4e1"
- integrity sha512-QVfGkdBQ8NzsSIiL3rV6AoFFWwMvlg1qpTwVQaMGY5XYThDUuNM4hYSzi8pbKlimTsWyQdaWRZE+jwlPsMiiZw==
- dependencies:
- readable-stream "^2.1.5"
- stream-shift "^1.0.0"
-
-stream-shift@^1.0.0:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b"
- integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==
-
-"string-width-cjs@npm:string-width@^4.2.0":
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
- integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.1"
-
-string-width@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
- integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==
- dependencies:
- code-point-at "^1.0.0"
- is-fullwidth-code-point "^1.0.0"
- strip-ansi "^3.0.0"
-
-"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
- integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.1"
-
-string-width@^2.0.0, string-width@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
- integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
- dependencies:
- is-fullwidth-code-point "^2.0.0"
- strip-ansi "^4.0.0"
-
-string-width@^5.0.1, string-width@^5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
- integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
- dependencies:
- eastasianwidth "^0.2.0"
- emoji-regex "^9.2.2"
- strip-ansi "^7.0.1"
-
-string-width@^7.0.0:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc"
- integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==
- dependencies:
- emoji-regex "^10.3.0"
- get-east-asian-width "^1.0.0"
- strip-ansi "^7.1.0"
-
-string_decoder@~0.10.x:
- version "0.10.31"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
- integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==
-
-string_decoder@~1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
- integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
- dependencies:
- safe-buffer "~5.1.0"
-
-stringstream@~0.0.4:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72"
- integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==
-
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
- integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
- dependencies:
- ansi-regex "^5.0.1"
-
-strip-ansi@^3.0.0, strip-ansi@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
- integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==
- dependencies:
- ansi-regex "^2.0.0"
-
-strip-ansi@^4.0.0, strip-ansi@~4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
- integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==
- dependencies:
- ansi-regex "^3.0.0"
-
-strip-ansi@^6.0.0, strip-ansi@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
- integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
- dependencies:
- ansi-regex "^5.0.1"
-
-strip-ansi@^7.0.1, strip-ansi@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
- integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
- dependencies:
- ansi-regex "^6.0.1"
-
-strip-bom@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
- integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
-
-strip-eof@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
- integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==
-
-strip-final-newline@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
- integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
-
-strip-final-newline@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd"
- integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==
-
-strip-json-comments@^3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
- integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
-
-strip-json-comments@~2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
- integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==
-
-striptags@^3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.2.0.tgz#cc74a137db2de8b0b9a370006334161f7dd67052"
- integrity sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw==
-
-stylis@4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51"
- integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==
-
-sucrase@^3.32.0:
- version "3.35.0"
- resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263"
- integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==
- dependencies:
- "@jridgewell/gen-mapping" "^0.3.2"
- commander "^4.0.0"
- glob "^10.3.10"
- lines-and-columns "^1.1.6"
- mz "^2.7.0"
- pirates "^4.0.1"
- ts-interface-checker "^0.1.9"
-
-supercluster@^7.1.5:
- version "7.1.5"
- resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-7.1.5.tgz#65a6ce4a037a972767740614c19051b64b8be5a3"
- integrity sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==
- dependencies:
- kdbush "^3.0.0"
-
-supports-color@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
- integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==
-
-supports-color@^5.3.0:
- version "5.5.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
- integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
- dependencies:
- has-flag "^3.0.0"
-
-supports-color@^7.1.0:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
- integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
- dependencies:
- has-flag "^4.0.0"
-
-supports-color@^8.1.1:
- version "8.1.1"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
- integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
- dependencies:
- has-flag "^4.0.0"
-
-supports-color@^9.4.0:
- version "9.4.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.4.0.tgz#17bfcf686288f531db3dea3215510621ccb55954"
- integrity sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==
-
-supports-preserve-symlinks-flag@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
- integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
-
-synckit@^0.8.6:
- version "0.8.8"
- resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7"
- integrity sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==
- dependencies:
- "@pkgr/core" "^0.1.0"
- tslib "^2.6.2"
-
-tailwind-merge@^2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.3.0.tgz#27d2134fd00a1f77eca22bcaafdd67055917d286"
- integrity sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==
- dependencies:
- "@babel/runtime" "^7.24.1"
-
-tailwindcss-animate@^1.0.7:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4"
- integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==
-
-tailwindcss@latest:
- version "3.4.3"
- resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.3.tgz#be48f5283df77dfced705451319a5dffb8621519"
- integrity sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==
- dependencies:
- "@alloc/quick-lru" "^5.2.0"
- arg "^5.0.2"
- chokidar "^3.5.3"
- didyoumean "^1.2.2"
- dlv "^1.1.3"
- fast-glob "^3.3.0"
- glob-parent "^6.0.2"
- is-glob "^4.0.3"
- jiti "^1.21.0"
- lilconfig "^2.1.0"
- micromatch "^4.0.5"
- normalize-path "^3.0.0"
- object-hash "^3.0.0"
- picocolors "^1.0.0"
- postcss "^8.4.23"
- postcss-import "^15.1.0"
- postcss-js "^4.0.1"
- postcss-load-config "^4.0.1"
- postcss-nested "^6.0.1"
- postcss-selector-parser "^6.0.11"
- resolve "^1.22.2"
- sucrase "^3.32.0"
-
-tar-fs@^1.15.3:
- version "1.16.3"
- resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509"
- integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==
- dependencies:
- chownr "^1.0.1"
- mkdirp "^0.5.1"
- pump "^1.0.0"
- tar-stream "^1.1.2"
-
-tar-stream@^1.1.2, tar-stream@^1.5.4:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
- integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
- dependencies:
- bl "^1.0.0"
- buffer-alloc "^1.2.0"
- end-of-stream "^1.0.0"
- fs-constants "^1.0.0"
- readable-stream "^2.3.0"
- to-buffer "^1.1.1"
- xtend "^4.0.0"
-
-tar@^2.0.0, tar@~2.2.1:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40"
- integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==
- dependencies:
- block-stream "*"
- fstream "^1.0.12"
- inherits "2"
-
-tar@^6.1.11, tar@^6.1.2, tar@^6.2.0, tar@^6.2.1:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
- integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==
- dependencies:
- chownr "^2.0.0"
- fs-minipass "^2.0.0"
- minipass "^5.0.0"
- minizlib "^2.1.1"
- mkdirp "^1.0.3"
- yallist "^4.0.0"
-
-term-size@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69"
- integrity sha512-7dPUZQGy/+m3/wjVz3ZW5dobSoD/02NxJpoXUX0WIyjfVS3l0c+b/+9phIDFA7FHzkYtwtMFgeGZ/Y8jVTeqQQ==
- dependencies:
- execa "^0.7.0"
-
-text-table@^0.2.0, text-table@~0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
- integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
-
-textarea@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/textarea/-/textarea-0.3.0.tgz#89cfdef8f3fc22c0c1aa00fcf242a044bf0c2e6b"
- integrity sha512-mLIr1WYhuoPNuq7Tz8kf0g/VFr0q1BnwScX820WITbyq7MTPbmxK1oVyeoYCzCFjBAcE2MNIBpIBDV1Ctyqxrg==
-
-thenify-all@^1.0.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
- integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==
- dependencies:
- thenify ">= 3.1.0 < 4"
-
-"thenify@>= 3.1.0 < 4":
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f"
- integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
- dependencies:
- any-promise "^1.0.0"
-
-three@^0.135.0:
- version "0.135.0"
- resolved "https://registry.yarnpkg.com/three/-/three-0.135.0.tgz#cff4ec8edd3c51ce9bc7e88d13e8eafed4d0ddfc"
- integrity sha512-kuEpuuxRzLv0MDsXai9huCxOSQPZ4vje6y0gn80SRmQvgz6/+rI0NAvCRAw56zYaWKMGMfqKWsxF9Qa2Z9xymQ==
-
-throttle-debounce@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-5.0.0.tgz#a17a4039e82a2ed38a5e7268e4132d6960d41933"
- integrity sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==
-
-throttleit@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.1.tgz#304ec51631c3b770c65c6c6f76938b384000f4d5"
- integrity sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==
-
-through2@^2.0.0:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
- integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
- dependencies:
- readable-stream "~2.3.6"
- xtend "~4.0.1"
-
-through@2, "through@>=2.2.7 <3", through@^2.3.8, through@~2.3, through@~2.3.1:
- version "2.3.8"
- resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
- integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
-
-timed-out@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
- integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==
-
-tiny-relative-date@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07"
- integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A==
-
-tinyqueue@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-2.0.3.tgz#64d8492ebf39e7801d7bd34062e29b45b2035f08"
- integrity sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==
-
-tippy.js@^6.3.7:
- version "6.3.7"
- resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c"
- integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==
- dependencies:
- "@popperjs/core" "^2.9.0"
-
-tmp@~0.2.1:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae"
- integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==
-
-to-buffer@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
- integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
-
-to-fast-properties@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
- integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
-
-to-px@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/to-px/-/to-px-1.1.0.tgz#b6b269ed5db0cc9aefc15272a4c8bcb2ca1e99ca"
- integrity sha512-bfg3GLYrGoEzrGoE05TAL/Uw+H/qrf2ptr9V3W7U0lkjjyYnIfgxmVLUfhQ1hZpIQwin81uxhDjvUkDYsC0xWw==
- dependencies:
- parse-unit "^1.0.1"
-
-to-regex-range@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
- integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
- dependencies:
- is-number "^7.0.0"
-
-topojson-client@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/topojson-client/-/topojson-client-3.1.0.tgz#22e8b1ed08a2b922feeb4af6f53b6ef09a467b99"
- integrity sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==
- dependencies:
- commander "2"
-
-tough-cookie@^4.1.3:
- version "4.1.4"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36"
- integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==
- dependencies:
- psl "^1.1.33"
- punycode "^2.1.1"
- universalify "^0.2.0"
- url-parse "^1.5.3"
-
-tough-cookie@~2.3.0:
- version "2.3.4"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
- integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==
- dependencies:
- punycode "^1.4.1"
-
-tough-cookie@~2.5.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
- integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
- dependencies:
- psl "^1.1.28"
- punycode "^2.1.1"
-
-treeverse@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/treeverse/-/treeverse-3.0.0.tgz#dd82de9eb602115c6ebd77a574aae67003cb48c8"
- integrity sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==
-
-ts-interface-checker@^0.1.9:
- version "0.1.13"
- resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
- integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
-
-ts-morph@^22.0.0:
- version "22.0.0"
- resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-22.0.0.tgz#5532c592fb6dddae08846f12c9ab0fc590b1d42e"
- integrity sha512-M9MqFGZREyeb5fTl6gNHKZLqBQA0TjA1lea+CR48R8EBTDuWrNqW6ccC5QvjNR4s6wDumD3LTCjOFSp9iwlzaw==
- dependencies:
- "@ts-morph/common" "~0.23.0"
- code-block-writer "^13.0.1"
-
-tsconfig-paths@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c"
- integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==
- dependencies:
- json5 "^2.2.2"
- minimist "^1.2.6"
- strip-bom "^3.0.0"
-
-tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6.2:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
- integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
-
-tuf-js@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/tuf-js/-/tuf-js-2.2.1.tgz#fdd8794b644af1a75c7aaa2b197ddffeb2911b56"
- integrity sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==
- dependencies:
- "@tufjs/models" "2.0.1"
- debug "^4.3.4"
- make-fetch-happen "^13.0.1"
-
-tunnel-agent@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
- integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==
- dependencies:
- safe-buffer "^5.0.1"
-
-tweetnacl@^0.14.3, tweetnacl@~0.14.0:
- version "0.14.5"
- resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
- integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==
-
-type-check@^0.4.0, type-check@~0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
- integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
- dependencies:
- prelude-ls "^1.2.1"
-
-type-fest@^0.20.2:
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
- integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
-
-type-fest@^0.21.3:
- version "0.21.3"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
- integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
-
-type-fest@^4.8.3:
- version "4.21.0"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.21.0.tgz#2eec399d9bda4ac686286314d07c6675fef3fdd8"
- integrity sha512-ADn2w7hVPcK6w1I0uWnM//y1rLXZhzB9mr0a3OirzclKF1Wp6VzevUmzz/NRAWunOT6E8HrnpGY7xOfc6K57fA==
-
-typedarray@^0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
- integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
-
-typescript@^5.4.5:
- version "5.5.3"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.3.tgz#e1b0a3c394190838a0b168e771b0ad56a0af0faa"
- integrity sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==
-
-uc.micro@^2.0.0, uc.micro@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee"
- integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==
-
-ufo@^1.5.3:
- version "1.5.3"
- resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.3.tgz#3325bd3c977b6c6cd3160bf4ff52989adc9d3344"
- integrity sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==
-
-uid-number@0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
- integrity sha512-c461FXIljswCuscZn67xq9PpszkPT6RjheWFQTgCyabJrTUozElanb0YEqv2UGgk247YpcJkFBuSGNvBlpXM9w==
-
-umask@~1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d"
- integrity sha512-lE/rxOhmiScJu9L6RTNVgB/zZbF+vGC0/p6D3xnkAePI2o0sMyFG966iR5Ki50OI/0mNi2yaRnxfLsPmEZF/JA==
-
-undici-types@~5.26.4:
- version "5.26.5"
- resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
- integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
-
-unique-filename@^1.1.0, unique-filename@~1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
- integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==
- dependencies:
- unique-slug "^2.0.0"
-
-unique-filename@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea"
- integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==
- dependencies:
- unique-slug "^4.0.0"
-
-unique-slug@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c"
- integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==
- dependencies:
- imurmurhash "^0.1.4"
-
-unique-slug@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3"
- integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==
- dependencies:
- imurmurhash "^0.1.4"
-
-unique-string@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a"
- integrity sha512-ODgiYu03y5g76A1I9Gt0/chLCzQjvzDy7DsZGsLOE/1MrF6wriEskSncj1+/C58Xk/kPZDppSctDybCwOSaGAg==
- dependencies:
- crypto-random-string "^1.0.0"
-
-universalify@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
- integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
-
-universalify@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d"
- integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==
-
-unpipe@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
- integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
-
-untildify@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b"
- integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==
-
-unzip-response@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
- integrity sha512-N0XH6lqDtFH84JxptQoZYmloF4nzrQqqrAymNj+/gW60AO2AZgOcf4O/nUXJcYfyQkqvMo9lSupBZmmgvuVXlw==
-
-update-browserslist-db@^1.0.13:
- version "1.0.15"
- resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz#60ed9f8cba4a728b7ecf7356f641a31e3a691d97"
- integrity sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==
- dependencies:
- escalade "^3.1.2"
- picocolors "^1.0.0"
-
-update-browserslist-db@^1.0.16:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e"
- integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==
- dependencies:
- escalade "^3.1.2"
- picocolors "^1.0.1"
-
-update-notifier@^2.3.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6"
- integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==
- dependencies:
- boxen "^1.2.1"
- chalk "^2.0.1"
- configstore "^3.0.0"
- import-lazy "^2.1.0"
- is-ci "^1.0.10"
- is-installed-globally "^0.1.0"
- is-npm "^1.0.0"
- latest-version "^3.0.0"
- semver-diff "^2.0.0"
- xdg-basedir "^3.0.0"
-
-update-notifier@~2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.2.0.tgz#1b5837cf90c0736d88627732b661c138f86de72f"
- integrity sha512-BrfvANq8gJjhtaeDiK1QFunFoo5ad9BJ+bTgeSaonpHUzjTtCdzqzuxCSKYfRvS/R20BAYT8HlCMZO2r4xDaQg==
- dependencies:
- boxen "^1.0.0"
- chalk "^1.0.0"
- configstore "^3.0.0"
- import-lazy "^2.1.0"
- is-npm "^1.0.0"
- latest-version "^3.0.0"
- semver-diff "^2.0.0"
- xdg-basedir "^3.0.0"
-
-uri-js@^4.2.2:
- version "4.4.1"
- resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
- integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
- dependencies:
- punycode "^2.1.0"
-
-url-parse-lax@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73"
- integrity sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==
- dependencies:
- prepend-http "^1.0.1"
-
-url-parse@^1.5.3:
- version "1.5.10"
- resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
- integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
- dependencies:
- querystringify "^2.1.1"
- requires-port "^1.0.0"
-
-util-deprecate@^1.0.2, util-deprecate@~1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
- integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
-
-util-extend@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f"
- integrity sha512-mLs5zAK+ctllYBj+iAQvlDCwoxU/WDOUaJkcFudeiAX6OajC6BKXJUa9a+tbtkC11dz2Ufb7h0lyvIOVn4LADA==
-
-uuid@^3.0.0, uuid@^3.3.2:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
- integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-
-uuid@^8.3.2:
- version "8.3.2"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
- integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
-
-uuid@~3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
- integrity sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==
-
-validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
- integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
- dependencies:
- spdx-correct "^3.0.0"
- spdx-expression-parse "^3.0.0"
-
-validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e"
- integrity sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==
- dependencies:
- builtins "^1.0.3"
-
-validate-npm-package-name@^5.0.0:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz#a316573e9b49f3ccd90dbb6eb52b3f06c6d604e8"
- integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==
-
-vee-validate@4.13.2, vee-validate@^4.13.2:
- version "4.13.2"
- resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-4.13.2.tgz#cf601c9ac029d58a15aecc1dbab28b15628f0a0e"
- integrity sha512-HlpR/6MJ92TW9f135umMZKUqdd/tFQTxLNSf2ImbU4Y/MlLVAUpF1l64VdjTOhbClAqPjCb5p/SqHDxLpUHXrw==
- dependencies:
- "@vue/devtools-api" "^6.6.1"
- type-fest "^4.8.3"
-
-verror@1.10.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
- integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==
- dependencies:
- assert-plus "^1.0.0"
- core-util-is "1.0.2"
- extsprintf "^1.2.0"
-
-vite@^5.4.9:
- version "5.4.9"
- resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.9.tgz#215c80cbebfd09ccbb9ceb8c0621391c9abdc19c"
- integrity sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==
- dependencies:
- esbuild "^0.21.3"
- postcss "^8.4.43"
- rollup "^4.20.0"
- optionalDependencies:
- fsevents "~2.3.3"
-
-vt-pbf@^3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/vt-pbf/-/vt-pbf-3.1.3.tgz#68fd150756465e2edae1cc5c048e063916dcfaac"
- integrity sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==
- dependencies:
- "@mapbox/point-geometry" "0.1.0"
- "@mapbox/vector-tile" "^1.3.1"
- pbf "^3.2.1"
-
-vue-demi@>=0.13.0, vue-demi@>=0.14.5, vue-demi@>=0.14.7:
- version "0.14.7"
- resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.7.tgz#8317536b3ef74c5b09f268f7782e70194567d8f2"
- integrity sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==
-
-vue-demi@>=0.14.10:
- version "0.14.10"
- resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04"
- integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==
-
-vue-demi@>=0.14.8:
- version "0.14.8"
- resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.8.tgz#00335e9317b45e4a68d3528aaf58e0cec3d5640a"
- integrity sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==
-
-vue-eslint-parser@^9.4.2:
- version "9.4.2"
- resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz#02ffcce82042b082292f2d1672514615f0d95b6d"
- integrity sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==
- dependencies:
- debug "^4.3.4"
- eslint-scope "^7.1.1"
- eslint-visitor-keys "^3.3.0"
- espree "^9.3.1"
- esquery "^1.4.0"
- lodash "^4.17.21"
- semver "^7.3.6"
-
-vue-i18n@9:
- version "9.13.1"
- resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-9.13.1.tgz#a292c8021b7be604ebfca5609ae1f8fafe5c36d7"
- integrity sha512-mh0GIxx0wPtPlcB1q4k277y0iKgo25xmDPWioVVYanjPufDBpvu5ySTjP5wOrSvlYQ2m1xI+CFhGdauv/61uQg==
- dependencies:
- "@intlify/core-base" "9.13.1"
- "@intlify/shared" "9.13.1"
- "@vue/devtools-api" "^6.5.0"
-
-vue-letter@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/vue-letter/-/vue-letter-0.2.0.tgz#86f2e3f0d2fe59f866050f790b43119161f1f577"
- integrity sha512-p4qHpw89GKidKyGcg4J4IjUcMQuVaTJq83c6UE4616claaLF9rj2Bg/Hq19uDCmokd+SvzEwxq6/ctfaaednkw==
- dependencies:
- lettersanitizer "^1.0.5"
-
-vue-picture-cropper@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/vue-picture-cropper/-/vue-picture-cropper-0.7.0.tgz#e9dec1b17542ba6c681a7ba6240282193e101d68"
- integrity sha512-NF7+Dgso6d0GB16E5d/BbrcTIHm1VWz8dS3IjLhoBl+ZeC+yDA46CyJphQuO32SisaPmrKHN8VbiE2LgAfhnkQ==
- dependencies:
- "@bassist/utils" "^0.4.0"
- cropperjs "^1.6.1"
-
-vue-router@^4.2.5:
- version "4.3.2"
- resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.3.2.tgz#08096c7765dacc6832f58e35f7a081a8b34116a7"
- integrity sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q==
- dependencies:
- "@vue/devtools-api" "^6.5.1"
-
-vue@^3.4.37:
- version "3.4.37"
- resolved "https://registry.yarnpkg.com/vue/-/vue-3.4.37.tgz#64ce0eeb8de16a29fb74e504777ee8c0c1cf229e"
- integrity sha512-3vXvNfkKTBsSJ7JP+LyR7GBuwQuckbWvuwAid3xbqK9ppsKt/DUvfqgZ48fgOLEfpy1IacL5f8QhUVl77RaI7A==
- dependencies:
- "@vue/compiler-dom" "3.4.37"
- "@vue/compiler-sfc" "3.4.37"
- "@vue/runtime-dom" "3.4.37"
- "@vue/server-renderer" "3.4.37"
- "@vue/shared" "3.4.37"
-
-w3c-keyname@^2.2.0:
- version "2.2.8"
- resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5"
- integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==
-
-wait-on@7.2.0:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-7.2.0.tgz#d76b20ed3fc1e2bebc051fae5c1ff93be7892928"
- integrity sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==
- dependencies:
- axios "^1.6.1"
- joi "^17.11.0"
- lodash "^4.17.21"
- minimist "^1.2.8"
- rxjs "^7.8.1"
-
-walk-up-path@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-3.0.1.tgz#c8d78d5375b4966c717eb17ada73dbd41490e886"
- integrity sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==
-
-wcwidth@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
- integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==
- dependencies:
- defaults "^1.0.3"
-
-which-module@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409"
- integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==
-
-which@1, which@^1.2.12, which@^1.2.9, which@^1.3.0, which@^1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
- integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
- dependencies:
- isexe "^2.0.0"
-
-which@^2.0.1:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
- integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
- dependencies:
- isexe "^2.0.0"
-
-which@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a"
- integrity sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==
- dependencies:
- isexe "^3.1.1"
-
-which@~1.2.14:
- version "1.2.14"
- resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5"
- integrity sha512-16uPglFkRPzgiUXYMi1Jf8Z5EzN1iB4V0ZtMXcHZnwsBtQhhHeCqoWw7tsUY42hJGNDWtUsVLTjakIa5BgAxCw==
- dependencies:
- isexe "^2.0.0"
-
-wide-align@^1.1.0:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
- integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
- dependencies:
- string-width "^1.0.2 || 2 || 3 || 4"
-
-widest-line@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc"
- integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==
- dependencies:
- string-width "^2.1.1"
-
-word-wrap@^1.2.5:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
- integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
-
-worker-farm@~1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.3.1.tgz#4333112bb49b17aa050b87895ca6b2cacf40e5ff"
- integrity sha512-ikAfMCRFdPRJjXG4TzMI2bs/I7kZPJrejDFbSUG6n0JptwUHEPfq/7Uap/aylHjPhxyfTueeWRmakCsLA5xJsg==
- dependencies:
- errno ">=0.1.1 <0.2.0-0"
- xtend ">=4.0.0 <4.1.0-0"
-
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
- integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
- dependencies:
- ansi-styles "^4.0.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
-
-wrap-ansi@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
- integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==
- dependencies:
- string-width "^1.0.1"
- strip-ansi "^3.0.1"
-
-wrap-ansi@^6.2.0:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
- integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
- dependencies:
- ansi-styles "^4.0.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
-
-wrap-ansi@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
- integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
- dependencies:
- ansi-styles "^4.0.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
-
-wrap-ansi@^8.1.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
- integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
- dependencies:
- ansi-styles "^6.1.0"
- string-width "^5.0.1"
- strip-ansi "^7.0.1"
-
-wrappy@1, wrappy@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
- integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
-
-write-file-atomic@^2.0.0:
- version "2.4.3"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
- integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
- dependencies:
- graceful-fs "^4.1.11"
- imurmurhash "^0.1.4"
- signal-exit "^3.0.2"
-
-write-file-atomic@^5.0.0, write-file-atomic@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7"
- integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==
- dependencies:
- imurmurhash "^0.1.4"
- signal-exit "^4.0.1"
-
-write-file-atomic@~2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.1.0.tgz#1769f4b551eedce419f0505deae2e26763542d37"
- integrity sha512-0TZ20a+xcIl4u0+Mj5xDH2yOWdmQiXlKf9Hm+TgDXjTMsEYb+gDrmb8e8UNAzMCitX8NBqG4Z/FUQIyzv/R1JQ==
- dependencies:
- graceful-fs "^4.1.11"
- imurmurhash "^0.1.4"
- slide "^1.1.5"
-
-xdg-basedir@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
- integrity sha512-1Dly4xqlulvPD3fZUQJLY+FUIeqN3N2MM3uqe4rCJftAvOjFa3jFGfctOgluGx4ahPbUCsZkmJILiP0Vi4T6lQ==
-
-xml-name-validator@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835"
- integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==
-
-"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
- integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
-
-y18n@^3.2.1:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696"
- integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==
-
-y18n@^4.0.0:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
- integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
-
-yallist@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
- integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==
-
-yallist@^3.0.2:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
- integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
-
-yallist@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
- integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-
-yaml@^1.10.0:
- version "1.10.2"
- resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
- integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
-
-yaml@^2.3.4:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.2.tgz#7a2b30f2243a5fc299e1f14ca58d475ed4bc5362"
- integrity sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==
-
-yargs-parser@^9.0.2:
- version "9.0.2"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
- integrity sha512-CswCfdOgCr4MMsT1GzbEJ7Z2uYudWyrGX8Bgh/0eyCzj/DXWdKq6a/ADufkzI1WAOIW6jYaXJvRyLhDO0kfqBw==
- dependencies:
- camelcase "^4.1.0"
-
-yargs@^11.0.0:
- version "11.1.1"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.1.tgz#5052efe3446a4df5ed669c995886cc0f13702766"
- integrity sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==
- dependencies:
- cliui "^4.0.0"
- decamelize "^1.1.1"
- find-up "^2.1.0"
- get-caller-file "^1.0.1"
- os-locale "^3.1.0"
- require-directory "^2.1.1"
- require-main-filename "^1.0.1"
- set-blocking "^2.0.0"
- string-width "^2.0.0"
- which-module "^2.0.0"
- y18n "^3.2.1"
- yargs-parser "^9.0.2"
-
-yauzl@^2.10.0:
- version "2.10.0"
- resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
- integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==
- dependencies:
- buffer-crc32 "~0.2.3"
- fd-slicer "~1.1.0"
-
-yocto-queue@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
- integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
-
-zod@^3.22.4, zod@^3.23.3, zod@^3.23.8:
- version "3.23.8"
- resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
- integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
diff --git a/go.mod b/go.mod
index 81d905b6..aa0ac338 100644
--- a/go.mod
+++ b/go.mod
@@ -1,4 +1,4 @@
-module github.com/abhinavxd/artemis
+module github.com/abhinavxd/libredesk
go 1.22.3
diff --git a/internal/ai/ai.go b/internal/ai/ai.go
new file mode 100644
index 00000000..e4e77956
--- /dev/null
+++ b/internal/ai/ai.go
@@ -0,0 +1,126 @@
+// Package ai manages AI prompts and integrates with LLM providers.
+package ai
+
+import (
+ "database/sql"
+ "embed"
+ "encoding/json"
+
+ "github.com/abhinavxd/libredesk/internal/ai/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/jmoiron/sqlx"
+ "github.com/zerodha/logf"
+)
+
+var (
+ //go:embed queries.sql
+ efs embed.FS
+)
+
+// Manager manages LLM providers.
+type Manager struct {
+ q queries
+ lo *logf.Logger
+}
+
+// Opts contains options for initializing the Manager.
+type Opts struct {
+ DB *sqlx.DB
+ Lo *logf.Logger
+}
+
+// queries contains prepared SQL queries.
+type queries struct {
+ GetDefaultProvider *sqlx.Stmt `query:"get-default-provider"`
+ GetPrompt *sqlx.Stmt `query:"get-prompt"`
+ GetPrompts *sqlx.Stmt `query:"get-prompts"`
+}
+
+// New creates and returns a new instance of the Manager.
+func New(opts Opts) (*Manager, error) {
+ var q queries
+ if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
+ return nil, err
+ }
+ return &Manager{
+ q: q,
+ lo: opts.Lo,
+ }, nil
+}
+
+// Completion sends a prompt to the default provider and returns the response.
+func (m *Manager) Completion(k string, prompt string) (string, error) {
+ systemPrompt, err := m.getPrompt(k)
+ if err != nil {
+ return "", err
+ }
+
+ client, err := m.getDefaultProviderClient()
+ if err != nil {
+ m.lo.Error("error getting provider client", "error", err)
+ return "", envelope.NewError(envelope.GeneralError, "Error getting provider client", nil)
+ }
+
+ payload := PromptPayload{
+ SystemPrompt: systemPrompt,
+ UserPrompt: prompt,
+ }
+
+ response, err := client.SendPrompt(payload)
+ if err != nil {
+ m.lo.Error("error sending prompt to provider", "error", err)
+ return "", envelope.NewError(envelope.GeneralError, err.Error(), nil)
+ }
+
+ return response, nil
+}
+
+// GetPrompts returns a list of prompts from the database.
+func (m *Manager) GetPrompts() ([]models.Prompt, error) {
+ var prompts = make([]models.Prompt, 0)
+ if err := m.q.GetPrompts.Select(&prompts); err != nil {
+ m.lo.Error("error fetching prompts", "error", err)
+ return nil, envelope.NewError(envelope.GeneralError, "Error fetching prompts", nil)
+ }
+ return prompts, nil
+}
+
+// getPrompt returns a prompt from the database.
+func (m *Manager) getPrompt(k string) (string, error) {
+ var p models.Prompt
+ if err := m.q.GetPrompt.Get(&p, k); err != nil {
+ if err == sql.ErrNoRows {
+ m.lo.Error("error prompt not found", "key", k)
+ return "", envelope.NewError(envelope.InputError, "Prompt not found", nil)
+ }
+ m.lo.Error("error fetching prompt", "error", err)
+ return "", envelope.NewError(envelope.GeneralError, "Error fetching prompt", nil)
+ }
+ return p.Content, nil
+}
+
+// getDefaultProviderClient returns a ProviderClient for the default provider.
+func (m *Manager) getDefaultProviderClient() (ProviderClient, error) {
+ var p models.Provider
+
+ if err := m.q.GetDefaultProvider.Get(&p); err != nil {
+ m.lo.Error("error fetching provider details", "error", err)
+ return nil, envelope.NewError(envelope.GeneralError, "Error fetching provider details", nil)
+ }
+
+ switch ProviderType(p.Provider) {
+ case ProviderOpenAI:
+ config := struct {
+ APIKey string `json:"api_key"`
+ }{}
+ if err := json.Unmarshal([]byte(p.Config), &config); err != nil {
+ m.lo.Error("error parsing provider config", "error", err)
+ return nil, envelope.NewError(envelope.GeneralError, "Error parsing provider config", nil)
+ }
+ return NewOpenAIClient(config.APIKey, m.lo), nil
+ default:
+ m.lo.Error("unsupported provider type", "provider", p.Provider)
+ return nil, envelope.NewError(envelope.GeneralError, "Unsupported provider type", nil)
+ }
+}
diff --git a/internal/ai/models/models.go b/internal/ai/models/models.go
new file mode 100644
index 00000000..ac58cdb5
--- /dev/null
+++ b/internal/ai/models/models.go
@@ -0,0 +1,22 @@
+package models
+
+import "time"
+
+type Provider struct {
+ ID string `db:"id"`
+ CreatedAt time.Time `db:"created_at"`
+ UpdatedAt time.Time `db:"updated_at"`
+ Name string `db:"name"`
+ Provider string `db:"provider"`
+ Config string `db:"config"`
+ IsDefault bool `db:"is_default"`
+}
+
+type Prompt struct {
+ ID int `db:"id" json:"id"`
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+ Title string `db:"title" json:"title"`
+ Key string `db:"key" json:"key"`
+ Content string `db:"content" json:"content,omitempty"`
+}
diff --git a/internal/ai/openai.go b/internal/ai/openai.go
new file mode 100644
index 00000000..8be93e7b
--- /dev/null
+++ b/internal/ai/openai.go
@@ -0,0 +1,91 @@
+package ai
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "time"
+
+ "github.com/zerodha/logf"
+)
+
+type OpenAIClient struct {
+ apikey string
+ lo *logf.Logger
+ client *http.Client
+}
+
+func NewOpenAIClient(apiKey string, lo *logf.Logger) *OpenAIClient {
+ return &OpenAIClient{
+ apikey: apiKey,
+ lo: lo,
+ client: &http.Client{Timeout: 10 * time.Second},
+ }
+}
+
+// SendPrompt sends a prompt to the OpenAI API and returns the response text.
+func (o *OpenAIClient) SendPrompt(payload PromptPayload) (string, error) {
+ if o.apikey == "" {
+ return "", fmt.Errorf("OpenAI API key is not set, Please ask your administrator to set the key")
+ }
+
+ apiURL := "https://api.openai.com/v1/chat/completions"
+ requestBody := map[string]interface{}{
+ "model": "gpt-4o-mini",
+ "messages": []map[string]string{
+ {"role": "system", "content": payload.SystemPrompt},
+ {"role": "user", "content": payload.UserPrompt},
+ },
+ "max_tokens": 1024,
+ "temperature": 0.7,
+ }
+
+ bodyBytes, err := json.Marshal(requestBody)
+ if err != nil {
+ o.lo.Error("error marshalling request body", "error", err)
+ return "", fmt.Errorf("marshalling request body: %w", err)
+ }
+
+ req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(bodyBytes))
+ if err != nil {
+ o.lo.Error("error creating request", "error", err)
+ return "", fmt.Errorf("error creating request: %w", err)
+ }
+
+ req.Header.Set("Authorization", "Bearer "+o.apikey)
+ req.Header.Set("Content-Type", "application/json")
+
+ resp, err := o.client.Do(req)
+ if err != nil {
+ o.lo.Error("error making HTTP request", "error", err)
+ return "", fmt.Errorf("making HTTP request: %w", err)
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode == http.StatusUnauthorized {
+ return "", fmt.Errorf("OpenAI API key is invalid, Please ask your administrator to update the key")
+ }
+
+ if resp.StatusCode != http.StatusOK {
+ body, _ := io.ReadAll(resp.Body)
+ return "", fmt.Errorf("API error: %s, body: %s", resp.Status, body)
+ }
+
+ var responseBody struct {
+ Choices []struct {
+ Message struct {
+ Content string `json:"content"`
+ } `json:"message"`
+ } `json:"choices"`
+ }
+ if err := json.NewDecoder(resp.Body).Decode(&responseBody); err != nil {
+ return "", fmt.Errorf("decoding response body: %w", err)
+ }
+
+ if len(responseBody.Choices) > 0 {
+ return responseBody.Choices[0].Message.Content, nil
+ }
+ return "", fmt.Errorf("no response found")
+}
diff --git a/internal/ai/provider.go b/internal/ai/provider.go
new file mode 100644
index 00000000..e2a8a62b
--- /dev/null
+++ b/internal/ai/provider.go
@@ -0,0 +1,20 @@
+package ai
+
+// ProviderClient is the interface all providers should implement.
+type ProviderClient interface {
+ SendPrompt(payload PromptPayload) (string, error)
+}
+
+// ProviderType is an enum-like type for different providers.
+type ProviderType string
+
+const (
+ ProviderOpenAI ProviderType = "openai"
+ ProviderClaude ProviderType = "claude"
+)
+
+// PromptPayload represents the structured input for an LLM provider.
+type PromptPayload struct {
+ SystemPrompt string `json:"system_prompt"`
+ UserPrompt string `json:"user_prompt"`
+}
diff --git a/internal/ai/queries.sql b/internal/ai/queries.sql
new file mode 100644
index 00000000..f1d2b3bb
--- /dev/null
+++ b/internal/ai/queries.sql
@@ -0,0 +1,8 @@
+-- name: get-default-provider
+SELECT id, name, provider, config, is_default FROM ai_providers where is_default is true;
+
+-- name: get-prompt
+SELECT id, key, title, content FROM ai_prompts where key = $1;
+
+-- name: get-prompts
+SELECT id, key, title FROM ai_prompts order by title;
\ No newline at end of file
diff --git a/internal/auth/auth.go b/internal/auth/auth.go
index b79ac406..40abfac1 100644
--- a/internal/auth/auth.go
+++ b/internal/auth/auth.go
@@ -1,3 +1,4 @@
+// Package auth implements OIDC multi-provider authentication and session management
package auth
import (
@@ -9,12 +10,14 @@ import (
"sync"
"time"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/abhinavxd/artemis/internal/stringutil"
- "github.com/abhinavxd/artemis/internal/user/models"
+ amodels "github.com/abhinavxd/libredesk/internal/auth/models"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/stringutil"
+ "github.com/abhinavxd/libredesk/internal/user/models"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/redis/go-redis/v9"
"github.com/valyala/fasthttp"
+ "github.com/volatiletech/null/v9"
"github.com/zerodha/fastglue"
"github.com/zerodha/logf"
sessredisstore "github.com/zerodha/simplesessions/stores/redis/v3"
@@ -23,6 +26,7 @@ import (
"golang.org/x/oauth2"
)
+// OIDCclaim holds OIDC token claims data
type OIDCclaim struct {
Email string `json:"email"`
EmailVerified bool `json:"email_verified"`
@@ -30,6 +34,7 @@ type OIDCclaim struct {
Picture string `json:"picture"`
}
+// Provider defines an OIDC provider configuration
type Provider struct {
ID int
Provider string
@@ -39,10 +44,12 @@ type Provider struct {
ClientSecret string
}
+// Config stores multiple OIDC provider configurations
type Config struct {
Providers []Provider
}
+// Auth is the auth service it manages OIDC authentication and sessions
type Auth struct {
mu sync.RWMutex
cfg Config
@@ -53,7 +60,7 @@ type Auth struct {
rd *redis.Client
}
-// New initializes an OIDC configuration for multiple providers.
+// New creates an Auth service with configured OIDC providers
func New(cfg Config, rd *redis.Client, logger *logf.Logger) (*Auth, error) {
oauthCfgs := make(map[int]oauth2.Config)
verifiers := make(map[int]*oidc.IDTokenVerifier)
@@ -85,7 +92,7 @@ func New(cfg Config, rd *redis.Client, logger *logf.Logger) (*Auth, error) {
Cookie: simplesessions.CookieOptions{
IsHTTPOnly: true,
IsSecure: true,
- MaxAge: time.Hour * 6,
+ Expires: time.Now().Add(time.Hour * 48),
},
})
@@ -114,8 +121,8 @@ func (a *Auth) Reload(cfg Config) error {
for _, provider := range cfg.Providers {
oidcProv, err := oidc.NewProvider(context.Background(), provider.ProviderURL)
if err != nil {
- a.logger.Error("error initializing oidc provider", "error", err, "provider", provider.Provider)
- continue
+ a.logger.Error("error initializing oidc provider", "provider", provider.Provider, "provider_url", provider.ProviderURL, "error", err)
+ return envelope.NewError(envelope.GeneralError, err.Error(), nil)
}
oauthCfg := oauth2.Config{
@@ -143,7 +150,6 @@ func (a *Auth) Reload(cfg Config) error {
func (a *Auth) LoginURL(providerID int, state string) (string, error) {
a.mu.RLock()
defer a.mu.RUnlock()
-
oauthCfg, ok := a.oauthCfgs[providerID]
if !ok {
return "", envelope.NewError(envelope.InputError, "Provider not found", nil)
@@ -152,7 +158,7 @@ func (a *Auth) LoginURL(providerID int, state string) (string, error) {
}
// ExchangeOIDCToken takes an OIDC authorization code, validates it, and returns an OIDC token for subsequent auth.
-func (a *Auth) ExchangeOIDCToken(ctx context.Context, providerID int, code, nonce string) (string, OIDCclaim, error) {
+func (a *Auth) ExchangeOIDCToken(ctx context.Context, providerID int, code string) (string, OIDCclaim, error) {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -183,10 +189,6 @@ func (a *Auth) ExchangeOIDCToken(ctx context.Context, providerID int, code, nonc
return "", OIDCclaim{}, fmt.Errorf("error verifying ID token: %v", err)
}
- if idTk.Nonce != nonce {
- return "", OIDCclaim{}, fmt.Errorf("nonce token mismatch")
- }
-
var claims OIDCclaim
if err := idTk.Claims(&claims); err != nil {
return "", OIDCclaim{}, errors.New("error getting user from OIDC")
@@ -195,7 +197,7 @@ func (a *Auth) ExchangeOIDCToken(ctx context.Context, providerID int, code, nonc
}
// SaveSession creates and sets a session (post successful login/auth).
-func (a *Auth) SaveSession(user models.User, r *fastglue.Request) error {
+func (a *Auth) SaveSession(user amodels.User, r *fastglue.Request) error {
a.mu.RLock()
defer a.mu.RUnlock()
@@ -217,6 +219,43 @@ func (a *Auth) SaveSession(user models.User, r *fastglue.Request) error {
return nil
}
+// SetSessionValues sets passed values in the session.
+func (a *Auth) SetSessionValues(r *fastglue.Request, values map[string]interface{}) error {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+
+ sess, err := a.sess.Acquire(r.RequestCtx, r, r)
+ if err != nil {
+ a.logger.Error("error acquiring session", "error", err)
+ return err
+ }
+
+ if err := sess.SetMulti(values); err != nil {
+ a.logger.Error("error setting session values", "error", err)
+ return err
+ }
+ return nil
+}
+
+// GetSessionValue returns the value for the given key from the session.
+func (a *Auth) GetSessionValue(r *fastglue.Request, key string) (any, error) {
+ a.mu.RLock()
+ defer a.mu.RUnlock()
+
+ sess, err := a.sess.Acquire(r.RequestCtx, r, r)
+ if err != nil {
+ a.logger.Error("error acquiring session", "error", err)
+ return "", err
+ }
+
+ val, err := sess.Get(key)
+ if err != nil {
+ a.logger.Error("error fetching session value", "error", err)
+ return "", err
+ }
+ return val, nil
+}
+
// SetCSRFCookie sets the CSRF token in the response cookie if not already set.
func (a *Auth) SetCSRFCookie(r *fastglue.Request) error {
a.mu.RLock()
@@ -265,7 +304,7 @@ func (a *Auth) ValidateSession(r *fastglue.Request) (models.User, error) {
return models.User{
ID: userID,
- Email: email,
+ Email: null.NewString(email, email != ""),
FirstName: firstName,
LastName: lastName,
}, nil
@@ -290,7 +329,7 @@ func (a *Auth) DestroySession(r *fastglue.Request) error {
// generateCSRFToken creates a random base64 encoded str.
func generateCSRFToken() (string, error) {
- b, err := stringutil.RandomAlNumString(30)
+ b, err := stringutil.RandomAlphanumeric(32)
if err != nil {
return "", err
}
diff --git a/internal/auth/models/models.go b/internal/auth/models/models.go
new file mode 100644
index 00000000..145987cd
--- /dev/null
+++ b/internal/auth/models/models.go
@@ -0,0 +1,9 @@
+package models
+
+// User represents an authenticated user.
+type User struct {
+ ID int `json:"id"`
+ FirstName string `json:"first_name"`
+ LastName string `json:"last_name"`
+ Email string `json:"email,omitempty"`
+}
diff --git a/internal/authz/authz.go b/internal/authz/authz.go
index ff26b578..7982779e 100644
--- a/internal/authz/authz.go
+++ b/internal/authz/authz.go
@@ -3,20 +3,21 @@ package authz
import (
"fmt"
+ "slices"
"strconv"
"strings"
- cmodels "github.com/abhinavxd/artemis/internal/conversation/models"
- "github.com/abhinavxd/artemis/internal/envelope"
- umodels "github.com/abhinavxd/artemis/internal/user/models"
+ cmodels "github.com/abhinavxd/libredesk/internal/conversation/models"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ umodels "github.com/abhinavxd/libredesk/internal/user/models"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
"github.com/zerodha/logf"
)
-// Enforcer is a struct that holds the Casbin enforcer
+// Enforcer is a wrapper around Casbin enforcer.
type Enforcer struct {
- enforcer *casbin.Enforcer
+ enforcer *casbin.SyncedEnforcer
lo *logf.Logger
}
@@ -40,7 +41,7 @@ func NewEnforcer(lo *logf.Logger) (*Enforcer, error) {
if err != nil {
return nil, fmt.Errorf("failed to create Casbin model: %v", err)
}
- e, err := casbin.NewEnforcer(m)
+ e, err := casbin.NewSyncedEnforcer(m)
if err != nil {
return nil, fmt.Errorf("failed to create Casbin enforcer: %v", err)
}
@@ -48,8 +49,16 @@ func NewEnforcer(lo *logf.Logger) (*Enforcer, error) {
return &Enforcer{enforcer: e, lo: lo}, nil
}
-// LoadPermissions adds the user's permissions to the Casbin enforcer if not already present.
+// LoadPermissions syncs user permissions with Casbin enforcer by removing existing
+// policies and adding current permissions as new policies
func (e *Enforcer) LoadPermissions(user umodels.User) error {
+ // Remove existing policies for the user
+ _, err := e.enforcer.RemoveFilteredPolicy(0, strconv.Itoa(user.ID))
+ if err != nil {
+ return fmt.Errorf("failed to remove policies: %v", err)
+ }
+
+ // Add each permission as a policy
for _, perm := range user.Permissions {
parts := strings.Split(perm, ":")
if len(parts) != 2 {
@@ -58,20 +67,19 @@ func (e *Enforcer) LoadPermissions(user umodels.User) error {
userID, permObj, permAct := strconv.Itoa(user.ID), parts[0], parts[1]
if _, err := e.enforcer.AddPolicy(userID, permObj, permAct); err != nil {
- return fmt.Errorf("failed to add policy: %v", err)
+ return fmt.Errorf("failed to add casbin policy: %v", err)
}
}
return nil
}
-// Enforce checks if a user has permission to perform an action on an object
+// Enforce checks if a user has permission to perform an action on an object.
func (e *Enforcer) Enforce(user umodels.User, obj, act string) (bool, error) {
- // Load permissions before enforcing
+ // Load permissions before enforcing.
err := e.LoadPermissions(user)
if err != nil {
return false, err
}
-
// Check if the user has the required permission
allowed, err := e.enforcer.Enforce(strconv.Itoa(user.ID), obj, act)
if err != nil {
@@ -80,41 +88,56 @@ func (e *Enforcer) Enforce(user umodels.User, obj, act string) (bool, error) {
return allowed, nil
}
-// EnforceConversationAccess checks if a user has access to a conversation based on their permissions.
-// It returns true if the user has read_all permission, or read_assigned permission and is in the assigned team,
-// or read_assigned permission and is the assigned user. Returns false otherwise.
+// EnforceConversationAccess determines if a user has access to a specific conversation based on their permissions.
+// Access can be granted under the following conditions:
+// 1. User has the "read_all" permission, allowing access to all conversations.
+// 2. User has the "read_assigned" permission and is the assigned user.
+// 3. User has the "read_team_inbox" permission and is part of the assigned team, with the conversation unassigned to any specific user.
+// 4. User has the "read_unassigned" permission and the conversation is unassigned to any user or team.
+// Returns true if access is granted, false otherwise. In case of an error while checking permissions, returns false and the error.
func (e *Enforcer) EnforceConversationAccess(user umodels.User, conversation cmodels.Conversation) (bool, error) {
- // Check for `read_all` permission
- allowed, err := e.enforcer.Enforce(strconv.Itoa(user.ID), "conversations", "read_all")
- if err != nil {
- return false, envelope.NewError(envelope.GeneralError, "Error checking permissions", nil)
- }
- if allowed {
- return true, nil
+ checkPermission := func(action string) (bool, error) {
+ allowed, err := e.Enforce(user, "conversations", action)
+ if err != nil {
+ e.lo.Error("error enforcing permission", "user_id", user.ID, "conversation_id", conversation.ID, "error", err)
+ return false, envelope.NewError(envelope.GeneralError, "Error checking permissions", nil)
+ }
+ if !allowed {
+ e.lo.Debug("permission denied", "user_id", user.ID, "action", action, "conversation_id", conversation.ID)
+ }
+ return allowed, nil
}
- // Check for `read_assigned` permission
- allowed, err = e.enforcer.Enforce(strconv.Itoa(user.ID), "conversations", "read_assigned")
- if err != nil {
- return false, envelope.NewError(envelope.GeneralError, "Error checking permissions", nil)
- }
- if allowed && conversation.AssignedUserID.Int == user.ID {
- return true, nil
+ // Check `read` permission
+ if allowed, err := checkPermission("read"); err != nil || !allowed {
+ return allowed, err
}
- // Check for `read_unassigned` permission
- allowed, err = e.enforcer.Enforce(strconv.Itoa(user.ID), "conversations", "read_unassigned")
- if err != nil {
- return false, envelope.NewError(envelope.GeneralError, "Error checking permissions", nil)
+ // Check `read_all` permission
+ if allowed, err := checkPermission("read_all"); err != nil || allowed {
+ return allowed, err
}
- if allowed {
- for _, teamID := range user.Teams.IDs() {
- if conversation.AssignedTeamID.Int == teamID {
- return true, nil
- }
+
+ // Check `read_assigned` permission for user-assigned conversations
+ if conversation.AssignedUserID.Int == user.ID {
+ if allowed, err := checkPermission("read_assigned"); err != nil || allowed {
+ return allowed, err
}
}
+ // Check `read_team_inbox` permission for team-assigned conversations
+ if conversation.AssignedTeamID.Int > 0 && slices.Contains(user.Teams.IDs(), conversation.AssignedTeamID.Int) && conversation.AssignedUserID.Int == 0 {
+ if allowed, err := checkPermission("read_team_inbox"); err != nil || allowed {
+ return allowed, err
+ }
+ }
+
+ // Check `read_unassigned` permission for unassigned conversations
+ if conversation.AssignedUserID.Int == 0 && conversation.AssignedTeamID.Int == 0 {
+ if allowed, err := checkPermission("read_unassigned"); err != nil || allowed {
+ return allowed, err
+ }
+ }
return false, nil
}
diff --git a/internal/authz/models/models.go b/internal/authz/models/models.go
index 74842e78..ceca36d2 100644
--- a/internal/authz/models/models.go
+++ b/internal/authz/models/models.go
@@ -5,6 +5,7 @@ const (
PermConversationsReadAll = "conversations:read_all"
PermConversationsReadUnassigned = "conversations:read_unassigned"
PermConversationsReadAssigned = "conversations:read_assigned"
+ PermConversationsReadTeamInbox = "conversations:read_team_inbox"
PermConversationsRead = "conversations:read"
PermConversationsUpdateUserAssignee = "conversations:update_user_assignee"
PermConversationsUpdateTeamAssignee = "conversations:update_team_assignee"
@@ -14,70 +15,60 @@ const (
PermMessagesRead = "messages:read"
PermMessagesWrite = "messages:write"
- // Conversation Status
- PermStatusRead = "status:read"
- PermStatusWrite = "status:write"
- PermStatusDelete = "status:delete"
+ // View
+ PermViewManage = "view:manage"
- // Admin
- PermAdminRead = "admin:read"
-
- // Settings
- PermSettingsGeneralWrite = "settings_general:write"
- PermSettingsNotificationsWrite = "settings_notifications:write"
- PermSettingsNotificationsRead = "settings_notifications:read"
-
- // OpenID Connect SSO
- PermOIDCRead = "oidc:read"
- PermOIDCWrite = "oidc:write"
- PermOIDCDelete = "oidc:delete"
+ // Status
+ PermStatusManage = "status:manage"
// Tags
- PermTagsWrite = "tags:write"
- PermTagsDelete = "tags:delete"
+ PermTagsManage = "tags:manage"
- // Canned Responses
- PermCannedResponsesWrite = "canned_responses:write"
- PermCannedResponsesDelete = "canned_responses:delete"
-
- // Dashboard
- PermDashboardGlobalRead = "dashboard_global:read"
+ // Macros
+ PermMacrosManage = "macros:manage"
// Users
- PermUsersRead = "users:read"
- PermUsersWrite = "users:write"
- PermUsersDelete = "users:delete"
+ PermUsersManage = "users:manage"
// Teams
- PermTeamsRead = "teams:read"
- PermTeamsWrite = "teams:write"
- PermTeamsDelete = "teams:delete"
+ PermTeamsManage = "teams:manage"
// Automations
- PermAutomationsRead = "automations:read"
- PermAutomationsWrite = "automations:write"
- PermAutomationsDelete = "automations:delete"
+ PermAutomationsManage = "automations:manage"
// Inboxes
- PermInboxesRead = "inboxes:read"
- PermInboxesWrite = "inboxes:write"
- PermInboxesDelete = "inboxes:delete"
+ PermInboxesManage = "inboxes:manage"
// Roles
- PermRolesRead = "roles:read"
- PermRolesWrite = "roles:write"
- PermRolesDelete = "roles:delete"
+ PermRolesManage = "roles:manage"
// Templates
- PermTemplatesRead = "templates:read"
- PermTemplatesWrite = "templates:write"
- PermTemplatesDelete = "templates:delete"
+ PermTemplatesManage = "templates:manage"
+
+ // Reports
+ PermReportsManage = "reports:manage"
+
+ // Business Hours
+ PermBusinessHoursManage = "business_hours:manage"
+
+ // SLA
+ PermSLAManage = "sla:manage"
+
+ // General Settings
+ PermGeneralSettingsManage = "general_settings:manage"
+
+ // Notification Settings
+ PermNotificationSettingsManage = "notification_settings:manage"
+
+ // OpenID Connect SSO
+ PermOIDCManage = "oidc:manage"
)
var validPermissions = map[string]struct{}{
PermConversationsReadAll: {},
PermConversationsReadUnassigned: {},
PermConversationsReadAssigned: {},
+ PermConversationsReadTeamInbox: {},
PermConversationsRead: {},
PermConversationsUpdateUserAssignee: {},
PermConversationsUpdateTeamAssignee: {},
@@ -86,40 +77,25 @@ var validPermissions = map[string]struct{}{
PermConversationsUpdateTags: {},
PermMessagesRead: {},
PermMessagesWrite: {},
- PermStatusRead: {},
- PermStatusWrite: {},
- PermStatusDelete: {},
- PermAdminRead: {},
- PermSettingsGeneralWrite: {},
- PermSettingsNotificationsWrite: {},
- PermSettingsNotificationsRead: {},
- PermOIDCRead: {},
- PermOIDCWrite: {},
- PermOIDCDelete: {},
- PermTagsWrite: {},
- PermTagsDelete: {},
- PermCannedResponsesWrite: {},
- PermCannedResponsesDelete: {},
- PermDashboardGlobalRead: {},
- PermUsersRead: {},
- PermUsersWrite: {},
- PermTeamsRead: {},
- PermTeamsWrite: {},
- PermAutomationsRead: {},
- PermAutomationsWrite: {},
- PermAutomationsDelete: {},
- PermInboxesRead: {},
- PermInboxesWrite: {},
- PermInboxesDelete: {},
- PermRolesRead: {},
- PermRolesWrite: {},
- PermRolesDelete: {},
- PermTemplatesRead: {},
- PermTemplatesWrite: {},
- PermTemplatesDelete: {},
+ PermViewManage: {},
+ PermStatusManage: {},
+ PermTagsManage: {},
+ PermMacrosManage: {},
+ PermUsersManage: {},
+ PermTeamsManage: {},
+ PermAutomationsManage: {},
+ PermInboxesManage: {},
+ PermRolesManage: {},
+ PermTemplatesManage: {},
+ PermReportsManage: {},
+ PermBusinessHoursManage: {},
+ PermSLAManage: {},
+ PermGeneralSettingsManage: {},
+ PermNotificationSettingsManage: {},
+ PermOIDCManage: {},
}
-// IsValidPermission retuns true if it's a valid perm.
+// IsValidPermission returns true if it's a valid permission.
func IsValidPermission(permission string) bool {
_, exists := validPermissions[permission]
return exists
diff --git a/internal/autoassigner/autoassigner.go b/internal/autoassigner/autoassigner.go
index 62ddf380..166e5ef5 100644
--- a/internal/autoassigner/autoassigner.go
+++ b/internal/autoassigner/autoassigner.go
@@ -4,14 +4,14 @@ package autoassigner
import (
"context"
"errors"
+ "fmt"
"strconv"
"sync"
"time"
- "github.com/abhinavxd/artemis/internal/conversation"
- "github.com/abhinavxd/artemis/internal/conversation/models"
- "github.com/abhinavxd/artemis/internal/team"
- umodels "github.com/abhinavxd/artemis/internal/user/models"
+ "github.com/abhinavxd/libredesk/internal/conversation/models"
+ tmodels "github.com/abhinavxd/libredesk/internal/team/models"
+ umodels "github.com/abhinavxd/libredesk/internal/user/models"
"github.com/mr-karan/balance"
"github.com/zerodha/logf"
)
@@ -20,30 +20,47 @@ var (
ErrTeamNotFound = errors.New("team not found")
)
+const (
+ AssignmentTypeRoundRobin = "Round robin"
+)
+
+type conversationStore interface {
+ GetUnassignedConversations() ([]models.Conversation, error)
+ UpdateConversationUserAssignee(conversationUUID string, userID int, user umodels.User) error
+ ActiveUserConversationsCount(userID int) (int, error)
+}
+
+type teamStore interface {
+ GetAll() ([]tmodels.Team, error)
+ GetMembers(teamID int) ([]umodels.User, error)
+}
+
// Engine represents a manager for assigning unassigned conversations
// to team agents in a round-robin pattern.
type Engine struct {
roundRobinBalancer map[int]*balance.Balance
// Mutex to protect the balancer map
- balanceMu sync.Mutex
+ balanceMu sync.Mutex
+ teamMaxAutoAssignments map[int]int
- systemUser umodels.User
- conversationManager *conversation.Manager
- teamManager *team.Manager
- lo *logf.Logger
- closed bool
- closedMu sync.Mutex
- wg sync.WaitGroup
+ systemUser umodels.User
+ conversationStore conversationStore
+ teamStore teamStore
+ lo *logf.Logger
+ closed bool
+ closedMu sync.Mutex
+ wg sync.WaitGroup
}
// New initializes a new Engine instance, set up with the provided team manager,
// conversation manager, and logger.
-func New(teamManager *team.Manager, conversationManager *conversation.Manager, systemUser umodels.User, lo *logf.Logger) (*Engine, error) {
+func New(teamStore teamStore, conversationStore conversationStore, systemUser umodels.User, lo *logf.Logger) (*Engine, error) {
var e = Engine{
- conversationManager: conversationManager,
- teamManager: teamManager,
- systemUser: systemUser,
- lo: lo,
+ conversationStore: conversationStore,
+ teamStore: teamStore,
+ systemUser: systemUser,
+ lo: lo,
+ teamMaxAutoAssignments: make(map[int]int),
}
balancer, err := e.populateTeamBalancer()
if err != nil {
@@ -55,8 +72,8 @@ func New(teamManager *team.Manager, conversationManager *conversation.Manager, s
// Run initiates the conversation assignment process and is to be invoked as a goroutine.
// This function continuously assigns unassigned conversations to agents at regular intervals.
-func (e *Engine) Run(ctx context.Context) {
- ticker := time.NewTicker(60 * time.Second)
+func (e *Engine) Run(ctx context.Context, autoAssignInterval time.Duration) {
+ ticker := time.NewTicker(autoAssignInterval)
defer ticker.Stop()
e.wg.Add(1)
@@ -73,6 +90,9 @@ func (e *Engine) Run(ctx context.Context) {
if closed {
return
}
+ if err := e.reloadBalancer(); err != nil {
+ e.lo.Error("error reloading balancer", "error", err)
+ }
if err := e.assignConversations(); err != nil {
e.lo.Error("error assigning conversations", "error", err)
}
@@ -92,14 +112,14 @@ func (e *Engine) Close() {
e.wg.Wait()
}
-// RefreshBalancer updates the round-robin balancer with the latest user and team data.
-func (e *Engine) RefreshBalancer() error {
+// reloadBalancer updates the round-robin balancer with the latest user and team data.
+func (e *Engine) reloadBalancer() error {
e.balanceMu.Lock()
defer e.balanceMu.Unlock()
balancer, err := e.populateTeamBalancer()
if err != nil {
- e.lo.Error("Error updating team balancer pool", "error", err)
+ e.lo.Error("error updating team balancer pool", "error", err)
return err
}
e.roundRobinBalancer = balancer
@@ -109,31 +129,33 @@ func (e *Engine) RefreshBalancer() error {
// populateTeamBalancer populates the team balancer pool with the team members.
func (e *Engine) populateTeamBalancer() (map[int]*balance.Balance, error) {
var (
- balancer = make(map[int]*balance.Balance)
+ balancer = make(map[int]*balance.Balance)
+ teams, err = e.teamStore.GetAll()
)
-
- teams, err := e.teamManager.GetAll()
if err != nil {
return nil, err
}
for _, team := range teams {
- if !team.AutoAssignConversations {
+ if team.ConversationAssignmentType != AssignmentTypeRoundRobin {
continue
}
- users, err := e.teamManager.GetTeamMembers(team.Name)
+ users, err := e.teamStore.GetMembers(team.ID)
if err != nil {
return nil, err
}
- // Add the users to team balancer pool.
+ // Add users to team's balancer pool.
for _, user := range users {
if _, ok := balancer[team.ID]; !ok {
balancer[team.ID] = balance.NewBalance()
}
balancer[team.ID].Add(strconv.Itoa(user.ID), 1)
}
+
+ // Set max auto assigned conversations for the team.
+ e.teamMaxAutoAssignments[team.ID] = team.MaxAutoAssignedConversations
}
return balancer, nil
}
@@ -141,42 +163,61 @@ func (e *Engine) populateTeamBalancer() (map[int]*balance.Balance, error) {
// assignConversations function fetches conversations that have been assigned to teams but not to any individual user,
// and then proceeds to assign them to team members based on a round-robin strategy.
func (e *Engine) assignConversations() error {
- unassigned, err := e.conversationManager.GetUnassignedConversations()
+ unassignedConversations, err := e.conversationStore.GetUnassignedConversations()
if err != nil {
- return err
+ return fmt.Errorf("fetching unassigned conversations: %w", err)
}
- e.lo.Debug("found unassigned conversations", "count", len(unassigned))
+ if len(unassignedConversations) > 0 {
+ e.lo.Debug("found unassigned conversations", "count", len(unassignedConversations))
+ }
- for _, conversation := range unassigned {
+ for _, conversation := range unassignedConversations {
// Get user from the pool.
- userIDStr, err := e.getUserFromPool(conversation)
+ userIDStr, err := e.getUserFromPool(conversation.AssignedTeamID.Int)
if err != nil {
- e.lo.Error("error fetching user from balancer pool", "error", err)
+ if err != ErrTeamNotFound {
+ e.lo.Error("error fetching user from balancer pool", "conversation_uuid", conversation.UUID, "error", err)
+ }
continue
}
// Convert to int.
userID, err := strconv.Atoi(userIDStr)
if err != nil {
- e.lo.Error("error converting user id from string to int", "error", err)
+ e.lo.Error("error converting user id from string to int", "user_id", userIDStr, "error", err)
continue
}
- // Assign conversation.
- e.conversationManager.UpdateConversationUserAssignee(conversation.UUID, userID, e.systemUser)
+ // Get active conversations count for the user.
+ activeConversationsCount, err := e.conversationStore.ActiveUserConversationsCount(userID)
+ if err != nil {
+ e.lo.Error("error fetching active conversations count for user", "user_id", userID, "error", err)
+ continue
+ }
+
+ // Check if user has reached the max auto assigned conversations limit.
+ if activeConversationsCount >= e.teamMaxAutoAssignments[conversation.AssignedTeamID.Int] {
+ e.lo.Debug("user has reached max auto assigned conversations limit, skipping auto assignment", "user_id", userID, "user_active_conversations_count", activeConversationsCount, "max_auto_assigned_conversations", e.teamMaxAutoAssignments[conversation.AssignedTeamID.Int])
+ continue
+ }
+
+ // Assign conversation to user.
+ if err := e.conversationStore.UpdateConversationUserAssignee(conversation.UUID, userID, e.systemUser); err != nil {
+ e.lo.Error("error assigning conversation", "conversation_uuid", conversation.UUID, "error", err)
+ continue
+ }
}
return nil
}
// getUserFromPool returns user ID from the team balancer pool.
-func (e *Engine) getUserFromPool(conversation models.Conversation) (string, error) {
+func (e *Engine) getUserFromPool(assignedTeamID int) (string, error) {
e.balanceMu.Lock()
defer e.balanceMu.Unlock()
- pool, ok := e.roundRobinBalancer[conversation.AssignedTeamID.Int]
+ pool, ok := e.roundRobinBalancer[assignedTeamID]
if !ok {
- e.lo.Warn("team not found in balancer", "team_id", conversation.AssignedTeamID.Int)
return "", ErrTeamNotFound
}
return pool.Get(), nil
diff --git a/internal/automation/automation.go b/internal/automation/automation.go
index 1657904f..96bd955b 100644
--- a/internal/automation/automation.go
+++ b/internal/automation/automation.go
@@ -11,12 +11,11 @@ import (
"sync"
"time"
- "github.com/abhinavxd/artemis/internal/automation/models"
- cmodels "github.com/abhinavxd/artemis/internal/conversation/models"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- mmodels "github.com/abhinavxd/artemis/internal/media/models"
- umodels "github.com/abhinavxd/artemis/internal/user/models"
+ "github.com/abhinavxd/libredesk/internal/automation/models"
+ cmodels "github.com/abhinavxd/libredesk/internal/conversation/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ umodels "github.com/abhinavxd/libredesk/internal/user/models"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
"github.com/zerodha/logf"
@@ -25,7 +24,6 @@ import (
var (
//go:embed queries.sql
efs embed.FS
-
// MaxQueueSize defines the maximum size of the task queues.
MaxQueueSize = 5000
)
@@ -51,8 +49,7 @@ type Engine struct {
rulesMu sync.RWMutex
q queries
lo *logf.Logger
- conversationStore ConversationStore
- systemUser umodels.User
+ conversationStore conversationStore
taskQueue chan ConversationTask
closed bool
closedMu sync.RWMutex
@@ -64,35 +61,31 @@ type Opts struct {
Lo *logf.Logger
}
-type ConversationStore interface {
- GetConversation(uuid string) (cmodels.Conversation, error)
- GetConversationsCreatedAfter(t time.Time) ([]cmodels.Conversation, error)
- UpdateConversationTeamAssignee(uuid string, teamID int, actor umodels.User) error
- UpdateConversationUserAssignee(uuid string, assigneeID int, actor umodels.User) error
- UpdateConversationStatus(uuid string, status []byte, actor umodels.User) error
- UpdateConversationPriority(uuid string, priority []byte, actor umodels.User) error
- SendPrivateNote(media []mmodels.Media, senderID int, conversationUUID, content string) error
- SendReply(media []mmodels.Media, senderID int, conversationUUID, content string) error
+type conversationStore interface {
+ ApplyAction(action models.RuleAction, conversation cmodels.Conversation, user umodels.User) error
+ GetConversation(teamID int, uuid string) (cmodels.Conversation, error)
+ GetConversationsCreatedAfter(time.Time) ([]cmodels.Conversation, error)
}
type queries struct {
- GetAll *sqlx.Stmt `query:"get-all"`
- GetRule *sqlx.Stmt `query:"get-rule"`
- InsertRule *sqlx.Stmt `query:"insert-rule"`
- UpdateRule *sqlx.Stmt `query:"update-rule"`
- DeleteRule *sqlx.Stmt `query:"delete-rule"`
- ToggleRule *sqlx.Stmt `query:"toggle-rule"`
- GetEnabledRules *sqlx.Stmt `query:"get-enabled-rules"`
+ GetAll *sqlx.Stmt `query:"get-all"`
+ GetRule *sqlx.Stmt `query:"get-rule"`
+ InsertRule *sqlx.Stmt `query:"insert-rule"`
+ UpdateRule *sqlx.Stmt `query:"update-rule"`
+ DeleteRule *sqlx.Stmt `query:"delete-rule"`
+ ToggleRule *sqlx.Stmt `query:"toggle-rule"`
+ GetEnabledRules *sqlx.Stmt `query:"get-enabled-rules"`
+ UpdateRuleWeight *sqlx.Stmt `query:"update-rule-weight"`
+ UpdateRuleExecutionMode *sqlx.Stmt `query:"update-rule-execution-mode"`
}
// New initializes a new Engine.
-func New(systemUser umodels.User, opt Opts) (*Engine, error) {
+func New(opt Opts) (*Engine, error) {
var (
q queries
e = &Engine{
- systemUser: systemUser,
- lo: opt.Lo,
- taskQueue: make(chan ConversationTask, MaxQueueSize),
+ lo: opt.Lo,
+ taskQueue: make(chan ConversationTask, MaxQueueSize),
}
)
if err := dbutil.ScanSQLFile("queries.sql", &q, opt.DB, efs); err != nil {
@@ -104,7 +97,7 @@ func New(systemUser umodels.User, opt Opts) (*Engine, error) {
}
// SetConversationStore sets conversations store.
-func (e *Engine) SetConversationStore(store ConversationStore) {
+func (e *Engine) SetConversationStore(store conversationStore) {
e.conversationStore = store
}
@@ -118,13 +111,13 @@ func (e *Engine) ReloadRules() {
// Run starts the Engine with a worker pool to evaluate rules based on events.
func (e *Engine) Run(ctx context.Context, workerCount int) {
- // Start the worker pool
+ // Spawn worker pool.
for i := 0; i < workerCount; i++ {
e.wg.Add(1)
go e.worker(ctx)
}
- // Ticker for timed triggers.
+ // Hourly ticker for timed triggers.
ticker := time.NewTicker(1 * time.Hour)
defer func() {
ticker.Stop()
@@ -213,7 +206,7 @@ func (e *Engine) ToggleRule(id int) error {
// UpdateRule updates an existing rule.
func (e *Engine) UpdateRule(id int, rule models.RuleRecord) error {
- if _, err := e.q.UpdateRule.Exec(id, rule.Name, rule.Description, rule.Type, pq.Array(rule.Events), rule.Rules); err != nil {
+ if _, err := e.q.UpdateRule.Exec(id, rule.Name, rule.Description, rule.Type, pq.Array(rule.Events), rule.Rules, rule.Enabled); err != nil {
e.lo.Error("error updating rule", "error", err)
return envelope.NewError(envelope.GeneralError, "Error updating automation rule.", nil)
}
@@ -244,41 +237,28 @@ func (e *Engine) DeleteRule(id int) error {
return nil
}
-// handleNewConversation handles new conversation events.
-func (e *Engine) handleNewConversation(conversationUUID string) {
- conversation, err := e.conversationStore.GetConversation(conversationUUID)
- if err != nil {
- e.lo.Error("error fetching conversation for new event", "uuid", conversationUUID, "error", err)
- return
+// UpdateRuleWeights updates the weights of the automation rules.
+func (e *Engine) UpdateRuleWeights(weights map[int]int) error {
+ for id, weight := range weights {
+ if _, err := e.q.UpdateRuleWeight.Exec(id, weight); err != nil {
+ e.lo.Error("error updating rule weight", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error updating weight", nil)
+ }
}
- rules := e.filterRulesByType(models.RuleTypeNewConversation, "")
- e.evalConversationRules(rules, conversation)
+ // Reload rules.
+ e.ReloadRules()
+ return nil
}
-// handleUpdateConversation handles update conversation events with specific eventType.
-func (e *Engine) handleUpdateConversation(conversationUUID, eventType string) {
- conversation, err := e.conversationStore.GetConversation(conversationUUID)
- if err != nil {
- e.lo.Error("error fetching conversation for update event", "uuid", conversationUUID, "error", err)
- return
- }
- rules := e.filterRulesByType(models.RuleTypeConversationUpdate, eventType)
- e.evalConversationRules(rules, conversation)
-}
-
-// handleTimeTrigger handles time trigger events.
-func (e *Engine) handleTimeTrigger() {
- thirtyDaysAgo := time.Now().Add(-30 * 24 * time.Hour)
- conversations, err := e.conversationStore.GetConversationsCreatedAfter(thirtyDaysAgo)
- if err != nil {
- e.lo.Error("error fetching conversations for time trigger", "error", err)
- return
- }
- rules := e.filterRulesByType(models.RuleTypeTimeTrigger, "")
- e.lo.Debug("fetched conversations for evaluating time triggers", "conversations_count", len(conversations), "rules_count", len(rules))
- for _, conversation := range conversations {
- e.evalConversationRules(rules, conversation)
+// UpdateRuleExecutionMode updates the execution mode for a type of rule.
+func (e *Engine) UpdateRuleExecutionMode(ruleType, mode string) error {
+ if _, err := e.q.UpdateRuleExecutionMode.Exec(ruleType, mode); err != nil {
+ e.lo.Error("error updating rule execution mode", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error updating rule execution mode", nil)
}
+ // Reload rules.
+ e.ReloadRules()
+ return nil
}
// EvaluateNewConversationRules enqueues a new conversation for rule evaluation.
@@ -322,6 +302,64 @@ func (e *Engine) EvaluateConversationUpdateRules(conversationUUID string, eventT
}
}
+// handleNewConversation handles new conversation events.
+func (e *Engine) handleNewConversation(conversationUUID string) {
+ e.lo.Debug("handling new conversation", "uuid", conversationUUID)
+ conversation, err := e.conversationStore.GetConversation(0, conversationUUID)
+ if err != nil {
+ e.lo.Error("error fetching conversation for new event", "uuid", conversationUUID, "error", err)
+ return
+ }
+ rules := e.filterRulesByType(models.RuleTypeNewConversation, "")
+ if len(rules) == 0 {
+ e.lo.Warn("no rules to evaluate for new conversation", "uuid", conversationUUID)
+ return
+ }
+ e.evalConversationRules(rules, conversation)
+}
+
+// handleUpdateConversation handles update conversation events with specific eventType.
+func (e *Engine) handleUpdateConversation(conversationUUID, eventType string) {
+ e.lo.Debug("handling update conversation", "uuid", conversationUUID, "event_type", eventType)
+ conversation, err := e.conversationStore.GetConversation(0, conversationUUID)
+ if err != nil {
+ e.lo.Error("error fetching conversation for update event", "uuid", conversationUUID, "error", err)
+ return
+ }
+ rules := e.filterRulesByType(models.RuleTypeConversationUpdate, eventType)
+ if len(rules) == 0 {
+ e.lo.Warn("no rules to evaluate for conversation update", "uuid", conversationUUID, "event_type", eventType)
+ return
+ }
+ e.evalConversationRules(rules, conversation)
+}
+
+// handleTimeTrigger handles time trigger events.
+func (e *Engine) handleTimeTrigger() {
+ e.lo.Debug("handling time triggers")
+ thirtyDaysAgo := time.Now().Add(-30 * 24 * time.Hour)
+ conversations, err := e.conversationStore.GetConversationsCreatedAfter(thirtyDaysAgo)
+ if err != nil {
+ e.lo.Error("error fetching conversations for time trigger", "error", err)
+ return
+ }
+ rules := e.filterRulesByType(models.RuleTypeTimeTrigger, "")
+ if len(rules) == 0 {
+ e.lo.Warn("no rules to evaluate for time trigger")
+ return
+ }
+ e.lo.Debug("fetched conversations for evaluating time triggers", "conversations_count", len(conversations), "rules_count", len(rules))
+ for _, c := range conversations {
+ // Fetch entire conversation.
+ conversation, err := e.conversationStore.GetConversation(0, c.UUID)
+ if err != nil {
+ e.lo.Error("error fetching conversation for time trigger", "uuid", c.UUID, "error", err)
+ continue
+ }
+ e.evalConversationRules(rules, conversation)
+ }
+}
+
// queryRules fetches automation rules from the database.
func (e *Engine) queryRules() []models.Rule {
var (
@@ -340,10 +378,11 @@ func (e *Engine) queryRules() []models.Rule {
e.lo.Error("error unmarshalling rule JSON", "error", err)
continue
}
- // Set the Type and event for each rule in the batch.
+ // Set values from DB.
for i := range rulesBatch {
rulesBatch[i].Type = rule.Type
rulesBatch[i].Events = rule.Events
+ rulesBatch[i].ExecutionMode = rule.ExecutionMode
}
filteredRules = append(filteredRules, rulesBatch...)
}
diff --git a/internal/automation/evaluator.go b/internal/automation/evaluator.go
index 2520b58b..c9ba3b35 100644
--- a/internal/automation/evaluator.go
+++ b/internal/automation/evaluator.go
@@ -6,9 +6,9 @@ import (
"strings"
"time"
- "github.com/abhinavxd/artemis/internal/automation/models"
- cmodels "github.com/abhinavxd/artemis/internal/conversation/models"
- mmodels "github.com/abhinavxd/artemis/internal/media/models"
+ "github.com/abhinavxd/libredesk/internal/automation/models"
+ cmodels "github.com/abhinavxd/libredesk/internal/conversation/models"
+ umodels "github.com/abhinavxd/libredesk/internal/user/models"
)
// evalConversationRules evaluates a list of rules against a given conversation.
@@ -16,7 +16,7 @@ import (
// the corresponding actions are executed.
func (e *Engine) evalConversationRules(rules []models.Rule, conversation cmodels.Conversation) {
for _, rule := range rules {
- e.lo.Debug("evaluating rule for conversation", "rule", rule, "conversation_uuid", conversation.UUID)
+ e.lo.Debug("evaluating rule for conversation", "rule", rule, "conversation_id", conversation.ID)
// At max there can be only 2 groups.
if len(rule.Groups) > 2 {
@@ -24,20 +24,30 @@ func (e *Engine) evalConversationRules(rules []models.Rule, conversation cmodels
continue
}
- var results []bool
- for _, group := range rule.Groups {
+ var groupEvalResults []bool
+ for idx, group := range rule.Groups {
+ if len(group.Rules) == 0 {
+ e.lo.Debug("no rules found in group, skipping rule group evaluation", "group_num", idx+1, "conversation_uuid", conversation.UUID)
+ continue
+ }
result := e.evaluateGroup(group.Rules, group.LogicalOp, conversation)
- e.lo.Debug("evaluating group rules", "logical_op", group.LogicalOp, "result", result, "conversation_uuid", conversation.UUID)
- results = append(results, result)
+ e.lo.Debug("group rule evaluation complete", "logical_op", group.LogicalOp, "result", result, "conversation_uuid", conversation.UUID)
+ groupEvalResults = append(groupEvalResults, result)
}
- if evaluateFinalResult(results, rule.GroupOperator) {
+ if evaluateFinalResult(groupEvalResults, rule.GroupOperator) {
e.lo.Debug("rule evaluation successful executing actions", "conversation_uuid", conversation.UUID)
for _, action := range rule.Actions {
- e.applyAction(action, conversation)
+ if err := e.conversationStore.ApplyAction(action, conversation, umodels.User{}); err != nil {
+ e.lo.Error("error applying action on conversation", "action", action, "conversation_uuid", conversation.UUID, "error", err)
+ }
+ }
+ if rule.ExecutionMode == models.ExecutionModeFirstMatch {
+ e.lo.Debug("first match rule execution mode, breaking out of rule evaluation", "conversation_uuid", conversation.UUID)
+ break
}
} else {
- e.lo.Debug("rule evaluation failed", "conversation_uuid", conversation.UUID)
+ e.lo.Debug("rule evaluation failed, skipping actions", "group_eval_results", groupEvalResults, "conversation_uuid", conversation.UUID)
}
}
}
@@ -100,14 +110,16 @@ func (e *Engine) evaluateRule(rule models.RuleDetail, conversation cmodels.Conve
// Extract the value from the conversation based on the rule's field
switch rule.Field {
+ case models.ContactEmail:
+ valueToCompare = conversation.Contact.Email.String
case models.ConversationSubject:
- valueToCompare = conversation.Subject
+ valueToCompare = conversation.Subject.String
case models.ConversationContent:
- valueToCompare = conversation.LastMessage
+ valueToCompare = conversation.LastMessage.String
case models.ConversationStatus:
- valueToCompare = conversation.Status.String
+ valueToCompare = strconv.Itoa(conversation.StatusID.Int)
case models.ConversationPriority:
- valueToCompare = conversation.Priority.String
+ valueToCompare = strconv.Itoa(conversation.PriorityID.Int)
case models.ConversationAssignedTeam:
if conversation.AssignedTeamID.Valid {
valueToCompare = strconv.Itoa(conversation.AssignedTeamID.Int)
@@ -119,15 +131,16 @@ func (e *Engine) evaluateRule(rule models.RuleDetail, conversation cmodels.Conve
case models.ConversationHoursSinceCreated:
valueToCompare = fmt.Sprintf("%.0f", (time.Since(conversation.CreatedAt).Hours()))
case models.ConversationHoursSinceResolved:
- if conversation.ResolvedAt.Valid {
+ if !conversation.ResolvedAt.IsZero() {
valueToCompare = fmt.Sprintf("%.0f", (time.Since(conversation.ResolvedAt.Time).Hours()))
}
+ case models.ConversationInbox:
+ valueToCompare = strconv.Itoa(conversation.InboxID)
default:
e.lo.Error("unrecognized rule field", "field", rule.Field)
return false
}
- // Case sensitivity handling
if !rule.CaseSensitiveMatch {
valueToCompare = strings.ToLower(valueToCompare)
rule.Value = strings.ToLower(rule.Value)
@@ -155,31 +168,35 @@ func (e *Engine) evaluateRule(rule models.RuleDetail, conversation cmodels.Conve
case models.RuleOperatorNotEqual:
conditionMet = valueToCompare != rule.Value
case models.RuleOperatorContains:
- // Split the value to compare into words
- words := strings.Fields(valueToCompare)
- wordMap := make(map[string]struct{}, len(words))
- for _, word := range words {
- wordMap[word] = struct{}{}
- }
- // Check if any of the rule values exist as complete words
- for _, val := range ruleValues {
- if _, exists := wordMap[val]; exists {
+ // Normalize input text by collapsing multiple spaces
+ normalizedInputText := strings.Join(strings.Fields(valueToCompare), " ")
+ conditionMet = false
+
+ // Check each rule value against the normalized input
+ for _, ruleValue := range ruleValues {
+ // Normalize rule value by collapsing multiple spaces
+ normalizedRuleValue := strings.Join(strings.Fields(ruleValue), " ")
+ if strings.Contains(
+ strings.ToLower(normalizedInputText),
+ strings.ToLower(normalizedRuleValue),
+ ) {
conditionMet = true
break
}
}
case models.RuleOperatorNotContains:
- // Split the value to compare into words
- words := strings.Fields(valueToCompare)
- wordMap := make(map[string]struct{}, len(words))
- for _, word := range words {
- wordMap[word] = struct{}{}
- }
-
- // Check if none of the rule values exist as complete words
+ // Normalize input text by collapsing multiple spaces
+ normalizedInputText := strings.Join(strings.Fields(valueToCompare), " ")
conditionMet = true
- for _, val := range ruleValues {
- if _, exists := wordMap[val]; exists {
+
+ // Check each rule value against the normalized input
+ for _, ruleValue := range ruleValues {
+ // Normalize rule value by collapsing multiple spaces
+ normalizedRuleValue := strings.Join(strings.Fields(ruleValue), " ")
+ if strings.Contains(
+ strings.ToLower(normalizedInputText),
+ strings.ToLower(normalizedRuleValue),
+ ) {
conditionMet = false
break
}
@@ -193,60 +210,9 @@ func (e *Engine) evaluateRule(rule models.RuleDetail, conversation cmodels.Conve
value2, _ := strconv.Atoi(rule.Value)
conditionMet = value1 > value2
default:
- e.lo.Error("unrecognized rule logical operator", "operator", rule.Operator)
+ e.lo.Error("error unrecognized rule logical operator", "operator", rule.Operator)
return false
}
-
- e.lo.Debug("rule conditions status", "met", conditionMet,
- "conversation_uuid", conversation.UUID)
+ e.lo.Debug("conversation automation rule status", "has_met", conditionMet, "conversation_uuid", conversation.UUID)
return conditionMet
}
-
-// applyAction applies a specific action to the given conversation.
-func (e *Engine) applyAction(action models.RuleAction, conversation cmodels.Conversation) error {
- switch action.Type {
- case models.ActionAssignTeam:
- e.lo.Debug("executing assign team action", "value", action.Action, "conversation_uuid", conversation.UUID)
- teamID, err := strconv.Atoi(action.Action)
- if err != nil {
- e.lo.Error("error converting string to int", "string", action.Action, "error", err)
- return err
- }
- if err := e.conversationStore.UpdateConversationTeamAssignee(conversation.UUID, teamID, e.systemUser); err != nil {
- return err
- }
- case models.ActionAssignUser:
- e.lo.Debug("executing assign user action", "value", action.Action, "conversation_uuid", conversation.UUID)
- agentID, err := strconv.Atoi(action.Action)
- if err != nil {
- e.lo.Error("error converting string to int", "string", action.Action, "error", err)
- return err
- }
- if err := e.conversationStore.UpdateConversationUserAssignee(conversation.UUID, agentID, e.systemUser); err != nil {
- return err
- }
- case models.ActionSetPriority:
- e.lo.Debug("executing set priority action", "value", action.Action, "conversation_uuid", conversation.UUID)
- if err := e.conversationStore.UpdateConversationPriority(conversation.UUID, []byte(action.Action), e.systemUser); err != nil {
- return err
- }
- case models.ActionSetStatus:
- e.lo.Debug("executing set status action", "value", action.Action, "conversation_uuid", conversation.UUID)
- if err := e.conversationStore.UpdateConversationStatus(conversation.UUID, []byte(action.Action), e.systemUser); err != nil {
- return err
- }
- case models.ActionSendPrivateNote:
- e.lo.Debug("executing send private note action", "value", action.Action, "conversation_uuid", conversation.UUID)
- if err := e.conversationStore.SendPrivateNote([]mmodels.Media{}, e.systemUser.ID, conversation.UUID, action.Action); err != nil {
- return err
- }
- case models.ActionReply:
- e.lo.Debug("executing reply action", "value", action.Action, "conversation_uuid", conversation.UUID)
- if err := e.conversationStore.SendReply([]mmodels.Media{}, e.systemUser.ID, conversation.UUID, action.Action); err != nil {
- return err
- }
- default:
- return fmt.Errorf("unrecognized rule action: %s", action.Type)
- }
- return nil
-}
diff --git a/internal/automation/models/models.go b/internal/automation/models/models.go
index 02eaa03b..d3268c44 100644
--- a/internal/automation/models/models.go
+++ b/internal/automation/models/models.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"time"
+ authzModels "github.com/abhinavxd/libredesk/internal/authz/models"
"github.com/lib/pq"
)
@@ -13,7 +14,10 @@ const (
ActionSetStatus = "set_status"
ActionSetPriority = "set_priority"
ActionSendPrivateNote = "send_private_note"
- ActionReply = "reply"
+ ActionReply = "send_reply"
+ ActionSetSLA = "set_sla"
+ ActionSetTags = "set_tags"
+ ActionSendCSAT = "send_csat"
OperatorAnd = "AND"
OperatorOR = "OR"
@@ -38,6 +42,8 @@ const (
ConversationAssignedTeam = "assigned_team"
ConversationHoursSinceCreated = "hours_since_created"
ConversationHoursSinceResolved = "hours_since_resolved"
+ ConversationInbox = "inbox"
+ ContactEmail = "contact_email"
EventConversationUserAssigned = "conversation.user.assigned"
EventConversationTeamAssigned = "conversation.team.assigned"
@@ -45,27 +51,44 @@ const (
EventConversationPriorityChange = "conversation.priority.change"
EventConversationMessageOutgoing = "conversation.message.outgoing"
EventConversationMessageIncoming = "conversation.message.incoming"
+
+ ExecutionModeAll = "all"
+ ExecutionModeFirstMatch = "first_match"
)
+// ActionPermissions maps actions to permissions
+var ActionPermissions = map[string]string{
+ ActionAssignTeam: authzModels.PermConversationsUpdateTeamAssignee,
+ ActionAssignUser: authzModels.PermConversationsUpdateUserAssignee,
+ ActionSetStatus: authzModels.PermConversationsUpdateStatus,
+ ActionSetPriority: authzModels.PermConversationsUpdatePriority,
+ ActionSendPrivateNote: authzModels.PermMessagesWrite,
+ ActionReply: authzModels.PermMessagesWrite,
+ ActionSetTags: authzModels.PermConversationsUpdateTags,
+}
+
// RuleRecord represents a rule record in the database
type RuleRecord struct {
- ID int `db:"id" json:"id"`
- CreatedAt time.Time `db:"created_at" json:"created_at"`
- UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
- Name string `db:"name" json:"name"`
- Description string `db:"description" json:"description"`
- Type string `db:"type" json:"type"`
- Events pq.StringArray `db:"events" json:"events"`
- Disabled bool `db:"disabled" json:"disabled"`
- Rules json.RawMessage `db:"rules" json:"rules"`
+ ID int `db:"id" json:"id"`
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+ Name string `db:"name" json:"name"`
+ Description string `db:"description" json:"description"`
+ Type string `db:"type" json:"type"`
+ Events pq.StringArray `db:"events" json:"events"`
+ Enabled bool `db:"enabled" json:"enabled"`
+ Weight int `db:"weight" json:"weight"`
+ ExecutionMode string `db:"execution_mode" json:"execution_mode"`
+ Rules json.RawMessage `db:"rules" json:"rules"`
}
type Rule struct {
- Type string `json:"type" db:"type"`
- Events []string `json:"event" db:"event"`
- GroupOperator string `json:"group_operator" db:"group_operator"`
- Groups []RuleGroup `json:"groups" db:"groups"`
- Actions []RuleAction `json:"actions" db:"actions"`
+ Type string `json:"type"`
+ ExecutionMode string `json:"execution_mode"`
+ Events []string `json:"event"`
+ GroupOperator string `json:"group_operator"`
+ Groups []RuleGroup `json:"groups"`
+ Actions []RuleAction `json:"actions"`
}
type RuleGroup struct {
@@ -81,6 +104,7 @@ type RuleDetail struct {
}
type RuleAction struct {
- Type string `json:"type" db:"type"`
- Action string `json:"value" db:"value"`
+ Type string `json:"type" db:"type"`
+ Value []string `json:"value" db:"value"`
+ DisplayValue []string `json:"display_value" db:"-"`
}
diff --git a/internal/automation/queries.sql b/internal/automation/queries.sql
index 97832c42..89f40833 100644
--- a/internal/automation/queries.sql
+++ b/internal/automation/queries.sql
@@ -2,18 +2,19 @@
select
type,
events,
- rules
-from automation_rules where disabled is not TRUE;
+ rules,
+ execution_mode
+from automation_rules where enabled is TRUE ORDER BY weight ASC;
-- name: get-all
-SELECT id, created_at, updated_at, name, description, type, events, rules, disabled from automation_rules where type = $1;
+SELECT id, created_at, updated_at, enabled, name, description, type, events, rules, execution_mode from automation_rules where type = $1 ORDER BY weight ASC;
-- name: get-rule
-SELECT id, created_at, updated_at, name, description, type, events, rules from automation_rules where id = $1;
+SELECT id, created_at, updated_at, enabled, name, description, type, events, rules, execution_mode from automation_rules where id = $1;
-- name: update-rule
-INSERT INTO automation_rules(id, name, description, type, events, rules)
-VALUES($1, $2, $3, $4, $5, $6)
+INSERT INTO automation_rules(id, name, description, type, events, rules, enabled)
+VALUES($1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (id)
DO UPDATE SET
name = EXCLUDED.name,
@@ -21,6 +22,7 @@ DO UPDATE SET
type = EXCLUDED.type,
events = EXCLUDED.events,
rules = EXCLUDED.rules,
+ enabled = EXCLUDED.enabled,
updated_at = now()
WHERE $1 > 0;
@@ -32,5 +34,15 @@ delete from automation_rules where id = $1;
-- name: toggle-rule
UPDATE automation_rules
-SET disabled = NOT disabled, updated_at = NOW()
+SET enabled = NOT enabled, updated_at = NOW()
WHERE id = $1;
+
+-- name: update-rule-weight
+UPDATE automation_rules
+SET weight = $2, updated_at = NOW()
+WHERE id = $1;
+
+-- name: update-rule-execution-mode
+UPDATE automation_rules
+SET execution_mode = $2, updated_at = NOW()
+WHERE type = $1;
\ No newline at end of file
diff --git a/internal/business_hours/business_hours.go b/internal/business_hours/business_hours.go
new file mode 100644
index 00000000..9cb7a18c
--- /dev/null
+++ b/internal/business_hours/business_hours.go
@@ -0,0 +1,107 @@
+// Package businesshours handles the management of business hours and holidays.
+package businesshours
+
+import (
+ "database/sql"
+ "embed"
+ "errors"
+
+ "github.com/abhinavxd/libredesk/internal/business_hours/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/jmoiron/sqlx"
+ "github.com/jmoiron/sqlx/types"
+ "github.com/volatiletech/null/v9"
+ "github.com/zerodha/logf"
+)
+
+var (
+ //go:embed queries.sql
+ efs embed.FS
+ ErrBusinessHoursNotFound = errors.New("business hours not found")
+)
+
+// Manager manages business hours.
+type Manager struct {
+ q queries
+ lo *logf.Logger
+}
+
+// Opts contains options for initializing the Manager.
+type Opts struct {
+ DB *sqlx.DB
+ Lo *logf.Logger
+}
+
+// queries contains prepared SQL queries.
+type queries struct {
+ GetBusinessHours *sqlx.Stmt `query:"get-business-hours"`
+ GetAllBusinessHours *sqlx.Stmt `query:"get-all-business-hours"`
+ InsertBusinessHours *sqlx.Stmt `query:"insert-business-hours"`
+ DeleteBusinessHours *sqlx.Stmt `query:"delete-business-hours"`
+ UpdateBusinessHours *sqlx.Stmt `query:"update-business-hours"`
+}
+
+// New creates and returns a new instance of the Manager.
+func New(opts Opts) (*Manager, error) {
+ var q queries
+ if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
+ return nil, err
+ }
+ return &Manager{
+ q: q,
+ lo: opts.Lo,
+ }, nil
+}
+
+// Get retrieves business hours.
+func (m *Manager) Get(id int) (models.BusinessHours, error) {
+ var businessHours models.BusinessHours
+ if err := m.q.GetBusinessHours.Get(&businessHours, id); err != nil {
+ if err == sql.ErrNoRows {
+ return businessHours, ErrBusinessHoursNotFound
+ }
+ return businessHours, err
+ }
+ return businessHours, nil
+}
+
+// GetAll retrieves all business hours.
+func (m *Manager) GetAll() ([]models.BusinessHours, error) {
+ var hours = make([]models.BusinessHours, 0)
+ if err := m.q.GetAllBusinessHours.Select(&hours); err != nil {
+ m.lo.Error("error fetching business hours", "error", err)
+ return nil, envelope.NewError(envelope.GeneralError, "Error fetching business hours", nil)
+ }
+ return hours, nil
+}
+
+// Create creates new business hours.
+func (m *Manager) Create(name string, description null.String, isAlwaysOpen bool, workingHrs, holidays types.JSONText) error {
+ if _, err := m.q.InsertBusinessHours.Exec(name, description, isAlwaysOpen, workingHrs, holidays); err != nil {
+ m.lo.Error("error inserting business hours", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error creating business hours", nil)
+ }
+ return nil
+}
+
+// Delete deletes business hours by ID.
+func (m *Manager) Delete(id int) error {
+ if _, err := m.q.DeleteBusinessHours.Exec(id); err != nil {
+ if dbutil.IsForeignKeyError(err) {
+ return envelope.NewError(envelope.GeneralError, "Cannot delete business hours as it is being used", nil)
+ }
+ m.lo.Error("error deleting business hours", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error deleting business hours", nil)
+ }
+ return nil
+}
+
+// Update updates business hours by ID.
+func (m *Manager) Update(id int, name string, description null.String, isAlwaysOpen bool, workingHrs, holidays types.JSONText) error {
+ if _, err := m.q.UpdateBusinessHours.Exec(id, name, description, isAlwaysOpen, workingHrs, holidays); err != nil {
+ m.lo.Error("error updating business hours", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error updating business hours", nil)
+ }
+ return nil
+}
diff --git a/internal/business_hours/models/models.go b/internal/business_hours/models/models.go
new file mode 100644
index 00000000..9d82325b
--- /dev/null
+++ b/internal/business_hours/models/models.go
@@ -0,0 +1,35 @@
+// Package models contains the data models for the businesshours package.
+package models
+
+import (
+ "time"
+
+ "github.com/jmoiron/sqlx/types"
+ "github.com/volatiletech/null/v9"
+)
+
+// BusinessHours represents the business in the database.
+type BusinessHours struct {
+ ID int `db:"id" json:"id"`
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+ Name string `db:"name" json:"name"`
+ Description null.String `db:"description" json:"description"`
+ IsAlwaysOpen bool `db:"is_always_open" json:"is_always_open"`
+ Holidays types.JSONText `db:"holidays" json:"holidays"`
+ Hours types.JSONText `db:"hours" json:"hours"`
+}
+
+// WorkingHours represents the working hours for a specific day.
+type WorkingHours struct {
+ OpenAllDay bool `json:"open_all_day"`
+ ClosedAllDay bool `json:"closed_all_day"`
+ Open string `json:"open"`
+ Close string `json:"close"`
+}
+
+// Holiday represents a holiday.
+type Holiday struct {
+ Name string `json:"name"`
+ Date string `json:"date"`
+}
diff --git a/internal/business_hours/queries.sql b/internal/business_hours/queries.sql
new file mode 100644
index 00000000..37225999
--- /dev/null
+++ b/internal/business_hours/queries.sql
@@ -0,0 +1,44 @@
+-- name: get-business-hours
+SELECT id,
+ created_at,
+ updated_at,
+ "name",
+ description,
+ is_always_open,
+ hours,
+ holidays
+FROM business_hours
+WHERE id = $1;
+
+-- name: get-all-business-hours
+SELECT id,
+ created_at,
+ updated_at,
+ "name",
+ description
+FROM business_hours
+ORDER BY updated_at DESC;
+
+-- name: insert-business-hours
+INSERT INTO business_hours (
+ "name",
+ description,
+ is_always_open,
+ hours,
+ holidays
+ )
+VALUES ($1, $2, $3, $4, $5);
+
+-- name: delete-business-hours
+DELETE FROM business_hours
+WHERE id = $1;
+
+-- name: update-business-hours
+UPDATE business_hours
+SET "name" = $2,
+ description = $3,
+ is_always_open = $4,
+ hours = $5,
+ holidays = $6,
+ updated_at = NOW()
+WHERE id = $1;
\ No newline at end of file
diff --git a/internal/cannedresp/cannedresp.go b/internal/cannedresp/cannedresp.go
deleted file mode 100644
index b4fe4284..00000000
--- a/internal/cannedresp/cannedresp.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// Package cannedresp provides functionality to manage canned responses in the system.
-package cannedresp
-
-import (
- "embed"
-
- "github.com/abhinavxd/artemis/internal/cannedresp/models"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/jmoiron/sqlx"
- "github.com/zerodha/logf"
-)
-
-var (
- //go:embed queries.sql
- efs embed.FS
-)
-
-// Manager handles the operations related to canned responses.
-type Manager struct {
- q queries
- lo *logf.Logger
-}
-
-// Opts holds the options for creating a new Manager.
-type Opts struct {
- DB *sqlx.DB
- Lo *logf.Logger
-}
-
-type queries struct {
- GetAll *sqlx.Stmt `query:"get-all"`
- Create *sqlx.Stmt `query:"create"`
- Update *sqlx.Stmt `query:"update"`
- Delete *sqlx.Stmt `query:"delete"`
-}
-
-// New initializes a new Manager.
-func New(opts Opts) (*Manager, error) {
- var q queries
-
- if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
- return nil, err
- }
-
- return &Manager{
- q: q,
- lo: opts.Lo,
- }, nil
-}
-
-// GetAll retrieves all canned responses.
-func (t *Manager) GetAll() ([]models.CannedResponse, error) {
- var c = make([]models.CannedResponse, 0)
- if err := t.q.GetAll.Select(&c); err != nil {
- t.lo.Error("error fetching canned responses", "error", err)
- return c, envelope.NewError(envelope.GeneralError, "Error fetching canned responses", nil)
- }
- return c, nil
-}
-
-// Create adds a new canned response.
-func (t *Manager) Create(title, content string) error {
- if _, err := t.q.Create.Exec(title, content); err != nil {
- t.lo.Error("error creating canned response", "error", err)
- return envelope.NewError(envelope.GeneralError, "Error creating canned response", nil)
- }
- return nil
-}
-
-// Update modifies an existing canned response.
-func (t *Manager) Update(id int, title, content string) error {
- result, err := t.q.Update.Exec(id, title, content)
- if err != nil {
- t.lo.Error("error updating canned response", "error", err)
- return envelope.NewError(envelope.GeneralError, "Error updating canned response", nil)
- }
- rowsAffected, _ := result.RowsAffected()
- if rowsAffected == 0 {
- return envelope.NewError(envelope.NotFoundError, "Canned response not found", nil)
- }
- return nil
-}
-
-// Delete removes a canned response by ID.
-func (t *Manager) Delete(id int) error {
- result, err := t.q.Delete.Exec(id)
- if err != nil {
- t.lo.Error("error deleting canned response", "error", err)
- return envelope.NewError(envelope.GeneralError, "Error deleting canned response", nil)
- }
- rowsAffected, _ := result.RowsAffected()
- if rowsAffected == 0 {
- return envelope.NewError(envelope.NotFoundError, "Canned response not found", nil)
- }
- return nil
-}
diff --git a/internal/cannedresp/models/models.go b/internal/cannedresp/models/models.go
deleted file mode 100644
index 60dd1029..00000000
--- a/internal/cannedresp/models/models.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package models
-
-import "time"
-
-type CannedResponse struct {
- ID string `db:"id" json:"id"`
- CreatedAt time.Time `db:"created_at" json:"created_at"`
- UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
- Title string `db:"title" json:"title"`
- Content string `db:"content" json:"content"`
-}
diff --git a/internal/cannedresp/queries.sql b/internal/cannedresp/queries.sql
deleted file mode 100644
index 05dd6cfa..00000000
--- a/internal/cannedresp/queries.sql
+++ /dev/null
@@ -1,13 +0,0 @@
--- name: get-all
-SELECT id, title, content, created_at, updated_at FROM canned_responses order by updated_at desc;
-
--- name: create
-INSERT INTO canned_responses (title, content)
-VALUES ($1, $2);
-
--- name: update
-UPDATE canned_responses
-SET title = $2, content = $3, updated_at = now() where id = $1;
-
--- name: delete
-DELETE FROM canned_responses WHERE id = $1;
\ No newline at end of file
diff --git a/internal/colorlog/colorlog.go b/internal/colorlog/colorlog.go
new file mode 100644
index 00000000..cd4d99cb
--- /dev/null
+++ b/internal/colorlog/colorlog.go
@@ -0,0 +1,19 @@
+// package colorlog provides logging in color.
+package colorlog
+
+import "log"
+
+const (
+ ANSIColourGreen = "\x1b[32m"
+ ANSIColourRed = "\x1b[31m"
+)
+
+// Green logs messages in green color.
+func Green(format string, v ...interface{}) {
+ log.Printf("%s"+format+"\x1b[0m", append([]interface{}{ANSIColourGreen}, v...)...)
+}
+
+// Red logs messages in red color.
+func Red(format string, v ...interface{}) {
+ log.Printf("%s"+format+"\x1b[0m", append([]interface{}{ANSIColourRed}, v...)...)
+}
diff --git a/internal/contact/contact.go b/internal/contact/contact.go
deleted file mode 100644
index a9a3caf2..00000000
--- a/internal/contact/contact.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Package contact provides functionality to manage contacts in the system.
-package contact
-
-import (
- "embed"
-
- "github.com/abhinavxd/artemis/internal/contact/models"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/jmoiron/sqlx"
- "github.com/zerodha/logf"
-)
-
-var (
- //go:embed queries.sql
- efs embed.FS
-)
-
-// Manager handles the operations related to contacts.
-type Manager struct {
- q queries
- lo *logf.Logger
-}
-
-// Opts holds the options for creating a new Manager.
-type Opts struct {
- DB *sqlx.DB
- Lo *logf.Logger
-}
-
-type queries struct {
- UpsertContact *sqlx.Stmt `query:"upsert-contact"`
-}
-
-// New initializes a new Manager.
-func New(opts Opts) (*Manager, error) {
- var q queries
-
- if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
- return nil, err
- }
-
- return &Manager{
- q: q,
- lo: opts.Lo,
- }, nil
-}
-
-// Upsert inserts or updates a contact and returns the contact ID.
-func (m *Manager) Upsert(con models.Contact) (int, error) {
- var contactID int
- if err := m.q.UpsertContact.QueryRow(con.Source, con.SourceID, con.InboxID,
- con.FirstName, con.LastName, con.Email, con.PhoneNumber, con.AvatarURL).Scan(&contactID); err != nil {
- m.lo.Error("error upserting contact", "error", err)
- return contactID, err
- }
- return contactID, nil
-}
diff --git a/internal/contact/models/models.go b/internal/contact/models/models.go
deleted file mode 100644
index ebcb76a6..00000000
--- a/internal/contact/models/models.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package models
-
-import (
- "time"
-
- "github.com/volatiletech/null/v9"
-)
-
-type Contact struct {
- ID int `db:"id" json:"id,omitempty"`
- CreatedAt time.Time `db:"created_at" json:"created_at,omitempty"`
- FirstName string `db:"first_name" json:"first_name"`
- LastName string `db:"last_name" json:"last_name"`
- Email string `db:"email" json:"email"`
- PhoneNumber null.String `db:"phone_number" json:"phone_number"`
- AvatarURL null.String `db:"avatar_url" json:"avatar_url"`
- InboxID int `db:"inbox_id" json:"-"`
- Source string `db:"source" json:"-"`
- SourceID string `db:"source_id" json:"-"`
-}
diff --git a/internal/contact/queries.sql b/internal/contact/queries.sql
deleted file mode 100644
index 010df5de..00000000
--- a/internal/contact/queries.sql
+++ /dev/null
@@ -1,35 +0,0 @@
--- name: upsert-contact
--- Check if contact exists
-WITH existing_contact AS (
- SELECT contact_id
- FROM public.contact_methods
- WHERE source = $1 AND source_id = $2
-)
-
--- Insert contact if it does not exist
-, ins_contact AS (
- INSERT INTO public.contacts (first_name, last_name, email, phone_number, avatar_url)
- SELECT $4, $5, $6, $7, $8
- WHERE NOT EXISTS (SELECT 1 FROM existing_contact)
- RETURNING id
-)
-
--- Determine which contact ID to use
-, final_contact AS (
- SELECT contact_id AS id FROM existing_contact
- UNION ALL
- SELECT id FROM ins_contact
- LIMIT 1
-)
-
--- Insert contact method if it does not exist
-, ins_contact_method AS (
- INSERT INTO public.contact_methods (contact_id, source, source_id, inbox_id)
- SELECT id, $1, $2, $3
- FROM final_contact
- ON CONFLICT DO NOTHING
-)
-
--- Return the final contact ID
-SELECT id AS contact_id FROM final_contact;
-
diff --git a/internal/conversation/conversation.go b/internal/conversation/conversation.go
index b6ece194..d8f7493f 100644
--- a/internal/conversation/conversation.go
+++ b/internal/conversation/conversation.go
@@ -1,4 +1,4 @@
-// Package conversation provides functionality to manage conversations in the system.
+// Package conversation manages conversations and messages.
package conversation
import (
@@ -9,47 +9,60 @@ import (
"errors"
"fmt"
"io"
+ "slices"
+ "strconv"
+ "strings"
"sync"
"time"
- "github.com/abhinavxd/artemis/internal/automation"
- cmodels "github.com/abhinavxd/artemis/internal/contact/models"
- "github.com/abhinavxd/artemis/internal/conversation/models"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/abhinavxd/artemis/internal/inbox"
- mmodels "github.com/abhinavxd/artemis/internal/media/models"
- notifier "github.com/abhinavxd/artemis/internal/notification"
- "github.com/abhinavxd/artemis/internal/stringutil"
- tmodels "github.com/abhinavxd/artemis/internal/team/models"
- "github.com/abhinavxd/artemis/internal/template"
- umodels "github.com/abhinavxd/artemis/internal/user/models"
- "github.com/abhinavxd/artemis/internal/ws"
+ "github.com/abhinavxd/libredesk/internal/automation"
+ amodels "github.com/abhinavxd/libredesk/internal/automation/models"
+ "github.com/abhinavxd/libredesk/internal/conversation/models"
+ pmodels "github.com/abhinavxd/libredesk/internal/conversation/priority/models"
+ smodels "github.com/abhinavxd/libredesk/internal/conversation/status/models"
+ csatModels "github.com/abhinavxd/libredesk/internal/csat/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/inbox"
+ mmodels "github.com/abhinavxd/libredesk/internal/media/models"
+ notifier "github.com/abhinavxd/libredesk/internal/notification"
+ slaModels "github.com/abhinavxd/libredesk/internal/sla/models"
+ tmodels "github.com/abhinavxd/libredesk/internal/team/models"
+ "github.com/abhinavxd/libredesk/internal/template"
+ umodels "github.com/abhinavxd/libredesk/internal/user/models"
+ "github.com/abhinavxd/libredesk/internal/ws"
"github.com/jmoiron/sqlx"
"github.com/knadh/go-i18n"
"github.com/lib/pq"
+ "github.com/volatiletech/null/v9"
"github.com/zerodha/logf"
)
var (
//go:embed queries.sql
- efs embed.FS
- ErrConversationNotFound = errors.New("conversation not found")
- ConversationsListAllowedFilters = []string{"status_id", "priority_id", "reference_number"}
+ efs embed.FS
+ errConversationNotFound = errors.New("conversation not found")
+ conversationsListAllowedFilterFields = []string{"status_id", "priority_id", "assigned_team_id", "assigned_user_id", "inbox_id"}
+ conversationStatusesFilterFields = []string{"id", "name"}
+ csatReplyMessage = "Please rate your experience with us:
Rate now"
)
const (
- conversationsListMaxPageSize = 50
+ conversationsListMaxPageSize = 100
)
// Manager handles the operations related to conversations
type Manager struct {
q queries
- contactStore contactStore
inboxStore inboxStore
userStore userStore
teamStore teamStore
mediaStore mediaStore
+ statusStore statusStore
+ priorityStore priorityStore
+ slaStore slaStore
+ settingsStore settingsStore
+ csatStore csatStore
notifier *notifier.Service
lo *logf.Logger
db *sqlx.DB
@@ -65,16 +78,27 @@ type Manager struct {
wg sync.WaitGroup
}
+type slaStore interface {
+ ApplySLA(startTime time.Time, conversationID, assignedTeamID, slaID int) (slaModels.SLAPolicy, error)
+}
+
+type statusStore interface {
+ Get(int) (smodels.Status, error)
+}
+
+type priorityStore interface {
+ Get(int) (pmodels.Priority, error)
+}
+
type teamStore interface {
- GetTeam(int) (tmodels.Team, error)
+ Get(int) (tmodels.Team, error)
+ UserBelongsToTeam(userID, teamID int) (bool, error)
}
type userStore interface {
Get(int) (umodels.User, error)
-}
-
-type contactStore interface {
- Upsert(cmodels.Contact) (int, error)
+ GetSystemUser() (umodels.User, error)
+ CreateContact(user *umodels.User) error
}
type mediaStore interface {
@@ -82,13 +106,23 @@ type mediaStore interface {
Attach(id int, model string, modelID int) error
GetByModel(id int, model string) ([]mmodels.Media, error)
ContentIDExists(contentID string) (bool, error)
- UploadAndInsert(fileName, contentType, contentID, modelType string, modelID int, content io.ReadSeeker, fileSize int, disposition string, meta []byte) (mmodels.Media, error)
+ Upload(fileName, contentType string, content io.ReadSeeker) (string, error)
+ UploadAndInsert(fileName, contentType, contentID string, modelType null.String, modelID null.Int, content io.ReadSeeker, fileSize int, disposition null.String, meta []byte) (mmodels.Media, error)
}
type inboxStore interface {
Get(int) (inbox.Inbox, error)
}
+type settingsStore interface {
+ GetAppRootURL() (string, error)
+}
+
+type csatStore interface {
+ Create(conversationID int) (csatModels.CSATResponse, error)
+ MakePublicURL(appBaseURL, uuid string) string
+}
+
// Opts holds the options for creating a new Manager.
type Opts struct {
DB *sqlx.DB
@@ -102,11 +136,15 @@ func New(
wsHub *ws.Hub,
i18n *i18n.I18n,
notifier *notifier.Service,
- contactStore contactStore,
+ slaStore slaStore,
+ statusStore statusStore,
+ priorityStore priorityStore,
inboxStore inboxStore,
userStore userStore,
teamStore teamStore,
mediaStore mediaStore,
+ settingsStore settingsStore,
+ csatStore csatStore,
automation *automation.Engine,
template *template.Manager,
opts Opts) (*Manager, error) {
@@ -121,11 +159,15 @@ func New(
wsHub: wsHub,
i18n: i18n,
notifier: notifier,
- contactStore: contactStore,
inboxStore: inboxStore,
userStore: userStore,
teamStore: teamStore,
mediaStore: mediaStore,
+ settingsStore: settingsStore,
+ csatStore: csatStore,
+ slaStore: slaStore,
+ statusStore: statusStore,
+ priorityStore: priorityStore,
automation: automation,
template: template,
db: opts.DB,
@@ -142,25 +184,29 @@ type queries struct {
// Conversation queries.
GetLatestReceivedMessageSourceID *sqlx.Stmt `query:"get-latest-received-message-source-id"`
GetToAddress *sqlx.Stmt `query:"get-to-address"`
- GetConversationID *sqlx.Stmt `query:"get-conversation-id"`
GetConversationUUID *sqlx.Stmt `query:"get-conversation-uuid"`
GetConversation *sqlx.Stmt `query:"get-conversation"`
GetConversationsCreatedAfter *sqlx.Stmt `query:"get-conversations-created-after"`
GetUnassignedConversations *sqlx.Stmt `query:"get-unassigned-conversations"`
GetConversations string `query:"get-conversations"`
- GetConversationsListUUIDs string `query:"get-conversations-list-uuids"`
+ GetContactConversations *sqlx.Stmt `query:"get-contact-conversations"`
GetConversationParticipants *sqlx.Stmt `query:"get-conversation-participants"`
+ GetUserActiveConversationsCount *sqlx.Stmt `query:"get-user-active-conversations-count"`
UpdateConversationFirstReplyAt *sqlx.Stmt `query:"update-conversation-first-reply-at"`
UpdateConversationAssigneeLastSeen *sqlx.Stmt `query:"update-conversation-assignee-last-seen"`
UpdateConversationAssignedUser *sqlx.Stmt `query:"update-conversation-assigned-user"`
UpdateConversationAssignedTeam *sqlx.Stmt `query:"update-conversation-assigned-team"`
+ RemoveConversationAssignee *sqlx.Stmt `query:"remove-conversation-assignee"`
UpdateConversationPriority *sqlx.Stmt `query:"update-conversation-priority"`
UpdateConversationStatus *sqlx.Stmt `query:"update-conversation-status"`
- UpdateConversationMeta *sqlx.Stmt `query:"update-conversation-meta"`
- InsertConverstionParticipant *sqlx.Stmt `query:"insert-conversation-participant"`
+ UpdateConversationLastMessage *sqlx.Stmt `query:"update-conversation-last-message"`
+ InsertConversationParticipant *sqlx.Stmt `query:"insert-conversation-participant"`
InsertConversation *sqlx.Stmt `query:"insert-conversation"`
UpsertConversationTags *sqlx.Stmt `query:"upsert-conversation-tags"`
+ GetConversationTags *sqlx.Stmt `query:"get-conversation-tags"`
UnassignOpenConversations *sqlx.Stmt `query:"unassign-open-conversations"`
+ ReOpenConversation *sqlx.Stmt `query:"re-open-conversation"`
+ UnsnoozeAll *sqlx.Stmt `query:"unsnooze-all"`
// Dashboard queries.
GetDashboardCharts string `query:"get-dashboard-charts"`
@@ -178,13 +224,13 @@ type queries struct {
}
// CreateConversation creates a new conversation and returns its ID and UUID.
-func (c *Manager) CreateConversation(contactID int, inboxID int, meta []byte) (int, string, error) {
+func (c *Manager) CreateConversation(contactID, contactChannelID, inboxID int, lastMessage string, lastMessageAt time.Time, subject string) (int, string, error) {
var (
- id int
- uuid string
- refNum, _ = stringutil.RandomNumericString(20)
+ id int
+ uuid string
+ prefix string
)
- if err := c.q.InsertConversation.QueryRow(refNum, contactID, models.StatusOpen, inboxID, meta).Scan(&id, &uuid); err != nil {
+ if err := c.q.InsertConversation.QueryRow(contactID, contactChannelID, models.StatusOpen, inboxID, lastMessage, lastMessageAt, subject, prefix).Scan(&id, &uuid); err != nil {
c.lo.Error("error inserting new conversation into the DB", "error", err)
return id, uuid, err
}
@@ -192,26 +238,32 @@ func (c *Manager) CreateConversation(contactID int, inboxID int, meta []byte) (i
}
// GetConversation retrieves a conversation by its UUID.
-func (c *Manager) GetConversation(uuid string) (models.Conversation, error) {
+func (c *Manager) GetConversation(id int, uuid string) (models.Conversation, error) {
var conversation models.Conversation
- if err := c.q.GetConversation.Get(&conversation, uuid); err != nil {
+ if err := c.q.GetConversation.Get(&conversation, id, uuid); err != nil {
if err == sql.ErrNoRows {
- return conversation, envelope.NewError(envelope.InputError, "Conversation not found.", nil)
+ return conversation, envelope.NewError(envelope.InputError, "Conversation not found", nil)
}
c.lo.Error("error fetching conversation", "error", err)
- return conversation, envelope.NewError(envelope.InputError, "Error fetching conversation.", nil)
+ return conversation, envelope.NewError(envelope.GeneralError, "Error fetching conversation", nil)
}
return conversation, nil
}
+// GetContactConversations retrieves conversations for a contact.
+func (c *Manager) GetContactConversations(contactID int) ([]models.Conversation, error) {
+ var conversations = make([]models.Conversation, 0)
+ if err := c.q.GetContactConversations.Select(&conversations, contactID); err != nil {
+ c.lo.Error("error fetching conversations", "error", err)
+ return conversations, envelope.NewError(envelope.GeneralError, "Error fetching conversations", nil)
+ }
+ return conversations, nil
+}
+
// GetConversationsCreatedAfter retrieves conversations created after the specified time.
func (c *Manager) GetConversationsCreatedAfter(time time.Time) ([]models.Conversation, error) {
var conversations = make([]models.Conversation, 0)
if err := c.q.GetConversationsCreatedAfter.Select(&conversations, time); err != nil {
- if err == sql.ErrNoRows {
- c.lo.Error("conversations not found", "created_after", time)
- return conversations, err
- }
c.lo.Error("error fetching conversation", "error", err)
return conversations, err
}
@@ -222,11 +274,11 @@ func (c *Manager) GetConversationsCreatedAfter(time time.Time) ([]models.Convers
func (c *Manager) UpdateConversationAssigneeLastSeen(uuid string) error {
if _, err := c.q.UpdateConversationAssigneeLastSeen.Exec(uuid); err != nil {
c.lo.Error("error updating conversation", "error", err)
- return envelope.NewError(envelope.GeneralError, "Error updating assignee last seen.", nil)
+ return envelope.NewError(envelope.GeneralError, "Error updating assignee last seen", nil)
}
// Broadcast the property update to all subscribers.
- c.BroadcastConversationPropertyUpdate(uuid, "assignee_last_seen_at", time.Now().Format(time.RFC3339))
+ c.BroadcastConversationUpdate(uuid, "assignee_last_seen_at", time.Now().Format(time.RFC3339))
return nil
}
@@ -240,17 +292,6 @@ func (c *Manager) GetConversationParticipants(uuid string) ([]models.Conversatio
return conv, nil
}
-// AddConversationParticipant adds a user as participant to a conversation.
-func (c *Manager) AddConversationParticipant(userID int, conversationUUID string) error {
- if _, err := c.q.InsertConverstionParticipant.Exec(userID, conversationUUID); err != nil {
- if pgErr, ok := err.(*pq.Error); ok && pgErr.Code == "23505" {
- return nil
- }
- return err
- }
- return nil
-}
-
// GetUnassignedConversations retrieves unassigned conversations.
func (c *Manager) GetUnassignedConversations() ([]models.Conversation, error) {
var conv []models.Conversation
@@ -263,19 +304,6 @@ func (c *Manager) GetUnassignedConversations() ([]models.Conversation, error) {
return conv, nil
}
-// GetConversationID retrieves the ID of a conversation by its UUID.
-func (c *Manager) GetConversationID(uuid string) (int, error) {
- var id int
- if err := c.q.GetConversationID.QueryRow(uuid).Scan(&id); err != nil {
- if err == sql.ErrNoRows {
- return id, err
- }
- c.lo.Error("fetching conversation from DB", "error", err)
- return id, err
- }
- return id, nil
-}
-
// GetConversationUUID retrieves the UUID of a conversation by its ID.
func (c *Manager) GetConversationUUID(id int) (string, error) {
var uuid string
@@ -290,90 +318,93 @@ func (c *Manager) GetConversationUUID(id int) (string, error) {
}
// GetAllConversationsList retrieves all conversations with optional filtering, ordering, and pagination.
-func (c *Manager) GetAllConversationsList(order, orderBy, filters string, page, pageSize int) ([]models.Conversation, int, error) {
- return c.GetConversations(0, models.AllConversations, order, orderBy, filters, page, pageSize)
+func (c *Manager) GetAllConversationsList(order, orderBy, filters string, page, pageSize int) ([]models.Conversation, error) {
+ return c.GetConversations(0, []int{}, []string{models.AllConversations}, order, orderBy, filters, page, pageSize)
}
// GetAssignedConversationsList retrieves conversations assigned to a specific user with optional filtering, ordering, and pagination.
-func (c *Manager) GetAssignedConversationsList(userID int, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, int, error) {
- return c.GetConversations(userID, models.AssignedConversations, order, orderBy, filters, page, pageSize)
+func (c *Manager) GetAssignedConversationsList(userID int, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, error) {
+ return c.GetConversations(userID, []int{}, []string{models.AssignedConversations}, order, orderBy, filters, page, pageSize)
}
// GetUnassignedConversationsList retrieves conversations assigned to a team the user is part of with optional filtering, ordering, and pagination.
-func (c *Manager) GetUnassignedConversationsList(userID int, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, int, error) {
- return c.GetConversations(userID, models.UnassignedConversations, order, orderBy, filters, page, pageSize)
+func (c *Manager) GetUnassignedConversationsList(order, orderBy, filters string, page, pageSize int) ([]models.Conversation, error) {
+ return c.GetConversations(0, []int{}, []string{models.UnassignedConversations}, order, orderBy, filters, page, pageSize)
+}
+
+// GetTeamUnassignedConversationsList retrieves conversations assigned to a team with optional filtering, ordering, and pagination.
+func (c *Manager) GetTeamUnassignedConversationsList(teamID int, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, error) {
+ return c.GetConversations(0, []int{teamID}, []string{models.TeamUnassignedConversations}, order, orderBy, filters, page, pageSize)
+}
+
+func (c *Manager) GetViewConversationsList(userID int, teamIDs []int, listType []string, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, error) {
+ return c.GetConversations(userID, teamIDs, listType, order, orderBy, filters, page, pageSize)
}
// GetConversations retrieves conversations list based on user ID, type, and optional filtering, ordering, and pagination.
-func (c *Manager) GetConversations(userID int, listType, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, int, error) {
+func (c *Manager) GetConversations(userID int, teamIDs []int, listTypes []string, order, orderBy, filters string, page, pageSize int) ([]models.Conversation, error) {
var conversations = make([]models.Conversation, 0)
- if orderBy == "" {
- orderBy = "last_message_at"
- }
- query, pageSize, qArgs, err := c.makeConversationsListQuery(userID, c.q.GetConversations, listType, order, orderBy, page, pageSize, filters)
+ // Make the query.
+ query, qArgs, err := c.makeConversationsListQuery(userID, teamIDs, listTypes, c.q.GetConversations, order, orderBy, page, pageSize, filters)
if err != nil {
- return conversations, pageSize, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
+ c.lo.Error("error making conversations query", "error", err)
+ return conversations, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
}
tx, err := c.db.BeginTxx(context.Background(), nil)
defer tx.Rollback()
if err != nil {
c.lo.Error("error preparing get conversations query", "error", err)
- return conversations, pageSize, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
+ return conversations, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
}
if err := tx.Select(&conversations, query, qArgs...); err != nil {
c.lo.Error("error fetching conversations", "error", err)
- return conversations, pageSize, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
+ return conversations, envelope.NewError(envelope.GeneralError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.entities.conversations}"), nil)
}
- return conversations, pageSize, nil
+ return conversations, nil
}
-// GetConversationsListUUIDs retrieves the UUIDs of conversations list.
-func (c *Manager) GetConversationsListUUIDs(userID, page, pageSize int, typ string) ([]string, error) {
- var ids = make([]string, 0)
-
- query, _, qArgs, err := c.makeConversationsListQuery(userID, c.q.GetConversationsListUUIDs, typ, "", "", page, pageSize, "")
+// ReOpenConversation reopens a conversation if it's snoozed, resolved or closed.
+func (c *Manager) ReOpenConversation(conversationUUID string, actor umodels.User) error {
+ rows, err := c.q.ReOpenConversation.Exec(conversationUUID)
if err != nil {
- c.lo.Error("error generating conversations query", "error", err)
- return ids, err
+ c.lo.Error("error reopening conversation", "uuid", conversationUUID, "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error reopening conversation", nil)
}
- tx, err := c.db.BeginTxx(context.Background(), nil)
- defer tx.Rollback()
- if err != nil {
- c.lo.Error("error preparing get conversation ids query", "error", err)
- return ids, err
- }
+ // Record the status change as an activity if the conversation was reopened.
+ count, _ := rows.RowsAffected()
+ if count > 0 {
+ // Broadcast update using WS
+ c.BroadcastConversationUpdate(conversationUUID, "status", models.StatusOpen)
- if err := tx.Select(&ids, query, qArgs...); err != nil {
- c.lo.Error("error fetching conversation uuids", "error", err)
- return ids, err
- }
- return ids, nil
-}
-
-// UpdateConversationMeta updates the metadata of a conversation.
-func (c *Manager) UpdateConversationMeta(conversationID int, conversationUUID string, meta map[string]string) error {
- metaJSON, err := json.Marshal(meta)
- if err != nil {
- c.lo.Error("error marshalling conversation meta", "meta", meta, "error", err)
- return err
- }
- if _, err := c.q.UpdateConversationMeta.Exec(conversationID, conversationUUID, metaJSON); err != nil {
- c.lo.Error("error updating conversation meta", "error", "error")
- return err
+ // Record the status change as an activity.
+ if err := c.RecordStatusChange(models.StatusOpen, conversationUUID, actor); err != nil {
+ return err
+ }
}
return nil
}
-// UpdateConversationLastMessage updates the last message details in the conversation meta.
-func (c *Manager) UpdateConversationLastMessage(conversationID int, conversationUUID, lastMessage string, lastMessageAt time.Time) error {
- return c.UpdateConversationMeta(conversationID, conversationUUID, map[string]string{
- "last_message": lastMessage,
- "last_message_at": lastMessageAt.Format(time.RFC3339),
- })
+// ActiveUserConversationsCount returns the count of active conversations for a user. i.e. conversations not closed or resolved status.
+func (c *Manager) ActiveUserConversationsCount(userID int) (int, error) {
+ var count int
+ if err := c.q.GetUserActiveConversationsCount.Get(&count, userID); err != nil {
+ c.lo.Error("error fetching active conversation count", "error", err)
+ return count, envelope.NewError(envelope.GeneralError, "Error fetching active conversation count", nil)
+ }
+ return count, nil
+}
+
+// UpdateConversationLastMessage updates the last message details for a conversation.
+func (c *Manager) UpdateConversationLastMessage(convesationID int, conversationUUID, lastMessage string, lastMessageAt time.Time) error {
+ if _, err := c.q.UpdateConversationLastMessage.Exec(convesationID, conversationUUID, lastMessage, lastMessageAt); err != nil {
+ c.lo.Error("error updating conversation last message", "error", err)
+ return err
+ }
+ return nil
}
// UpdateConversationFirstReplyAt updates the first reply timestamp for a conversation.
@@ -386,7 +417,7 @@ func (c *Manager) UpdateConversationFirstReplyAt(conversationUUID string, conver
rows, _ := res.RowsAffected()
if rows > 0 {
- c.BroadcastConversationPropertyUpdate(conversationUUID, "first_reply_at", at.Format(time.RFC3339))
+ c.BroadcastConversationUpdate(conversationUUID, "first_reply_at", at.Format(time.RFC3339))
}
return nil
}
@@ -397,13 +428,13 @@ func (c *Manager) UpdateConversationUserAssignee(uuid string, assigneeID int, ac
return envelope.NewError(envelope.GeneralError, "Error updating assignee", nil)
}
- conversation, err := c.GetConversation(uuid)
+ conversation, err := c.GetConversation(0, uuid)
if err != nil {
return err
}
// Send email to assignee.
- if err := c.SendAssignedConversationEmail([]int{assigneeID}, conversation.Subject, uuid); err != nil {
+ if err := c.SendAssignedConversationEmail([]int{assigneeID}, conversation); err != nil {
c.lo.Error("error sending assigned conversation email", "error", err)
}
@@ -426,57 +457,93 @@ func (c *Manager) UpdateConversationTeamAssignee(uuid string, teamID int, actor
// UpdateAssignee updates the assignee of a conversation.
func (c *Manager) UpdateAssignee(uuid string, assigneeID int, assigneeType string) error {
+ var prop string
switch assigneeType {
case models.AssigneeTypeUser:
+ prop = "assigned_user_id"
if _, err := c.q.UpdateConversationAssignedUser.Exec(uuid, assigneeID); err != nil {
c.lo.Error("error updating conversation assignee", "error", err)
- return fmt.Errorf("error updating assignee")
+ return fmt.Errorf("updating assignee: %w", err)
}
-
- // Broadcast update to all subscribers.
- c.BroadcastConversationPropertyUpdate(uuid, "assigned_user_id", assigneeID)
case models.AssigneeTypeTeam:
+ prop = "assigned_team_id"
if _, err := c.q.UpdateConversationAssignedTeam.Exec(uuid, assigneeID); err != nil {
c.lo.Error("error updating conversation assignee", "error", err)
- return fmt.Errorf("error updating assignee")
+ return fmt.Errorf("updating assignee: %w", err)
}
-
- // Broadcast update to all subscribers.
- c.BroadcastConversationPropertyUpdate(uuid, "assigned_team_id", assigneeID)
default:
- return errors.New("invalid assignee type")
+ return fmt.Errorf("invalid assignee type: %s", assigneeType)
}
+ // Broadcast update to all subscribers.
+ c.BroadcastConversationUpdate(uuid, prop, assigneeID)
return nil
}
// UpdateConversationPriority updates the priority of a conversation.
-func (c *Manager) UpdateConversationPriority(uuid string, priority []byte, actor umodels.User) error {
- var priorityStr = string(priority)
+func (c *Manager) UpdateConversationPriority(uuid string, priorityID int, priority string, actor umodels.User) error {
+ // Fetch the priority name if priority ID is provided.
+ if priorityID > 0 {
+ p, err := c.priorityStore.Get(priorityID)
+ if err != nil {
+ return envelope.NewError(envelope.InputError, err.Error(), nil)
+ }
+ priority = p.Name
+ }
if _, err := c.q.UpdateConversationPriority.Exec(uuid, priority); err != nil {
c.lo.Error("error updating conversation priority", "error", err)
return envelope.NewError(envelope.GeneralError, "Error updating priority", nil)
}
- if err := c.RecordPriorityChange(priorityStr, uuid, actor); err != nil {
+ if err := c.RecordPriorityChange(priority, uuid, actor); err != nil {
return envelope.NewError(envelope.GeneralError, "Error recording priority change", nil)
}
+ c.BroadcastConversationUpdate(uuid, "priority", priority)
return nil
}
// UpdateConversationStatus updates the status of a conversation.
-func (c *Manager) UpdateConversationStatus(uuid string, status []byte, actor umodels.User) error {
- var statusStr = string(status)
- if _, err := c.q.UpdateConversationStatus.Exec(uuid, status); err != nil {
+func (c *Manager) UpdateConversationStatus(uuid string, statusID int, status, snoozeDur string, actor umodels.User) error {
+ // Fetch the status name if status ID is provided.
+ if statusID > 0 {
+ s, err := c.statusStore.Get(statusID)
+ if err != nil {
+ return envelope.NewError(envelope.InputError, err.Error(), nil)
+ }
+ status = s.Name
+ }
+
+ if status == models.StatusSnoozed && snoozeDur == "" {
+ return envelope.NewError(envelope.InputError, "Snooze duration is required", nil)
+ }
+
+ // Parse the snooze duration if status is snoozed.
+ snoozeUntil := time.Time{}
+ if status == models.StatusSnoozed {
+ duration, err := time.ParseDuration(snoozeDur)
+ if err != nil {
+ c.lo.Error("error parsing snooze duration", "error", err)
+ return envelope.NewError(envelope.InputError, "Invalid snooze duration format", nil)
+ }
+ snoozeUntil = time.Now().Add(duration)
+ }
+
+ // Update the conversation status.
+ if _, err := c.q.UpdateConversationStatus.Exec(uuid, status, snoozeUntil); err != nil {
c.lo.Error("error updating conversation status", "error", err)
return envelope.NewError(envelope.GeneralError, "Error updating status", nil)
}
- if err := c.RecordStatusChange(statusStr, uuid, actor); err != nil {
+
+ // Record the status change as an activity.
+ if err := c.RecordStatusChange(status, uuid, actor); err != nil {
return envelope.NewError(envelope.GeneralError, "Error recording status change", nil)
}
- c.BroadcastConversationPropertyUpdate(uuid, "status", string(status))
+
+ // Broadcast update using WS
+ c.BroadcastConversationUpdate(uuid, "status", status)
return nil
}
// GetDashboardCounts returns dashboard counts
+// TODO: Rename to overview [reports/overview].
func (c *Manager) GetDashboardCounts(userID, teamID int) (json.RawMessage, error) {
var counts = json.RawMessage{}
tx, err := c.db.BeginTxx(context.Background(), nil)
@@ -497,6 +564,7 @@ func (c *Manager) GetDashboardCounts(userID, teamID int) (json.RawMessage, error
cond = " AND assigned_team_id = $1"
qArgs = append(qArgs, teamID)
}
+ // TODO: Add date range filter support.
cond += " AND c.created_at >= NOW() - INTERVAL '30 days'"
query := fmt.Sprintf(c.q.GetDashboardCounts, cond)
@@ -528,7 +596,7 @@ func (c *Manager) GetDashboardChart(userID, teamID int) (json.RawMessage, error)
qArgs []interface{}
)
- // TODO: Add date range filter on the UI.
+ // TODO: Add date range filter support.
if userID > 0 {
cond = " AND assigned_user_id = $1"
qArgs = append(qArgs, userID)
@@ -536,10 +604,10 @@ func (c *Manager) GetDashboardChart(userID, teamID int) (json.RawMessage, error)
cond = " AND assigned_team_id = $1"
qArgs = append(qArgs, teamID)
}
- cond += " AND c.created_at >= NOW() - INTERVAL '30 days'"
+ cond += " AND c.created_at >= NOW() - INTERVAL '90 days'"
// Apply the same condition across queries.
- query := fmt.Sprintf(c.q.GetDashboardCharts, cond, cond)
+ query := fmt.Sprintf(c.q.GetDashboardCharts, cond, cond, cond, cond)
if err := tx.Get(&stats, query, qArgs...); err != nil {
c.lo.Error("error fetching dashboard charts", "error", err)
return nil, envelope.NewError(envelope.GeneralError, "Error fetching dashboard charts", nil)
@@ -548,67 +616,122 @@ func (c *Manager) GetDashboardChart(userID, teamID int) (json.RawMessage, error)
}
// UpsertConversationTags upserts the tags associated with a conversation.
-func (t *Manager) UpsertConversationTags(uuid string, tagIDs []int) error {
- if _, err := t.q.UpsertConversationTags.Exec(uuid, pq.Array(tagIDs)); err != nil {
+func (t *Manager) UpsertConversationTags(uuid string, tagNames []string, actor umodels.User) error {
+ // Get the existing tags.
+ tags, err := t.getConversationTags(uuid)
+ if err != nil {
+ return envelope.NewError(envelope.GeneralError, "Error fetching tags", nil)
+ }
+
+ // Upsert the tags.
+ if _, err := t.q.UpsertConversationTags.Exec(uuid, pq.Array(tagNames)); err != nil {
t.lo.Error("error upserting conversation tags", "error", err)
return envelope.NewError(envelope.GeneralError, "Error upserting tags", nil)
}
+
+ // Find the newly added tags.
+ newTags := []string{}
+ for _, tag := range tagNames {
+ if slices.Contains(tags, tag) {
+ continue
+ }
+ newTags = append(newTags, tag)
+ }
+
+ // Record the new tags as activities.
+ for _, tag := range newTags {
+ if err := t.RecordTagChange(uuid, tag, actor); err != nil {
+ return envelope.NewError(envelope.GeneralError, "Error recording tag change", nil)
+ }
+ }
+
return nil
}
+// getConversationTags retrieves the tags associated with a conversation.
+func (t *Manager) getConversationTags(uuid string) ([]string, error) {
+ var tags []string
+ if err := t.q.GetConversationTags.Select(&tags, uuid); err != nil {
+ t.lo.Error("error fetching conversation tags", "error", err)
+ return tags, envelope.NewError(envelope.GeneralError, "Error fetching tags", nil)
+ }
+ return tags, nil
+}
+
// makeConversationsListQuery prepares a SQL query string for conversations list
-func (c *Manager) makeConversationsListQuery(userID int, baseQuery, listType, order, orderBy string, page, pageSize int, filtersJSON string) (string, int, []interface{}, error) {
+func (c *Manager) makeConversationsListQuery(userID int, teamIDs []int, listTypes []string, baseQuery, order, orderBy string, page, pageSize int, filtersJSON string) (string, []interface{}, error) {
var qArgs []interface{}
+
+ // Set defaults
+ if orderBy == "" {
+ orderBy = "last_message_at"
+ }
if order == "" {
order = "DESC"
}
if filtersJSON == "" {
filtersJSON = "[]"
}
- if pageSize > conversationsListMaxPageSize {
- pageSize = conversationsListMaxPageSize
- }
- if pageSize < 1 {
- pageSize = 10
+
+ // Validate inputs
+ if pageSize > conversationsListMaxPageSize || pageSize < 1 {
+ return "", nil, fmt.Errorf("invalid page size: must be between 1 and %d", conversationsListMaxPageSize)
}
if page < 1 {
- page = 1
+ return "", nil, fmt.Errorf("page must be greater than 0")
}
- // Set condition based on the list type.
- switch listType {
- case models.AssignedConversations:
- baseQuery = fmt.Sprintf(baseQuery, "AND conversations.assigned_user_id = $1")
- qArgs = append(qArgs, userID)
- case models.UnassignedConversations:
- baseQuery = fmt.Sprintf(baseQuery, "AND conversations.assigned_user_id IS NULL AND conversations.assigned_team_id IN (SELECT team_id FROM team_members WHERE user_id = $1)")
- qArgs = append(qArgs, userID)
- case models.AllConversations:
+ if len(listTypes) == 0 {
+ return "", nil, fmt.Errorf("no conversation list types specified")
+ }
+
+ // Prepare the conditions based on the list types.
+ conditions := []string{}
+ for _, lt := range listTypes {
+ switch lt {
+ case models.AssignedConversations:
+ conditions = append(conditions, fmt.Sprintf("conversations.assigned_user_id = $%d", len(qArgs)+1))
+ qArgs = append(qArgs, userID)
+ case models.UnassignedConversations:
+ conditions = append(conditions, "conversations.assigned_user_id IS NULL AND conversations.assigned_team_id IS NULL")
+ case models.TeamUnassignedConversations:
+ placeholders := make([]string, len(teamIDs))
+ for i := range teamIDs {
+ placeholders[i] = fmt.Sprintf("$%d", len(qArgs)+i+1)
+ }
+ conditions = append(conditions, fmt.Sprintf("(conversations.assigned_team_id IN (%s) AND conversations.assigned_user_id IS NULL)", strings.Join(placeholders, ",")))
+ for _, id := range teamIDs {
+ qArgs = append(qArgs, id)
+ }
+ case models.AllConversations:
+ // No conditions needed for all conversations.
+ default:
+ return "", nil, fmt.Errorf("unknown conversation type: %s", lt)
+ }
+ }
+
+ if len(conditions) > 0 {
+ baseQuery = fmt.Sprintf(baseQuery, "AND ("+strings.Join(conditions, " OR ")+")")
+ } else {
+ // Replace the `%s` in the base query with an empty string.
baseQuery = fmt.Sprintf(baseQuery, "")
- default:
- return "", pageSize, nil, fmt.Errorf("invalid conversation type %s", listType)
}
- query, qArgs, err := dbutil.PaginateAndFilterQuery(baseQuery, qArgs, dbutil.PaginationOptions{
+ return dbutil.BuildPaginatedQuery(baseQuery, qArgs, dbutil.PaginationOptions{
Order: order,
OrderBy: orderBy,
Page: page,
PageSize: pageSize,
}, filtersJSON, dbutil.AllowedFields{
- "conversations": ConversationsListAllowedFilters,
+ "conversations": conversationsListAllowedFilterFields,
+ "conversation_statuses": conversationStatusesFilterFields,
})
- if err != nil {
- c.lo.Error("error preparing query", "error", err)
- return "", pageSize, nil, err
- }
-
- return query, pageSize, qArgs, err
}
-// GetToAddress retrieves the recipient addresses for a conversation.
-func (m *Manager) GetToAddress(conversationID int, channel string) ([]string, error) {
+// GetToAddress retrieves the recipient addresses for a conversation and channel.
+func (m *Manager) GetToAddress(conversationID int) ([]string, error) {
var addr []string
- if err := m.q.GetToAddress.Select(&addr, conversationID, channel); err != nil {
+ if err := m.q.GetToAddress.Select(&addr, conversationID); err != nil {
m.lo.Error("error fetching `to` address for message", "error", err, "conversation_id", conversationID)
return addr, err
}
@@ -626,27 +749,38 @@ func (m *Manager) GetLatestReceivedMessageSourceID(conversationID int) (string,
}
// SendAssignedConversationEmail sends a email for an assigned conversation to the passed user ids.
-func (m *Manager) SendAssignedConversationEmail(userIDs []int, subject, conversationUUID string) error {
- content, err := m.template.Render(template.TmplConversationAssigned,
+func (m *Manager) SendAssignedConversationEmail(userIDs []int, conversation models.Conversation) error {
+ agent, err := m.userStore.Get(userIDs[0])
+ if err != nil {
+ m.lo.Error("error fetching agent", "user_id", userIDs[0], "error", err)
+ return fmt.Errorf("fetching agent: %w", err)
+ }
+
+ content, subject, err := m.template.RenderNamedTemplate(template.TmplConversationAssigned,
map[string]interface{}{
- "Conversation": map[string]string{
- "Subject": subject,
- "UUID": conversationUUID,
+ "conversation": map[string]string{
+ "subject": conversation.Subject.String,
+ "uuid": conversation.UUID,
+ "reference_number": conversation.ReferenceNumber,
+ "priority": conversation.Priority.String,
+ },
+ "agent": map[string]string{
+ "full_name": agent.FullName(),
},
})
if err != nil {
- m.lo.Error("error rendering template", "template", template.TmplConversationAssigned, "error", err)
- return err
+ m.lo.Error("error rendering template", "template", template.TmplConversationAssigned, "conversation_uuid", conversation.UUID, "error", err)
+ return fmt.Errorf("rendering template: %w", err)
}
nm := notifier.Message{
UserIDs: userIDs,
- Subject: "Conversation Assigned",
+ Subject: subject,
Content: content,
Provider: notifier.ProviderEmail,
}
if err := m.notifier.Send(nm); err != nil {
m.lo.Error("error sending notification message", "error", err)
- return err
+ return fmt.Errorf("sending notification message: %w", err)
}
return nil
}
@@ -660,3 +794,107 @@ func (m *Manager) UnassignOpen(userID int) error {
}
return nil
}
+
+// ApplySLA applies the SLA policy to a conversation.
+func (m *Manager) ApplySLA(conversation models.Conversation, policyID int, actor umodels.User) error {
+ policy, err := m.slaStore.ApplySLA(conversation.CreatedAt, conversation.ID, conversation.AssignedTeamID.Int, policyID)
+ if err != nil {
+ m.lo.Error("error applying SLA to conversation", "conversation_id", conversation.ID, "policy_id", policyID, "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error applying SLA", nil)
+ }
+
+ // Record the SLA application as an activity.
+ if err := m.RecordSLASet(conversation.UUID, policy.Name, actor); err != nil {
+ return err
+ }
+ return nil
+}
+
+// ApplyAction applies an action to a conversation, this can be called from multiple packages across the app to perform actions on conversations.
+// all actions are executed on behalf of the provided user if the user is not provided, system user is used.
+func (m *Manager) ApplyAction(action amodels.RuleAction, conv models.Conversation, user umodels.User) error {
+ // CSAT action does not require a value.
+ if len(action.Value) == 0 && action.Type != amodels.ActionSendCSAT {
+ return fmt.Errorf("empty value for action %s", action.Type)
+ }
+
+ // Fall back to system user if user is not provided.
+ if user.ID == 0 {
+ var err error
+ if user, err = m.userStore.GetSystemUser(); err != nil {
+ return fmt.Errorf("get system user: %w", err)
+ }
+ }
+
+ m.lo.Debug("executing action",
+ "type", action.Type,
+ "value", action.Value,
+ "conv_uuid", conv.UUID,
+ "user_id", user.ID,
+ )
+
+ switch action.Type {
+ case amodels.ActionAssignTeam:
+ teamID, _ := strconv.Atoi(action.Value[0])
+ return m.UpdateConversationTeamAssignee(conv.UUID, teamID, user)
+ case amodels.ActionAssignUser:
+ agentID, _ := strconv.Atoi(action.Value[0])
+ return m.UpdateConversationUserAssignee(conv.UUID, agentID, user)
+ case amodels.ActionSetPriority:
+ priorityID, _ := strconv.Atoi(action.Value[0])
+ return m.UpdateConversationPriority(conv.UUID, priorityID, "", user)
+ case amodels.ActionSetStatus:
+ statusID, _ := strconv.Atoi(action.Value[0])
+ return m.UpdateConversationStatus(conv.UUID, statusID, "", "", user)
+ case amodels.ActionSendPrivateNote:
+ return m.SendPrivateNote([]mmodels.Media{}, user.ID, conv.UUID, action.Value[0])
+ case amodels.ActionReply:
+ return m.SendReply([]mmodels.Media{}, user.ID, conv.UUID, action.Value[0], nil, nil, nil)
+ case amodels.ActionSetSLA:
+ slaID, _ := strconv.Atoi(action.Value[0])
+ return m.ApplySLA(conv, slaID, user)
+ case amodels.ActionSetTags:
+ return m.UpsertConversationTags(conv.UUID, action.Value, user)
+ case amodels.ActionSendCSAT:
+ return m.SendCSATReply(user.ID, conv)
+ default:
+ return fmt.Errorf("unknown action: %s", action.Type)
+ }
+}
+
+// RemoveConversationAssignee removes the assignee from the conversation.
+func (m *Manager) RemoveConversationAssignee(uuid, typ string) error {
+ if _, err := m.q.RemoveConversationAssignee.Exec(uuid, typ); err != nil {
+ m.lo.Error("error removing conversation assignee", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error removing conversation assignee", nil)
+ }
+ return nil
+}
+
+// SendCSATReply sends a CSAT reply message to a conversation.
+func (m *Manager) SendCSATReply(actorUserID int, conversation models.Conversation) error {
+ appRootURL, err := m.settingsStore.GetAppRootURL()
+ if err != nil {
+ return envelope.NewError(envelope.GeneralError, "Error fetching app root URL", nil)
+ }
+ csat, err := m.csatStore.Create(conversation.ID)
+ if err != nil {
+ return envelope.NewError(envelope.GeneralError, "Error creating CSAT", nil)
+ }
+ csatPublicURL := m.csatStore.MakePublicURL(appRootURL, csat.UUID)
+ message := fmt.Sprintf(csatReplyMessage, csatPublicURL)
+ // Store `is_csat` meta to identify and filter CSAT public url from the message.
+ meta := map[string]interface{}{
+ "is_csat": true,
+ }
+ return m.SendReply([]mmodels.Media{}, actorUserID, conversation.UUID, message, nil, nil, meta)
+}
+
+// addConversationParticipant adds a user as participant to a conversation.
+func (c *Manager) addConversationParticipant(userID int, conversationUUID string) error {
+ if _, err := c.q.InsertConversationParticipant.Exec(userID, conversationUUID); err != nil && !dbutil.IsUniqueViolationError(err) {
+ c.lo.Error("error adding conversation participant", "user_id", userID, "conversation_uuid", conversationUUID, "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error adding conversation participant", nil)
+ }
+ return nil
+}
diff --git a/internal/conversation/message.go b/internal/conversation/message.go
index 8eb78d89..6644fca8 100644
--- a/internal/conversation/message.go
+++ b/internal/conversation/message.go
@@ -7,17 +7,22 @@ import (
"encoding/json"
"errors"
"fmt"
+ "path/filepath"
+ "slices"
+ "strings"
"time"
- "github.com/abhinavxd/artemis/internal/attachment"
- amodels "github.com/abhinavxd/artemis/internal/automation/models"
- "github.com/abhinavxd/artemis/internal/conversation/models"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/abhinavxd/artemis/internal/inbox"
- mmodels "github.com/abhinavxd/artemis/internal/media/models"
- "github.com/abhinavxd/artemis/internal/stringutil"
- umodels "github.com/abhinavxd/artemis/internal/user/models"
+ "github.com/abhinavxd/libredesk/internal/attachment"
+ amodels "github.com/abhinavxd/libredesk/internal/automation/models"
+ "github.com/abhinavxd/libredesk/internal/conversation/models"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/image"
+ "github.com/abhinavxd/libredesk/internal/inbox"
+ mmodels "github.com/abhinavxd/libredesk/internal/media/models"
+ "github.com/abhinavxd/libredesk/internal/stringutil"
+ umodels "github.com/abhinavxd/libredesk/internal/user/models"
"github.com/lib/pq"
+ "github.com/volatiletech/null/v9"
)
const (
@@ -25,13 +30,13 @@ const (
MessageOutgoing = "outgoing"
MessageActivity = "activity"
- SenderTypeUser = "user"
+ SenderTypeAgent = "agent"
SenderTypeContact = "contact"
- MessageStatusPending = "pending"
- MessageStatusSent = "sent"
- MessageStatusFailed = "failed"
- MessageStatusReceived = "received"
+ MessageStatusPending = "pending"
+ MessageStatusSent = "sent"
+ MessageStatusFailed = "failed"
+ MessageStatusReceived = "received"
ActivityStatusChange = "status_change"
ActivityPriorityChange = "priority_change"
@@ -39,6 +44,7 @@ const (
ActivityAssignedTeamChange = "assigned_team_change"
ActivitySelfAssign = "self_assign"
ActivityTagChange = "tag_change"
+ ActivitySLASet = "sla_set"
ContentTypeText = "text"
ContentTypeHTML = "html"
@@ -49,25 +55,24 @@ const (
// Run starts a pool of worker goroutines to handle message dispatching via inbox's channel and processes incoming messages. It scans for
// pending outgoing messages at the specified read interval and pushes them to the outgoing queue.
-func (m *Manager) Run(ctx context.Context, dispatchConcurrency int, scanInterval time.Duration) {
+func (m *Manager) Run(ctx context.Context, incomingQWorkers, outgoingQWorkers, scanInterval time.Duration) {
dbScanner := time.NewTicker(scanInterval)
defer dbScanner.Stop()
- // Spawn a worker goroutine pool to dispatch messages.
- for range dispatchConcurrency {
+ for range outgoingQWorkers {
m.wg.Add(1)
go func() {
defer m.wg.Done()
- m.MessageDispatchWorker(ctx)
+ m.MessageSenderWorker(ctx)
+ }()
+ }
+ for range incomingQWorkers {
+ m.wg.Add(1)
+ go func() {
+ defer m.wg.Done()
+ m.IncomingMessageWorker(ctx)
}()
}
-
- // Spawn a goroutine to process incoming messages.
- m.wg.Add(1)
- go func() {
- defer m.wg.Done()
- m.IncomingMessageWorker(ctx)
- }()
// Scan pending outgoing messages and send them.
for {
@@ -126,8 +131,8 @@ func (m *Manager) IncomingMessageWorker(ctx context.Context) {
}
}
-// MessageDispatchWorker dispatches outgoing pending messages.
-func (m *Manager) MessageDispatchWorker(ctx context.Context) {
+// MessageSenderWorker sends outgoing pending messages.
+func (m *Manager) MessageSenderWorker(ctx context.Context) {
for {
select {
case <-ctx.Done():
@@ -136,19 +141,19 @@ func (m *Manager) MessageDispatchWorker(ctx context.Context) {
if !ok {
return
}
- m.processOutgoingMessage(message)
+ m.sendOutgoingMessage(message)
}
}
}
-// processOutgoingMessage handles the processing of a single outgoing message
-func (m *Manager) processOutgoingMessage(message models.Message) {
+// sendOutgoingMessage sends an outgoing message.
+func (m *Manager) sendOutgoingMessage(message models.Message) {
defer m.outgoingProcessingMessages.Delete(message.ID)
// Helper function to handle errors
handleError := func(err error, errorMsg string) bool {
if err != nil {
- m.lo.Error(errorMsg, "error", err, "id", message.ID)
+ m.lo.Error(errorMsg, "error", err, "message_id", message.ID)
m.UpdateMessageStatus(message.UUID, MessageStatusFailed)
return true
}
@@ -173,9 +178,9 @@ func (m *Manager) processOutgoingMessage(message models.Message) {
return
}
- // Set message properties
+ // Set message sender and receiver
message.From = inbox.FromAddress()
- message.To, _ = m.GetToAddress(message.ConversationID, inbox.Channel())
+ message.To, _ = m.GetToAddress(message.ConversationID)
message.InReplyTo, _ = m.GetLatestReceivedMessageSourceID(message.ConversationID)
// Send message
@@ -193,12 +198,12 @@ func (m *Manager) processOutgoingMessage(message models.Message) {
func (m *Manager) RenderContentInTemplate(channel string, message *models.Message) error {
switch channel {
case inbox.ChannelEmail:
- conversation, err := m.GetConversation(message.ConversationUUID)
+ conversation, err := m.GetConversation(0, message.ConversationUUID)
if err != nil {
m.lo.Error("error fetching conversation", "uuid", message.ConversationUUID, "error", err)
return fmt.Errorf("fetching conversation: %w", err)
}
- message.Content, err = m.template.RenderEmail(conversation, message.Content)
+ message.Content, err = m.template.RenderWithBaseTemplate(conversation, message.Content)
if err != nil {
m.lo.Error("could not render email content using template", "id", message.ID, "error", err)
return fmt.Errorf("could not render email content using template: %w", err)
@@ -258,7 +263,7 @@ func (m *Manager) UpdateMessageStatus(uuid string, status string) error {
// Broadcast messge status update to all conversation subscribers.
conversationUUID, _ := m.getConversationUUIDFromMessageUUID(uuid)
- m.BroadcastMessagePropUpdate(conversationUUID, uuid, "status" /*property*/, status)
+ m.BroadcastMessageUpdate(conversationUUID, uuid, "status" /*property*/, status)
return nil
}
@@ -277,7 +282,7 @@ func (m *Manager) SendPrivateNote(media []mmodels.Media, senderID int, conversat
ConversationUUID: conversationUUID,
SenderID: senderID,
Type: MessageOutgoing,
- SenderType: SenderTypeUser,
+ SenderType: SenderTypeAgent,
Status: MessageStatusSent,
Content: content,
ContentType: ContentTypeHTML,
@@ -288,18 +293,32 @@ func (m *Manager) SendPrivateNote(media []mmodels.Media, senderID int, conversat
}
// SendReply inserts a reply message in a conversation.
-func (m *Manager) SendReply(media []mmodels.Media, senderID int, conversationUUID, content string) error {
- // Insert Message.
+func (m *Manager) SendReply(media []mmodels.Media, senderID int, conversationUUID, content string, cc, bcc []string, meta map[string]interface{}) error {
+ cc = stringutil.RemoveEmpty(cc)
+ bcc = stringutil.RemoveEmpty(bcc)
+
+ // Save cc and bcc as JSON in meta.
+ if len(cc) > 0 {
+ meta["cc"] = cc
+ }
+ if len(bcc) > 0 {
+ meta["bcc"] = bcc
+ }
+ metaJSON, err := json.Marshal(meta)
+ if err != nil {
+ return envelope.NewError(envelope.GeneralError, "Error marshalling message meta", nil)
+ }
message := models.Message{
ConversationUUID: conversationUUID,
SenderID: senderID,
Type: MessageOutgoing,
- SenderType: SenderTypeUser,
+ SenderType: SenderTypeAgent,
Status: MessageStatusPending,
Content: content,
ContentType: ContentTypeHTML,
Private: false,
Media: media,
+ Meta: string(metaJSON),
}
return m.InsertMessage(&message)
}
@@ -311,12 +330,16 @@ func (m *Manager) InsertMessage(message *models.Message) error {
message.Status = MessageStatusSent
}
- if message.Meta == "" {
+ // Handle empty meta.
+ if message.Meta == "" || message.Meta == "null" {
message.Meta = "{}"
}
+ // Convert HTML content to text for search.
+ message.TextContent = stringutil.HTML2Text(message.Content)
+
// Insert Message.
- if err := m.q.InsertMessage.QueryRow(message.Type, message.Status, message.ConversationID, message.ConversationUUID, message.Content, message.SenderID, message.SenderType,
+ if err := m.q.InsertMessage.QueryRow(message.Type, message.Status, message.ConversationID, message.ConversationUUID, message.Content, message.TextContent, message.SenderID, message.SenderType,
message.Private, message.ContentType, message.SourceID, message.Meta).Scan(&message.ID, &message.UUID, &message.CreatedAt); err != nil {
m.lo.Error("error inserting message in db", "error", err)
return envelope.NewError(envelope.GeneralError, "Error sending message", nil)
@@ -328,22 +351,21 @@ func (m *Manager) InsertMessage(message *models.Message) error {
}
// Add this user as a participant.
- if err := m.AddConversationParticipant(message.SenderID, message.ConversationUUID); err != nil {
- return envelope.NewError(envelope.GeneralError, "Error sending message", nil)
+ if err := m.addConversationParticipant(message.SenderID, message.ConversationUUID); err != nil {
+ return err
}
- // Update conversation meta with the last message details.
- plainTextContent := stringutil.HTML2Text(message.Content)
- m.UpdateConversationLastMessage(0, message.ConversationUUID, plainTextContent, message.CreatedAt)
+ // Update conversation last message details in conversation metadata.
+ m.UpdateConversationLastMessage(message.ConversationID, message.ConversationUUID, message.TextContent, message.CreatedAt)
- // Broadcast new message to all conversation subscribers.
- m.BroadcastNewConversationMessage(message.ConversationUUID, plainTextContent, message.UUID, message.CreatedAt.Format(time.RFC3339), message.Type, message.Private)
+ // Broadcast new message.
+ m.BroadcastNewMessage(message.ConversationUUID, message.TextContent, message.UUID, message.CreatedAt.Format(time.RFC3339), message.Type, message.Private)
return nil
}
// RecordAssigneeUserChange records an activity for a user assignee change.
func (m *Manager) RecordAssigneeUserChange(conversationUUID string, assigneeID int, actor umodels.User) error {
- // Self assign.
+ // Self assignment.
if assigneeID == actor.ID {
return m.InsertConversationActivity(ActivitySelfAssign, conversationUUID, actor.FullName(), actor)
}
@@ -358,7 +380,7 @@ func (m *Manager) RecordAssigneeUserChange(conversationUUID string, assigneeID i
// RecordAssigneeTeamChange records an activity for a team assignee change.
func (m *Manager) RecordAssigneeTeamChange(conversationUUID string, teamID int, actor umodels.User) error {
- team, err := m.teamStore.GetTeam(teamID)
+ team, err := m.teamStore.Get(teamID)
if err != nil {
return err
}
@@ -375,6 +397,16 @@ func (m *Manager) RecordStatusChange(status, conversationUUID string, actor umod
return m.InsertConversationActivity(ActivityStatusChange, conversationUUID, status, actor)
}
+// RecordSLASet records an activity for an SLA set.
+func (m *Manager) RecordSLASet(conversationUUID string, slaName string, actor umodels.User) error {
+ return m.InsertConversationActivity(ActivitySLASet, conversationUUID, slaName, actor)
+}
+
+// RecordTagChange records an activity for a tag change.
+func (m *Manager) RecordTagChange(conversationUUID string, tag string, actor umodels.User) error {
+ return m.InsertConversationActivity(ActivityTagChange, conversationUUID, tag, actor)
+}
+
// InsertConversationActivity inserts an activity message.
func (m *Manager) InsertConversationActivity(activityType, conversationUUID, newValue string, actor umodels.User) error {
content, err := m.getMessageActivityContent(activityType, newValue, actor.FullName())
@@ -391,11 +423,13 @@ func (m *Manager) InsertConversationActivity(activityType, conversationUUID, new
ConversationUUID: conversationUUID,
Private: true,
SenderID: actor.ID,
- SenderType: SenderTypeUser,
+ SenderType: SenderTypeAgent,
}
- // InsertMessage message in DB.
- m.InsertMessage(&message)
+ if err := m.InsertMessage(&message); err != nil {
+ m.lo.Error("error inserting activity message", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error inserting activity message", nil)
+ }
return nil
}
@@ -420,11 +454,13 @@ func (m *Manager) getMessageActivityContent(activityType, newValue, actorName st
case ActivitySelfAssign:
content = fmt.Sprintf("%s self-assigned this conversation", actorName)
case ActivityPriorityChange:
- content = fmt.Sprintf("%s changed priority to %s", actorName, newValue)
+ content = fmt.Sprintf("%s set priority to %s", actorName, newValue)
case ActivityStatusChange:
content = fmt.Sprintf("%s marked the conversation as %s", actorName, newValue)
case ActivityTagChange:
- content = fmt.Sprintf("%s added tags %s", actorName, newValue)
+ content = fmt.Sprintf("%s added tag %s", actorName, newValue)
+ case ActivitySLASet:
+ content = fmt.Sprintf("%s set %s SLA", actorName, newValue)
default:
return "", fmt.Errorf("invalid activity type %s", activityType)
}
@@ -434,20 +470,18 @@ func (m *Manager) getMessageActivityContent(activityType, newValue, actorName st
// processIncomingMessage handles the insertion of an incoming message and
// associated contact. It finds or creates the contact, checks for existing
// conversations, and creates a new conversation if necessary. It also
-// inserts the message, uploads any attachments, and evaluates automation rules.
+// inserts the message, uploads any attachments, and queues the conversation evaluation of automation rules.
func (m *Manager) processIncomingMessage(in models.IncomingMessage) error {
- var err error
-
- // Find or create contact.
- in.Message.SenderID, err = m.contactStore.Upsert(in.Contact)
- if err != nil {
+ // Find or create contact and set sender ID in message.
+ if err := m.userStore.CreateContact(&in.Contact); err != nil {
m.lo.Error("error upserting contact", "error", err)
return err
}
+ in.Message.SenderID = in.Contact.ID
- // This message already exists?
+ // Conversations exists for this message?
conversationID, err := m.findConversationID([]string{in.Message.SourceID.String})
- if err != nil && err != ErrConversationNotFound {
+ if err != nil && err != errConversationNotFound {
return err
}
if conversationID > 0 {
@@ -455,18 +489,19 @@ func (m *Manager) processIncomingMessage(in models.IncomingMessage) error {
}
// Find or create new conversation.
- isNewConversation, err := m.findOrCreateConversation(&in.Message, in.InboxID, in.Message.SenderID)
+ isNewConversation, err := m.findOrCreateConversation(&in.Message, in.InboxID, in.Contact.ContactChannelID, in.Contact.ID)
if err != nil {
return err
}
- // Insert message.
- if err = m.InsertMessage(&in.Message); err != nil {
- return err
+ // Upload message attachments.
+ if err := m.uploadMessageAttachments(&in.Message); err != nil {
+ // Log error but continue processing.
+ m.lo.Error("error uploading message attachments", "message_source_id", in.Message.SourceID, "error", err)
}
- // Upload attachments.
- if err := m.uploadMessageAttachments(&in.Message); err != nil {
+ // Insert message.
+ if err = m.InsertMessage(&in.Message); err != nil {
return err
}
@@ -475,6 +510,16 @@ func (m *Manager) processIncomingMessage(in models.IncomingMessage) error {
m.automation.EvaluateNewConversationRules(in.Message.ConversationUUID)
} else {
m.automation.EvaluateConversationUpdateRules(in.Message.ConversationUUID, amodels.EventConversationMessageIncoming)
+ // Reopen conversation if it's closed, snoozed, or resolved.
+ systemUser, err := m.userStore.GetSystemUser()
+ if err != nil {
+ m.lo.Error("error fetching system user", "error", err)
+ return fmt.Errorf("error fetching system user for reopening conversation: %w", err)
+ }
+ if err := m.ReOpenConversation(in.Message.ConversationUUID, systemUser); err != nil {
+ m.lo.Error("error reopening conversation", "error", err)
+ return fmt.Errorf("error reopening conversation: %w", err)
+ }
}
return nil
}
@@ -483,7 +528,7 @@ func (m *Manager) processIncomingMessage(in models.IncomingMessage) error {
func (m *Manager) MessageExists(messageID string) (bool, error) {
_, err := m.findConversationID([]string{messageID})
if err != nil {
- if errors.Is(err, ErrConversationNotFound) {
+ if errors.Is(err, errConversationNotFound) {
return false, nil
}
m.lo.Error("error fetching message from db", "error", err)
@@ -514,7 +559,7 @@ func (m *Manager) GetConversationByMessageID(id int) (models.Conversation, error
var conversation = models.Conversation{}
if err := m.q.GetConversationByMessageID.Get(&conversation, id); err != nil {
if err == sql.ErrNoRows {
- return conversation, ErrConversationNotFound
+ return conversation, errConversationNotFound
}
m.lo.Error("error fetching message from DB", "error", err)
return conversation, envelope.NewError(envelope.GeneralError, "Error fetching message", nil)
@@ -525,13 +570,13 @@ func (m *Manager) GetConversationByMessageID(id int) (models.Conversation, error
// generateMessagesQuery generates the SQL query for fetching messages in a conversation.
func (c *Manager) generateMessagesQuery(baseQuery string, qArgs []interface{}, page, pageSize int) (string, int, []interface{}, error) {
if page <= 0 {
- page = 1
+ return "", 0, nil, errors.New("page must be greater than 0")
}
if pageSize > maxMessagesPerPage {
pageSize = maxMessagesPerPage
}
if pageSize <= 0 {
- pageSize = 10
+ return "", 0, nil, errors.New("page size must be greater than 0")
}
// Calculate the offset
@@ -546,51 +591,63 @@ func (c *Manager) generateMessagesQuery(baseQuery string, qArgs []interface{}, p
}
// uploadMessageAttachments uploads attachments for a message.
-func (m *Manager) uploadMessageAttachments(message *models.Message) error {
+func (m *Manager) uploadMessageAttachments(message *models.Message) []error {
if len(message.Attachments) == 0 {
return nil
}
- var uploadErr error
+ var uploadErr []error
for _, attachment := range message.Attachments {
- // Check if this attachment already exists by content ID.
- exists, err := m.mediaStore.ContentIDExists(attachment.ContentID)
- if err != nil {
- m.lo.Error("error checking media existence", "error", err)
- continue
+ // Check if this attachment already exists by the content ID.
+ if attachment.ContentID != "" {
+ exists, err := m.mediaStore.ContentIDExists(attachment.ContentID)
+ if err != nil {
+ m.lo.Error("error checking media existence by content ID", "content_id", attachment.ContentID, "error", err)
+ continue
+ }
+ if exists {
+ m.lo.Debug("attachment with content ID already exists", "content_id", attachment.ContentID)
+ continue
+ }
}
- if exists {
- m.lo.Debug("attachment already exists", "content_id", attachment.ContentID)
- continue
- }
+ m.lo.Debug("uploading message attachment", "name", attachment.Name, "content_id", attachment.ContentID, "size", attachment.Size)
- m.lo.Debug("uploading message attachment", "name", attachment.Name)
+ // Sanitize filename and upload.
attachment.Name = stringutil.SanitizeFilename(attachment.Name)
-
- reader := bytes.NewReader(attachment.Content)
- _, err = m.mediaStore.UploadAndInsert(
+ attachReader := bytes.NewReader(attachment.Content)
+ media, err := m.mediaStore.UploadAndInsert(
attachment.Name,
attachment.ContentType,
attachment.ContentID,
- mmodels.ModelMessages,
- message.ID,
- reader,
+ /** Linking media to message happens later **/
+ null.String{}, /** modelType */
+ null.Int{}, /** modelID **/
+ attachReader,
attachment.Size,
- attachment.Disposition,
- []byte("{}"),
+ null.StringFrom(attachment.Disposition),
+ []byte("{}"), /** meta **/
)
-
if err != nil {
- uploadErr = err
+ uploadErr = append(uploadErr, err)
m.lo.Error("failed to upload attachment", "name", attachment.Name, "error", err)
}
+
+ // If the attachment is an image, generate and upload thumbnail.
+ attachmentExt := strings.TrimPrefix(strings.ToLower(filepath.Ext(attachment.Name)), ".")
+ if slices.Contains(image.Exts, attachmentExt) {
+ if err := m.uploadThumbnailForMedia(media, attachment.Content); err != nil {
+ uploadErr = append(uploadErr, err)
+ m.lo.Error("error uploading thumbnail", "error", err)
+ }
+ }
+ message.Media = append(message.Media, media)
}
return uploadErr
}
// findOrCreateConversation finds or creates a conversation for the given message.
-func (m *Manager) findOrCreateConversation(in *models.Message, inboxID int, contactID int) (bool, error) {
+func (m *Manager) findOrCreateConversation(in *models.Message, inboxID, contactChannelID, contactID int) (bool, error) {
var (
new bool
err error
@@ -604,25 +661,16 @@ func (m *Manager) findOrCreateConversation(in *models.Message, inboxID int, cont
sourceIDs = append(sourceIDs, in.InReplyTo)
}
conversationID, err = m.findConversationID(sourceIDs)
- if err != nil && err != ErrConversationNotFound {
+ if err != nil && err != errConversationNotFound {
return new, err
}
// Conversation not found, create one.
if conversationID == 0 {
new = true
-
- // Put subject & last message details in meta.
- plainTextContent := stringutil.HTML2Text(in.Content)
- conversationMeta, err := json.Marshal(map[string]string{
- "subject": in.Subject,
- "last_message": plainTextContent,
- "last_message_at": time.Now().Format(time.RFC3339),
- })
- if err != nil {
- return false, err
- }
- conversationID, conversationUUID, err = m.CreateConversation(contactID, inboxID, conversationMeta)
+ lastMessage := stringutil.HTML2Text(in.Content)
+ lastMessageAt := time.Now()
+ conversationID, conversationUUID, err = m.CreateConversation(contactID, contactChannelID, inboxID, lastMessage, lastMessageAt, in.Subject)
if err != nil || conversationID == 0 {
return new, err
}
@@ -630,7 +678,6 @@ func (m *Manager) findOrCreateConversation(in *models.Message, inboxID int, cont
in.ConversationUUID = conversationUUID
return new, nil
}
-
// Get UUID.
if conversationUUID == "" {
conversationUUID, err = m.GetConversationUUID(conversationID)
@@ -646,12 +693,12 @@ func (m *Manager) findOrCreateConversation(in *models.Message, inboxID int, cont
// findConversationID finds the conversation ID from the message source ID.
func (m *Manager) findConversationID(messageSourceIDs []string) (int, error) {
if len(messageSourceIDs) == 0 {
- return 0, ErrConversationNotFound
+ return 0, errConversationNotFound
}
var conversationID int
if err := m.q.MessageExistsBySourceID.QueryRow(pq.Array(messageSourceIDs)).Scan(&conversationID); err != nil {
if err == sql.ErrNoRows {
- return conversationID, ErrConversationNotFound
+ return conversationID, errConversationNotFound
}
m.lo.Error("error fetching msg from DB", "error", err)
return conversationID, err
@@ -680,7 +727,7 @@ func (m *Manager) attachAttachmentsToMessage(message *models.Message) error {
attachment := attachment.Attachment{
Name: media.Filename,
Content: blob,
- Header: attachment.MakeHeader(media.ContentType, media.UUID, media.Filename, "base64", media.Disposition),
+ Header: attachment.MakeHeader(media.ContentType, media.UUID, media.Filename, "base64", media.Disposition.String),
}
attachments = append(attachments, attachment)
}
@@ -702,3 +749,28 @@ func (m *Manager) getOutgoingProcessingMessageIDs() []int {
})
return out
}
+
+// uploadThumbnailForMedia prepares and uploads a thumbnail for an image attachment.
+func (m *Manager) uploadThumbnailForMedia(media mmodels.Media, content []byte) error {
+ // Create a reader from the content
+ file := bytes.NewReader(content)
+
+ // Seek to the beginning of the file
+ file.Seek(0, 0)
+
+ // Create the thumbnail
+ thumbFile, err := image.CreateThumb(image.DefThumbSize, file)
+ if err != nil {
+ return fmt.Errorf("error creating thumbnail: %w", err)
+ }
+
+ // Generate thumbnail name
+ thumbName := fmt.Sprintf("thumb_%s", media.UUID)
+
+ // Upload the thumbnail
+ if _, err := m.mediaStore.Upload(thumbName, media.ContentType, thumbFile); err != nil {
+ m.lo.Error("error uploading thumbnail", "error", err)
+ return fmt.Errorf("error uploading thumbnail: %w", err)
+ }
+ return nil
+}
diff --git a/internal/conversation/models/models.go b/internal/conversation/models/models.go
index 732c7e7d..37ed4bb7 100644
--- a/internal/conversation/models/models.go
+++ b/internal/conversation/models/models.go
@@ -1,50 +1,71 @@
package models
import (
+ "encoding/json"
"net/textproto"
"time"
- "github.com/abhinavxd/artemis/internal/attachment"
- cmodels "github.com/abhinavxd/artemis/internal/contact/models"
- mmodels "github.com/abhinavxd/artemis/internal/media/models"
+ "github.com/abhinavxd/libredesk/internal/attachment"
+ mmodels "github.com/abhinavxd/libredesk/internal/media/models"
+ umodels "github.com/abhinavxd/libredesk/internal/user/models"
+ "github.com/lib/pq"
"github.com/volatiletech/null/v9"
)
var (
- StatusOpen = "Open"
+ StatusOpen = "Open"
+ StatusReplied = "Replied"
+ StatusResolved = "Resolved"
+ StatusClosed = "Closed"
+ StatusSnoozed = "Snoozed"
AssigneeTypeTeam = "team"
AssigneeTypeUser = "user"
- AllConversations = "all"
- AssignedConversations = "assigned"
- UnassignedConversations = "unassigned"
+ AllConversations = "all"
+ AssignedConversations = "assigned"
+ UnassignedConversations = "unassigned"
+ TeamUnassignedConversations = "team_unassigned"
)
type Conversation struct {
- ID int `db:"id" json:"id"`
- CreatedAt time.Time `db:"created_at" json:"created_at"`
- UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
- UUID string `db:"uuid" json:"uuid"`
- ClosedAt null.Time `db:"closed_at" json:"closed_at,omitempty"`
- ResolvedAt null.Time `db:"resolved_at" json:"resolved_at,omitempty"`
- ReferenceNumber string `db:"reference_number" json:"reference_number,omitempty"`
- Priority null.String `db:"priority" json:"priority"`
- Status null.String `db:"status" json:"status"`
- FirstReplyAt null.Time `db:"first_reply_at" json:"first_reply_at"`
- ContactID int `db:"contact_id" json:"contact_id"`
- AssignedUserID null.Int `db:"assigned_user_id" json:"assigned_user_id"`
- AssignedTeamID null.Int `db:"assigned_team_id" json:"assigned_team_id"`
- AssigneeLastSeenAt null.Time `db:"assignee_last_seen_at" json:"assignee_last_seen_at"`
- Subject string `db:"subject" json:"subject"`
- UnreadMessageCount int `db:"unread_message_count" json:"unread_message_count"`
- InboxName string `db:"inbox_name" json:"inbox_name"`
- InboxChannel string `db:"inbox_channel" json:"inbox_channel"`
- Tags null.JSON `db:"tags" json:"tags"`
- LastMessageAt null.Time `db:"last_message_at" json:"last_message_at"`
- LastMessage string `db:"last_message" json:"last_message"`
- Contact cmodels.Contact `db:"contact" json:"contact"`
- Total int `db:"total" json:"-"`
+ ID int `db:"id" json:"id,omitempty"`
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+ UUID string `db:"uuid" json:"uuid"`
+ ContactID int `db:"contact_id" json:"contact_id"`
+ InboxID int `db:"inbox_id" json:"inbox_id,omitempty"`
+ ClosedAt null.Time `db:"closed_at" json:"closed_at,omitempty"`
+ ResolvedAt null.Time `db:"resolved_at" json:"resolved_at,omitempty"`
+ ReferenceNumber string `db:"reference_number" json:"reference_number,omitempty"`
+ Priority null.String `db:"priority" json:"priority"`
+ PriorityID null.Int `db:"priority_id" json:"priority_id"`
+ Status null.String `db:"status" json:"status"`
+ StatusID null.Int `db:"status_id" json:"status_id"`
+ FirstReplyAt null.Time `db:"first_reply_at" json:"first_reply_at"`
+ AssignedUserID null.Int `db:"assigned_user_id" json:"assigned_user_id"`
+ AssignedTeamID null.Int `db:"assigned_team_id" json:"assigned_team_id"`
+ AssigneeLastSeenAt null.Time `db:"assignee_last_seen_at" json:"assignee_last_seen_at"`
+ WaitingSince null.Time `db:"waiting_since" json:"waiting_since"`
+ Subject null.String `db:"subject" json:"subject"`
+ UnreadMessageCount int `db:"unread_message_count" json:"unread_message_count"`
+ InboxName string `db:"inbox_name" json:"inbox_name"`
+ InboxChannel string `db:"inbox_channel" json:"inbox_channel"`
+ Tags null.JSON `db:"tags" json:"tags"`
+ Meta pq.StringArray `db:"meta" json:"meta"`
+ CustomAttributes pq.StringArray `db:"custom_attributes" json:"custom_attributes"`
+ LastMessageAt null.Time `db:"last_message_at" json:"last_message_at"`
+ LastMessage null.String `db:"last_message" json:"last_message"`
+ Contact umodels.User `db:"contact" json:"contact"`
+ SLAPolicyID null.Int `db:"sla_policy_id" json:"sla_policy_id"`
+ SlaPolicyName null.String `db:"sla_policy_name" json:"sla_policy_name"`
+ NextSLADeadlineAt null.Time `db:"next_sla_deadline_at" json:"next_sla_deadline_at"`
+ BCC json.RawMessage `db:"bcc" json:"bcc"`
+ CC json.RawMessage `db:"cc" json:"cc"`
+ FirstResponseDueAt null.Time `db:"-" json:"first_response_due_at"`
+ ResolutionDueAt null.Time `db:"-" json:"resolution_due_at"`
+ PreviousConversations []Conversation `db:"-" json:"previous_conversations"`
+ Total int `db:"total" json:"-"`
}
type ConversationParticipant struct {
@@ -68,7 +89,7 @@ type NewConversationsStats struct {
// Message represents a message in a conversation
type Message struct {
- ID int `db:"id" json:"id"`
+ ID int `db:"id" json:"id,omitempty"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
UUID string `db:"uuid" json:"uuid"`
@@ -76,6 +97,7 @@ type Message struct {
Status string `db:"status" json:"status"`
ConversationID int `db:"conversation_id" json:"conversation_id"`
Content string `db:"content" json:"content"`
+ TextContent string `db:"text_content" json:"text_content"`
ContentType string `db:"content_type" json:"content_type"`
Private bool `db:"private" json:"private"`
SourceID null.String `db:"source_id" json:"-"`
@@ -90,6 +112,8 @@ type Message struct {
AltContent string `db:"alt_content" json:"-"`
Subject string `db:"subject" json:"-"`
Channel string `db:"channel" json:"-"`
+ CC pq.StringArray `db:"cc" json:"-"`
+ BCC pq.StringArray `db:"bcc" json:"-"`
References []string `json:"-"`
InReplyTo string `json:"-"`
Headers textproto.MIMEHeader `json:"-"`
@@ -97,10 +121,22 @@ type Message struct {
Total int `db:"total" json:"-"`
}
+// CensorCSATContent redacts the content of a CSAT message to prevent leaking the CSAT survey public link.
+func (m *Message) CensorCSATContent() {
+ var meta map[string]interface{}
+ if err := json.Unmarshal([]byte(m.Meta), &meta); err != nil {
+ return
+ }
+ if isCsat, _ := meta["is_csat"].(bool); isCsat {
+ m.Content = "Please rate your experience with us"
+ m.TextContent = m.Content
+ }
+}
+
// IncomingMessage links a message with the contact information and inbox id.
type IncomingMessage struct {
Message Message
- Contact cmodels.Contact
+ Contact umodels.User
InboxID int
}
diff --git a/internal/conversation/priority/priority.go b/internal/conversation/priority/priority.go
index cb9e5d2b..64fb02cd 100644
--- a/internal/conversation/priority/priority.go
+++ b/internal/conversation/priority/priority.go
@@ -4,9 +4,9 @@ package priority
import (
"embed"
- "github.com/abhinavxd/artemis/internal/conversation/priority/models"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/conversation/priority/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
"github.com/jmoiron/sqlx"
"github.com/zerodha/logf"
)
@@ -31,6 +31,7 @@ type Opts struct {
// queries contains prepared SQL queries.
type queries struct {
GetAll *sqlx.Stmt `query:"get-all"`
+ Get *sqlx.Stmt `query:"get"`
}
// New creates and returns a new instance of the Manager.
@@ -54,3 +55,13 @@ func (m *Manager) GetAll() ([]models.Priority, error) {
}
return priorities, nil
}
+
+// Get retrieves a priority by ID.
+func (m *Manager) Get(id int) (models.Priority, error) {
+ var priority models.Priority
+ if err := m.q.Get.Get(&priority, id); err != nil {
+ m.lo.Error("error fetching priority", "error", err)
+ return priority, envelope.NewError(envelope.GeneralError, "Error fetching priority", nil)
+ }
+ return priority, nil
+}
diff --git a/internal/conversation/priority/queries.sql b/internal/conversation/priority/queries.sql
index 0bf95aa5..ab887bf2 100644
--- a/internal/conversation/priority/queries.sql
+++ b/internal/conversation/priority/queries.sql
@@ -1,2 +1,5 @@
-- name: get-all
-SELECT created_at, id, name from conversation_priorities;
\ No newline at end of file
+SELECT created_at, id, name from conversation_priorities;
+
+-- name: get
+SELECT created_at, id, name from conversation_priorities WHERE id = $1;
\ No newline at end of file
diff --git a/internal/conversation/queries.sql b/internal/conversation/queries.sql
index bb682684..571ef406 100644
--- a/internal/conversation/queries.sql
+++ b/internal/conversation/queries.sql
@@ -1,115 +1,159 @@
+-- name: unsnooze-all
+UPDATE conversations
+SET snoozed_until = NULL, status_id = (SELECT id FROM conversation_statuses WHERE name = 'Open')
+WHERE snoozed_until <= now();
+
-- name: insert-conversation
+WITH
+status_id AS (
+ SELECT id FROM conversation_statuses WHERE name = $3
+),
+reference_number AS (
+ SELECT generate_reference_number($8) as reference_number
+)
INSERT INTO conversations
-(reference_number, contact_id, status_id, inbox_id, meta)
-VALUES($1, $2,
- (SELECT id FROM conversation_statuses WHERE name = $3),
- $4,
- $5)
+(contact_id, contact_channel_id, status_id, inbox_id, last_message, last_message_at, subject, reference_number)
+VALUES(
+ $1,
+ $2,
+ (SELECT id FROM status_id),
+ $4,
+ $5,
+ $6,
+ $7,
+ (SELECT reference_number FROM reference_number)
+)
RETURNING id, uuid;
-- name: get-conversations
SELECT
- COUNT(*) OVER() AS total,
+ COUNT(*) OVER() as total,
+ conversations.id,
+ conversations.created_at,
conversations.updated_at,
conversations.uuid,
+ conversations.waiting_since,
conversations.assignee_last_seen_at,
- contacts.first_name as "contact.first_name",
- contacts.last_name as "contact.last_name",
- contacts.avatar_url as "contact.avatar_url",
+ users.created_at as "contact.created_at",
+ users.updated_at as "contact.updated_at",
+ users.first_name as "contact.first_name",
+ users.last_name as "contact.last_name",
+ users.avatar_url as "contact.avatar_url",
inboxes.channel as inbox_channel,
inboxes.name as inbox_name,
- COALESCE(conversations.meta->>'subject', '') as subject,
- COALESCE(conversations.meta->>'last_message', '') as last_message,
- COALESCE((conversations.meta->>'last_message_at')::timestamp, '1970-01-01 00:00:00'::timestamp) as last_message_at,
+ conversations.sla_policy_id,
+ conversations.first_reply_at,
+ conversations.resolved_at,
+ conversations.subject,
+ conversations.last_message,
+ conversations.last_message_at,
+ conversations.next_sla_deadline_at,
+ conversations.priority_id,
(
- SELECT COUNT(*)
- FROM conversation_messages m
- WHERE m.conversation_id = conversations.id AND m.created_at > conversations.assignee_last_seen_at
- ) AS unread_message_count,
+ SELECT CASE WHEN COUNT(*) > 9 THEN 10 ELSE COUNT(*) END
+ FROM (
+ SELECT 1 FROM conversation_messages
+ WHERE conversation_id = conversations.id
+ AND created_at > conversations.assignee_last_seen_at
+ LIMIT 10
+ ) t
+ ) as unread_message_count,
conversation_statuses.name as status,
conversation_priorities.name as priority
-FROM conversations
- JOIN contacts ON conversations.contact_id = contacts.id
- JOIN inboxes ON conversations.inbox_id = inboxes.id
- LEFT JOIN conversation_statuses ON conversations.status_id = conversation_statuses.id
- LEFT JOIN conversation_priorities ON conversations.priority_id = conversation_priorities.id
-WHERE 1=1 %s
-
--- name: get-conversations-list-uuids
-SELECT
- conversations.uuid
-FROM conversations
-LEFT JOIN conversation_statuses ON conversations.status_id = conversation_statuses.id
-LEFT JOIN conversation_priorities ON conversations.priority_id = conversation_priorities.id
+ FROM conversations
+ JOIN users ON contact_id = users.id
+ JOIN inboxes ON inbox_id = inboxes.id
+ LEFT JOIN conversation_statuses ON status_id = conversation_statuses.id
+ LEFT JOIN conversation_priorities ON priority_id = conversation_priorities.id
WHERE 1=1 %s
-- name: get-conversation
+WITH last_reply AS (
+ SELECT
+ conversation_id,
+ meta->'cc' as cc,
+ meta->'bcc' as bcc
+ FROM conversation_messages
+ WHERE private = false
+ AND type IN ('outgoing', 'incoming')
+ AND (
+ ($1 > 0 AND conversation_id = $1)
+ OR ($2 != '' AND conversation_id = (SELECT id FROM conversations WHERE uuid = $2::uuid))
+ )
+ ORDER BY created_at DESC
+ LIMIT 1
+)
SELECT
- c.created_at,
- c.updated_at,
- c.closed_at,
- c.resolved_at,
- p.name as priority,
- s.name as status,
- c.uuid,
- c.reference_number,
- c.first_reply_at,
- c.assigned_user_id,
- c.assigned_team_id,
- c.meta->>'subject' as subject,
- c.contact_id,
- COALESCE(c.meta->>'last_message', '') as last_message,
- (SELECT COALESCE(
- (SELECT json_agg(t.name)
- FROM tags t
- INNER JOIN conversation_tags ct ON ct.tag_id = t.id
- WHERE ct.conversation_id = c.id),
- '[]'::json
- )) AS tags,
- ct.first_name as "contact.first_name",
- ct.last_name as "contact.last_name",
- ct.email as "contact.email",
- ct.phone_number as "contact.phone_number",
- ct.avatar_url as "contact.avatar_url"
+ c.id,
+ c.created_at,
+ c.updated_at,
+ c.closed_at,
+ c.resolved_at,
+ c.inbox_id,
+ c.status_id,
+ c.priority_id,
+ p.name as priority,
+ s.name as status,
+ c.uuid,
+ c.reference_number,
+ c.first_reply_at,
+ c.waiting_since,
+ c.assigned_user_id,
+ c.assigned_team_id,
+ c.subject,
+ c.contact_id,
+ c.sla_policy_id,
+ sla.name as sla_policy_name,
+ c.last_message,
+ (SELECT COALESCE(
+ (SELECT json_agg(t.name)
+ FROM tags t
+ INNER JOIN conversation_tags ct ON ct.tag_id = t.id
+ WHERE ct.conversation_id = c.id),
+ '[]'::json
+ )) AS tags,
+ ct.created_at as "contact.created_at",
+ ct.updated_at as "contact.updated_at",
+ ct.first_name as "contact.first_name",
+ ct.last_name as "contact.last_name",
+ ct.email as "contact.email",
+ ct.avatar_url as "contact.avatar_url",
+ ct.phone_number as "contact.phone_number",
+ COALESCE(lr.cc, '[]'::jsonb) as cc,
+ COALESCE(lr.bcc, '[]'::jsonb) as bcc
FROM conversations c
-JOIN contacts ct ON c.contact_id = ct.id
-LEFT JOIN users u ON u.id = c.assigned_user_id
+JOIN users ct ON c.contact_id = ct.id
+LEFT JOIN sla_policies sla ON c.sla_policy_id = sla.id
LEFT JOIN teams at ON at.id = c.assigned_team_id
LEFT JOIN conversation_statuses s ON c.status_id = s.id
LEFT JOIN conversation_priorities p ON c.priority_id = p.id
-WHERE c.uuid = $1;
+LEFT JOIN last_reply lr ON lr.conversation_id = c.id
+WHERE
+ ($1 > 0 AND c.id = $1)
+ OR
+ ($2 != '' AND c.uuid = $2::uuid)
+
-- name: get-conversations-created-after
SELECT
- c.created_at,
- c.updated_at,
- c.closed_at,
- c.resolved_at,
- p.name as priority,
- s.name as status,
- c.uuid,
- c.reference_number,
- c.first_reply_at,
- ct.first_name as first_name,
- ct.last_name as last_name,
- ct.email as email,
- ct.phone_number as phone_number,
- ct.avatar_url as avatar_url,
- (SELECT COALESCE(
- (SELECT json_agg(t.name)
- FROM tags t
- INNER JOIN conversation_tags ct ON ct.tag_id = t.id
- WHERE ct.conversation_id = c.id),
- '[]'::json
- )) AS tags
+ c.id,
+ c.uuid
FROM conversations c
-JOIN contacts ct ON c.contact_id = ct.id
-LEFT JOIN conversation_statuses s ON c.status_id = s.id
-LEFT JOIN conversation_priorities p ON c.priority_id = p.id
WHERE c.created_at > $1;
--- name: get-conversation-id
-SELECT id from conversations where uuid = $1;
+-- name: get-contact-conversations
+SELECT
+ c.uuid,
+ u.first_name AS "contact.first_name",
+ u.last_name AS "contact.last_name",
+ u.avatar_url AS "contact.avatar_url",
+ c.last_message,
+ c.last_message_at
+FROM users u
+JOIN conversations c ON c.contact_id = u.id
+WHERE c.contact_id = $1
+ORDER BY c.created_at DESC
+LIMIT 10;
-- name: get-conversation-uuid
SELECT uuid from conversations where id = $1;
@@ -117,34 +161,29 @@ SELECT uuid from conversations where id = $1;
-- name: update-conversation-assigned-user
UPDATE conversations
SET assigned_user_id = $2,
+-- Reset assignee_last_seen_at when assigned to a new user.
+assignee_last_seen_at = NULL,
updated_at = now()
WHERE uuid = $1;
-- name: update-conversation-assigned-team
UPDATE conversations
SET assigned_team_id = $2,
-assigned_user_id = NULL,
updated_at = now()
WHERE uuid = $1;
-- name: update-conversation-status
UPDATE conversations
SET status_id = (SELECT id FROM conversation_statuses WHERE name = $2),
- resolved_at = CASE
- WHEN $2 = 'Resolved' THEN
- COALESCE(resolved_at, CURRENT_TIMESTAMP)
- WHEN $2 != 'Resolved' THEN
- resolved_at
- END,
- closed_at = CASE
- WHEN $2 = 'Closed' THEN
- COALESCE(closed_at, CURRENT_TIMESTAMP)
- ELSE
- closed_at
- END,
+ resolved_at = CASE WHEN $2 = 'Resolved' THEN NOW() ELSE resolved_at END,
+ closed_at = CASE WHEN $2 = 'Closed' THEN NOW() ELSE closed_at END,
+ snoozed_until = CASE WHEN $2 = 'Snoozed' THEN $3::timestamptz ELSE NULL END,
updated_at = now()
WHERE uuid = $1;
+-- name: get-user-active-conversations-count
+SELECT COUNT(*) FROM conversations WHERE status_id IN (SELECT id FROM conversation_statuses WHERE name NOT IN ('Resolved', 'Closed')) and assigned_user_id = $1;
+
-- name: update-conversation-priority
UPDATE conversations
SET priority_id = (SELECT id FROM conversation_priorities WHERE name = $2),
@@ -157,10 +196,11 @@ SET assignee_last_seen_at = now(),
updated_at = now()
WHERE uuid = $1;
--- name: update-conversation-meta
-UPDATE conversations
-SET meta = meta || $3, updated_at = now()
-WHERE CASE WHEN $1 > 0 THEN id = $1 ELSE uuid = $2 END;
+-- name: update-conversation-last-message
+UPDATE conversations SET last_message = $3, last_message_at = $4 WHERE CASE
+ WHEN $1 > 0 THEN id = $1
+ ELSE uuid = $2
+END
-- name: get-conversation-participants
SELECT users.id as id, first_name, last_name, avatar_url
@@ -178,42 +218,26 @@ VALUES($1, (SELECT id FROM conversations WHERE uuid = $2));
-- name: get-unassigned-conversations
SELECT
+ c.created_at,
c.updated_at,
c.uuid,
- c.assignee_last_seen_at,
c.assigned_team_id,
inb.channel as inbox_channel,
- inb.name as inbox_name,
- ct.first_name,
- ct.last_name,
- ct.avatar_url,
- COALESCE(c.meta->>'subject', '') as subject,
- COALESCE(c.meta->>'last_message', '') as last_message,
- COALESCE((c.meta->>'last_message_at')::timestamp, '1970-01-01 00:00:00'::timestamp) as last_message_at,
- (
- SELECT COUNT(*)
- FROM conversation_messages m
- WHERE m.conversation_id = c.id AND m.created_at > c.assignee_last_seen_at
- ) AS unread_message_count,
- s.name as status,
- p.name as priority
+ inb.name as inbox_name
FROM conversations c
- JOIN contacts ct ON c.contact_id = ct.id
JOIN inboxes inb ON c.inbox_id = inb.id
- LEFT JOIN conversation_statuses s ON c.status_id = s.id
- LEFT JOIN conversation_priorities p ON c.priority_id = p.id
WHERE assigned_user_id IS NULL AND assigned_team_id IS NOT NULL;
-- name: get-dashboard-counts
SELECT json_build_object(
- 'resolved_count', COUNT(CASE WHEN s.name = 'Resolved' THEN 1 END),
- 'unresolved_count', COUNT(CASE WHEN s.name NOT IN ('Resolved', 'Closed') THEN 1 END),
- 'awaiting_response_count', COUNT(CASE WHEN first_reply_at IS NULL THEN 1 END),
- 'total_count', COUNT(*)
+ 'open', COUNT(*),
+ 'awaiting_response', COUNT(CASE WHEN c.waiting_since IS NOT NULL THEN 1 END),
+ 'unassigned', COUNT(CASE WHEN c.assigned_user_id IS NULL THEN 1 END),
+ 'pending', COUNT(CASE WHEN c.first_reply_at IS NOT NULL THEN 1 END)
)
FROM conversations c
-LEFT JOIN conversation_statuses s ON c.status_id = s.id
-WHERE 1=1 %s
+INNER JOIN conversation_statuses s ON c.status_id = s.id
+WHERE s.name not in ('Resolved', 'Closed') AND 1=1 %s;
-- name: get-dashboard-charts
WITH new_conversations AS (
@@ -221,7 +245,7 @@ WITH new_conversations AS (
FROM (
SELECT
TO_CHAR(created_at::date, 'YYYY-MM-DD') AS date,
- COUNT(*) AS new_conversations
+ COUNT(*) AS count
FROM
conversations c
WHERE 1=1 %s
@@ -231,6 +255,21 @@ WITH new_conversations AS (
date
) agg
),
+resolved_conversations AS (
+ SELECT json_agg(row_to_json(agg)) AS data
+ FROM (
+ SELECT
+ TO_CHAR(resolved_at::date, 'YYYY-MM-DD') AS date,
+ COUNT(*) AS count
+ FROM
+ conversations c
+ WHERE c.resolved_at IS NOT NULL AND 1=1 %s
+ GROUP BY
+ date
+ ORDER BY
+ date
+ ) agg
+),
status_summary AS (
SELECT json_agg(row_to_json(agg)) AS data
FROM (
@@ -243,13 +282,30 @@ status_summary AS (
conversations c
LEFT join conversation_statuses s on s.id = c.status_id
LEFT join conversation_priorities p on p.id = c.priority_id
- WHERE 1=1 %s
+ WHERE 1=1 AND s.name > '' %s
GROUP BY
s.name
) agg
+),
+messages_sent as (
+ SELECT json_agg(row_to_json(agg)) AS data
+ FROM (
+ SELECT
+ TO_CHAR(created_at::date, 'YYYY-MM-DD') AS date,
+ COUNT(*) AS count
+ FROM
+ conversation_messages c
+ WHERE status = 'sent' AND 1=1 %s
+ GROUP BY
+ date
+ ORDER BY
+ date
+ ) agg
)
SELECT json_build_object(
'new_conversations', (SELECT data FROM new_conversations),
+ 'resolved_conversations', (SELECT data FROM resolved_conversations),
+ 'messages_sent', (SELECT data FROM messages_sent),
'status_summary', (SELECT data FROM status_summary)
) AS result;
@@ -263,21 +319,32 @@ WHERE first_reply_at IS NULL AND id = $1;
WITH conversation_id AS (
SELECT id FROM conversations WHERE uuid = $1
),
+-- Insert new tags
inserted AS (
INSERT INTO conversation_tags (conversation_id, tag_id)
- SELECT conversation_id.id, unnest($2::int[])
- FROM conversation_id
+ SELECT conversation_id.id, t.id
+ FROM conversation_id, tags t
+ WHERE t.name = ANY($2::text[])
ON CONFLICT (conversation_id, tag_id) DO UPDATE SET tag_id = EXCLUDED.tag_id
)
+-- Delete tags that are not in the new list
DELETE FROM conversation_tags
WHERE conversation_id = (SELECT id FROM conversation_id)
- AND tag_id NOT IN (SELECT unnest($2::int[]));
+AND tag_id NOT IN (
+ SELECT id FROM tags WHERE name = ANY($2::text[])
+);
+
+-- name: get-conversation-tags
+SELECT t.name
+FROM conversation_tags ct
+JOIN tags t ON ct.tag_id = t.id
+WHERE ct.conversation_id = (SELECT id FROM conversations WHERE uuid = $1);
-- name: get-to-address
-SELECT cm.source_id
+SELECT cc.identifier
FROM conversations c
-INNER JOIN contact_methods cm ON cm.contact_id = c.contact_id
-WHERE c.id = $1 AND cm.source = $2;
+INNER JOIN contact_channels cc ON cc.id = c.contact_channel_id
+WHERE c.id = $1;
-- name: get-conversation-uuid-from-message-uuid
SELECT c.uuid AS conversation_uuid
@@ -311,9 +378,11 @@ SELECT
m.conversation_id,
m.content_type,
m.source_id,
+ ARRAY(SELECT jsonb_array_elements_text(m.meta->'cc')) AS cc,
+ ARRAY(SELECT jsonb_array_elements_text(m.meta->'bcc')) AS bcc,
c.inbox_id,
c.uuid as conversation_uuid,
- COALESCE(c.meta->>'subject', '') as subject
+ c.subject
FROM conversation_messages m
INNER JOIN conversations c ON c.id = m.conversation_id
WHERE m.status = 'pending'
@@ -330,6 +399,7 @@ SELECT
m.private,
m.sender_type,
m.sender_id,
+ m.meta,
COALESCE(
json_agg(
json_build_object(
@@ -344,87 +414,75 @@ SELECT
'[]'::json
) AS attachments
FROM conversation_messages m
-LEFT JOIN media ON media.model_id = m.id AND media.model_type = 'messages'
+LEFT JOIN media ON media.model_type = 'messages' AND media.model_id = m.id
WHERE m.uuid = $1
GROUP BY
m.id, m.created_at, m.updated_at, m.status, m.type, m.content, m.uuid, m.private, m.sender_type
ORDER BY m.created_at;
-- name: get-messages
-WITH conversation_id AS (
- SELECT id
- FROM conversations
- WHERE uuid = $1
- LIMIT 1
-),
-attachments AS (
- SELECT
- model_id as message_id,
- json_agg(
- json_build_object(
- 'name', filename,
- 'content_type', content_type,
- 'uuid', uuid,
- 'size', size,
- 'content_id', content_id,
- 'disposition', disposition
- ) ORDER BY filename
- ) AS attachment_details
- FROM media
- WHERE model_type = 'messages'
- GROUP BY message_id
-)
SELECT
- COUNT(*) OVER() AS total,
- m.created_at,
- m.updated_at,
- m.status,
- m.type,
- m.content,
- m.uuid,
- m.private,
- m.sender_id,
- m.sender_type,
- COALESCE(a.attachment_details, '[]'::json) AS attachments
+ COUNT(*) OVER() AS total,
+ m.created_at,
+ m.updated_at,
+ m.status,
+ m.type,
+ m.content,
+ m.uuid,
+ m.private,
+ m.sender_id,
+ m.sender_type,
+ m.meta,
+ COALESCE(
+ (SELECT json_agg(
+ json_build_object(
+ 'name', filename,
+ 'content_type', content_type,
+ 'uuid', uuid,
+ 'size', size,
+ 'content_id', content_id,
+ 'disposition', disposition
+ ) ORDER BY filename
+ ) FROM media
+ WHERE model_type = 'messages' AND model_id = m.id),
+ '[]'::json) AS attachments
FROM conversation_messages m
-LEFT JOIN attachments a ON a.message_id = m.id
-WHERE m.conversation_id = (SELECT id FROM conversation_id) ORDER BY m.created_at DESC
-%s
+WHERE m.conversation_id = (
+ SELECT id FROM conversations WHERE uuid = $1 LIMIT 1
+)
+ORDER BY m.created_at DESC %s
-- name: insert-message
WITH conversation_id AS (
- SELECT id
- FROM conversations
- WHERE CASE
- WHEN $3 > 0 THEN id = $3
- ELSE uuid = $4
- END
+ SELECT id
+ FROM conversations
+ WHERE CASE
+ WHEN $3 > 0 THEN id = $3
+ ELSE uuid = $4
+ END
+),
+inserted_msg AS (
+ INSERT INTO conversation_messages (
+ "type", status, conversation_id, "content",
+ text_content, sender_id, sender_type, private,
+ content_type, source_id, meta
+ )
+ VALUES (
+ $1, $2, (SELECT id FROM conversation_id),
+ $5, $6, $7, $8, $9, $10, $11, $12
+ )
+ RETURNING id, uuid, created_at, conversation_id
+),
+updated_conversation AS (
+ UPDATE conversations
+ SET waiting_since = CASE
+ WHEN $8 = 'contact' THEN NOW()
+ WHEN $8 = 'agent' THEN NULL
+ ELSE waiting_since
+ END
+ WHERE id = (SELECT id FROM conversation_id)
)
-INSERT INTO conversation_messages (
- "type",
- status,
- conversation_id,
- "content",
- sender_id,
- sender_type,
- private,
- content_type,
- source_id,
- meta
-)
-VALUES (
- $1,
- $2,
- (SELECT id FROM conversation_id),
- $5,
- $6,
- $7,
- $8,
- $9,
- $10,
- $11
-)
-RETURNING id, uuid, created_at;
+SELECT id, uuid, created_at FROM inserted_msg;
-- name: message-exists-by-source-id
SELECT conversation_id
@@ -443,3 +501,19 @@ WHERE m.id = $1;
-- name: update-message-status
update conversation_messages set status = $1, updated_at = now() where uuid = $2;
+
+-- name: remove-conversation-assignee
+UPDATE conversations
+SET
+ assigned_user_id = CASE WHEN $2 = 'user' THEN NULL ELSE assigned_user_id END,
+ assigned_team_id = CASE WHEN $2 = 'team' THEN NULL ELSE assigned_team_id END,
+ updated_at = now()
+WHERE uuid = $1;
+
+-- name: re-open-conversation
+UPDATE conversations
+SET status_id = (SELECT id FROM conversation_statuses WHERE name = 'Open'), snoozed_until = NULL,
+ updated_at = now()
+WHERE uuid = $1 and status_id in (
+ SELECT id FROM conversation_statuses WHERE name IN ('Snoozed', 'Closed', 'Resolved')
+)
\ No newline at end of file
diff --git a/internal/conversation/status/models/models.go b/internal/conversation/status/models/models.go
index c65f8dd1..b794a9df 100644
--- a/internal/conversation/status/models/models.go
+++ b/internal/conversation/status/models/models.go
@@ -7,6 +7,7 @@ var DefaultStatuses = []string{
"Replied",
"Resolved",
"Closed",
+ "Snoozed",
}
type Status struct {
diff --git a/internal/conversation/status/status.go b/internal/conversation/status/status.go
index 564363b5..cb069935 100644
--- a/internal/conversation/status/status.go
+++ b/internal/conversation/status/status.go
@@ -5,9 +5,9 @@ import (
"embed"
"slices"
- "github.com/abhinavxd/artemis/internal/conversation/status/models"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/conversation/status/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
"github.com/jmoiron/sqlx"
"github.com/zerodha/logf"
)
@@ -41,11 +41,9 @@ type queries struct {
// New creates and returns a new instance of the Manager.
func New(opts Opts) (*Manager, error) {
var q queries
-
if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
return nil, err
}
-
return &Manager{
q: q,
lo: opts.Lo,
@@ -74,7 +72,7 @@ func (m *Manager) Create(name string) error {
// Delete deletes a status by ID.
func (m *Manager) Delete(id int) error {
// Disallow deletion of default statuses.
- status, err := m.get(id)
+ status, err := m.Get(id)
if err != nil {
return envelope.NewError(envelope.GeneralError, "Error fetching status", nil)
}
@@ -84,9 +82,8 @@ func (m *Manager) Delete(id int) error {
}
if _, err := m.q.DeleteStatus.Exec(id); err != nil {
- // Check if the error is a foreign key error.
if dbutil.IsForeignKeyError(err) {
- return envelope.NewError(envelope.InputError, "Cannot delete status as it is in use, Please remove this status from all conversations before deleting", nil)
+ return envelope.NewError(envelope.InputError, "Cannot delete status as it is in use, Please remove this status from all conversations before deleting.", nil)
}
m.lo.Error("error deleting status", "error", err)
return envelope.NewError(envelope.GeneralError, "Error deleting status", nil)
@@ -96,6 +93,16 @@ func (m *Manager) Delete(id int) error {
// Update updates a status by id.
func (m *Manager) Update(id int, name string) error {
+ // Disallow updating of default statuses.
+ status, err := m.Get(id)
+ if err != nil {
+ return envelope.NewError(envelope.GeneralError, "Error fetching status", nil)
+ }
+
+ if slices.Contains(models.DefaultStatuses, status.Name) {
+ return envelope.NewError(envelope.InputError, "Cannot update default status", nil)
+ }
+
if _, err := m.q.UpdateStatus.Exec(id, name); err != nil {
m.lo.Error("error updating status", "error", err)
return envelope.NewError(envelope.GeneralError, "Error updating status", nil)
@@ -103,12 +110,12 @@ func (m *Manager) Update(id int, name string) error {
return nil
}
-// get retrieves a status by ID.
-func (m *Manager) get(id int) (models.Status, error) {
+// Get retrieves a status by ID.
+func (m *Manager) Get(id int) (models.Status, error) {
var status models.Status
if err := m.q.GetStatus.Get(&status, id); err != nil {
m.lo.Error("error fetching status", "error", err)
- return status, err
+ return status, envelope.NewError(envelope.GeneralError, "Error fetching status", nil)
}
return status, nil
}
diff --git a/internal/conversation/unsnoozer.go b/internal/conversation/unsnoozer.go
new file mode 100644
index 00000000..97d2b2e4
--- /dev/null
+++ b/internal/conversation/unsnoozer.go
@@ -0,0 +1,34 @@
+package conversation
+
+import (
+ "context"
+ "fmt"
+ "time"
+)
+
+// RunUnsnoozer runs the conversation unsnoozer.
+func (c *Manager) RunUnsnoozer(ctx context.Context, unsnoozeInterval time.Duration) {
+ ticker := time.NewTicker(unsnoozeInterval)
+ defer ticker.Stop()
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case <-ticker.C:
+ c.unsnoozeAll(ctx)
+ }
+ }
+}
+
+// unsnoozeAll unsnoozes all snoozed conversations.
+func (c *Manager) unsnoozeAll(ctx context.Context) {
+ res, err := c.q.UnsnoozeAll.ExecContext(ctx)
+ if err != nil {
+ c.lo.Error("error unsnoozing all conversations", err)
+ return
+ }
+ rows, _ := res.RowsAffected()
+ if rows > 0 {
+ c.lo.Info(fmt.Sprintf("unsnoozed %d conversations", rows))
+ }
+}
diff --git a/internal/conversation/ws.go b/internal/conversation/ws.go
index 3507060f..64ace23e 100644
--- a/internal/conversation/ws.go
+++ b/internal/conversation/ws.go
@@ -2,13 +2,12 @@ package conversation
import (
"encoding/json"
- "time"
- wsmodels "github.com/abhinavxd/artemis/internal/ws/models"
+ wsmodels "github.com/abhinavxd/libredesk/internal/ws/models"
)
-// BroadcastNewMessage broadcasts a new message to the conversation subscribers.
-func (m *Manager) BroadcastNewConversationMessage(conversationUUID, content, messageUUID, lastMessageAt, typ string, private bool) {
+// BroadcastNewMessage broadcasts a new message to all users.
+func (m *Manager) BroadcastNewMessage(conversationUUID, content, messageUUID, lastMessageAt, typ string, private bool) {
message := wsmodels.Message{
Type: wsmodels.MessageTypeNewMessage,
Data: map[string]interface{}{
@@ -20,42 +19,25 @@ func (m *Manager) BroadcastNewConversationMessage(conversationUUID, content, mes
"type": typ,
},
}
- m.broadcastToConversation(conversationUUID, message)
+ m.broadcastToUsers([]int{}, message)
}
-// BroadcastMessagePropUpdate broadcasts a message property update to the conversation subscribers.
-func (m *Manager) BroadcastMessagePropUpdate(conversationUUID, messageUUID, prop string, value any) {
+// BroadcastMessageUpdate broadcasts a message update to all users.
+func (m *Manager) BroadcastMessageUpdate(conversationUUID, messageUUID, prop string, value any) {
message := wsmodels.Message{
Type: wsmodels.MessageTypeMessagePropUpdate,
Data: map[string]interface{}{
- "uuid": messageUUID,
- "prop": prop,
- "value": value,
+ "conversation_uuid": conversationUUID,
+ "uuid": messageUUID,
+ "prop": prop,
+ "value": value,
},
}
- m.broadcastToConversation(conversationUUID, message)
+ m.broadcastToUsers([]int{}, message)
}
-// BroadcastNewConversation broadcasts a new conversation to the user.
-func (m *Manager) BroadcastNewConversation(userID int, conversationUUID, avatarURL, firstName, lastName, lastMessage, inboxName string, lastMessageAt time.Time, unreadMessageCount int) {
- message := wsmodels.Message{
- Type: wsmodels.MessageTypeNewConversation,
- Data: map[string]interface{}{
- "uuid": conversationUUID,
- "avatar_url": avatarURL,
- "first_name": firstName,
- "last_name": lastName,
- "last_message": lastMessage,
- "last_message_at": lastMessageAt.Format(time.RFC3339),
- "inbox_name": inboxName,
- "unread_message_count": unreadMessageCount,
- },
- }
- m.broadcastToUsers([]int{userID}, message)
-}
-
-// BroadcastConversationPropertyUpdate broadcasts a conversation property update to the conversation subscribers.
-func (m *Manager) BroadcastConversationPropertyUpdate(conversationUUID, prop string, value any) {
+// BroadcastConversationUpdate broadcasts a conversation update to all users.
+func (m *Manager) BroadcastConversationUpdate(conversationUUID, prop string, value any) {
message := wsmodels.Message{
Type: wsmodels.MessageTypeConversationPropertyUpdate,
Data: map[string]interface{}{
@@ -64,21 +46,14 @@ func (m *Manager) BroadcastConversationPropertyUpdate(conversationUUID, prop str
"value": value,
},
}
- m.broadcastToConversation(conversationUUID, message)
+ m.broadcastToUsers([]int{}, message)
}
-// broadcastToConversation broadcasts a message to the conversation subscribers.
-func (m *Manager) broadcastToConversation(conversationUUID string, message wsmodels.Message) {
- userIDs := m.wsHub.GetConversationSubscribers(conversationUUID)
- m.lo.Debug("broadcasting new message to conversation subscribers", "user_ids", userIDs, "conversation_uuid", conversationUUID, "message", message)
- m.broadcastToUsers(userIDs, message)
-}
-
-// broadcastToUsers broadcasts a websocket message to the passed user IDs.
+// broadcastToUsers broadcasts a message to a list of users, if the list is empty it broadcasts to all users.
func (m *Manager) broadcastToUsers(userIDs []int, message wsmodels.Message) {
messageBytes, err := json.Marshal(message)
if err != nil {
- m.lo.Error("error marshlling message", "error", err)
+ m.lo.Error("error marshalling WS message", "error", err)
return
}
m.wsHub.BroadcastMessage(wsmodels.BroadcastMessage{
diff --git a/internal/csat/csat.go b/internal/csat/csat.go
new file mode 100644
index 00000000..65338d49
--- /dev/null
+++ b/internal/csat/csat.go
@@ -0,0 +1,107 @@
+// Package csat contains the logic for managing CSAT.
+package csat
+
+import (
+ "database/sql"
+ "embed"
+ "errors"
+ "fmt"
+
+ "github.com/abhinavxd/libredesk/internal/csat/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/jmoiron/sqlx"
+ "github.com/zerodha/logf"
+)
+
+var (
+ //go:embed queries.sql
+ efs embed.FS
+ ErrCSATAlreadyExists = errors.New("CSAT already exists")
+)
+
+const (
+ csatURL = "%s/csat/%s"
+)
+
+// Manager manages CSAT.
+type Manager struct {
+ q queries
+ lo *logf.Logger
+}
+
+// Opts contains options for initializing the Manager.
+type Opts struct {
+ DB *sqlx.DB
+ Lo *logf.Logger
+}
+
+// queries contains prepared SQL queries.
+type queries struct {
+ Insert *sqlx.Stmt `query:"insert"`
+ Get *sqlx.Stmt `query:"get"`
+ Update *sqlx.Stmt `query:"update"`
+}
+
+// New creates and returns a new instance of the Manager.
+func New(opts Opts) (*Manager, error) {
+ var q queries
+ if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
+ return nil, err
+ }
+ return &Manager{
+ q: q,
+ lo: opts.Lo,
+ }, nil
+}
+
+// Create creates a new CSAT for the given conversation ID.
+func (m *Manager) Create(conversationID int) (models.CSATResponse, error) {
+ var (
+ uuid string
+ rsp models.CSATResponse
+ )
+ if err := m.q.Insert.QueryRow(conversationID).Scan(&uuid); err != nil {
+ m.lo.Error("error creating CSAT", "error", err)
+ return rsp, envelope.NewError(envelope.GeneralError, "Error creating CSAT survey", nil)
+ }
+ return m.Get(uuid)
+}
+
+// Get retrieves the CSAT for the given UUID.
+func (m *Manager) Get(uuid string) (models.CSATResponse, error) {
+ var csat models.CSATResponse
+ err := m.q.Get.Get(&csat, uuid)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ return csat, envelope.NewError(envelope.InputError, "CSAT not found", nil)
+ }
+ m.lo.Error("error getting CSAT", "error", err)
+ return csat, err
+ }
+ return csat, nil
+}
+
+// UpdateResponse updates the CSAT response for the given csat.
+func (m *Manager) UpdateResponse(uuid string, score int, feedback string) error {
+ csat, err := m.Get(uuid)
+ if err != nil {
+ return err
+ }
+
+ if csat.Score > 0 || !csat.ResponseTimestamp.IsZero() {
+ return envelope.NewError(envelope.InputError, "CSAT already submitted", nil)
+ }
+
+ _, err = m.q.Update.Exec(uuid, score, feedback)
+ if err != nil {
+ m.lo.Error("error updating CSAT", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error saving CSAT response", nil)
+ }
+ return nil
+}
+
+// MakePublicURL returns the public URL for the given CSAT UUID.
+func (m *Manager) MakePublicURL(appBaseURL, uuid string) string {
+ return fmt.Sprintf(csatURL, appBaseURL, uuid)
+}
diff --git a/internal/csat/models/models.go b/internal/csat/models/models.go
new file mode 100644
index 00000000..8b3addff
--- /dev/null
+++ b/internal/csat/models/models.go
@@ -0,0 +1,20 @@
+// package models has the models for the customer satisfaction survey responses.
+package models
+
+import (
+ "time"
+
+ "github.com/volatiletech/null/v9"
+)
+
+// CSATResponse represents a customer satisfaction survey response.
+type CSATResponse struct {
+ ID int `db:"id"`
+ UUID string `db:"uuid"`
+ CreatedAt time.Time `db:"created_at"`
+ UpdatedAt time.Time `db:"updated_at"`
+ ConversationID int `db:"conversation_id"`
+ Score int `db:"rating"`
+ Feedback null.String `db:"feedback"`
+ ResponseTimestamp null.Time `db:"response_timestamp"`
+}
diff --git a/internal/csat/queries.sql b/internal/csat/queries.sql
new file mode 100644
index 00000000..94e10104
--- /dev/null
+++ b/internal/csat/queries.sql
@@ -0,0 +1,25 @@
+-- name: insert
+INSERT INTO csat_responses (
+ conversation_id
+ )
+VALUES ($1)
+RETURNING uuid;
+
+-- name: get
+SELECT id,
+ uuid,
+ created_at,
+ updated_at,
+ conversation_id,
+ rating,
+ feedback,
+ response_timestamp
+FROM csat_responses
+WHERE uuid = $1;
+
+-- name: update
+UPDATE csat_responses
+SET rating = $2,
+ feedback = $3,
+ response_timestamp = NOW()
+WHERE uuid = $1;
diff --git a/internal/dbutil/builder.go b/internal/dbutil/builder.go
index 345523d0..a425b8f4 100644
--- a/internal/dbutil/builder.go
+++ b/internal/dbutil/builder.go
@@ -7,7 +7,7 @@ import (
"strings"
)
-// PaginationOptions represents the options for paginating a query
+// PaginationOptions represents the options for paginating a query.
type PaginationOptions struct {
Page int
PageSize int
@@ -15,12 +15,13 @@ type PaginationOptions struct {
Order string
}
+// Order directions.
const (
- ASC string = "ASC"
- DESC string = "DESC"
+ ASC = "ASC"
+ DESC = "DESC"
)
-// Filter represents a single filter condition
+// Filter represents a filter to be applied to a query.
type Filter struct {
Model string `json:"model"`
Field string `json:"field"`
@@ -28,107 +29,111 @@ type Filter struct {
Value string `json:"value"`
}
-// AllowedFields represents the allowed fields for each model
+// AllowedFields is a map of model names to a list of allowed fields for that model.
type AllowedFields map[string][]string
-// PaginateAndFilterQuery returns a paginated and filtered query with arguments
-func PaginateAndFilterQuery(baseQuery string, existingArgs []interface{}, opts PaginationOptions, filtersJSON string, allowedFields AllowedFields) (string, []interface{}, error) {
- // Parse filters
+// BuildPaginatedQuery builds a paginated query from the given base query, existing arguments, pagination options, filters JSON, and allowed fields.
+func BuildPaginatedQuery(baseQuery string, existingArgs []interface{}, opts PaginationOptions, filtersJSON string, allowedFields AllowedFields) (string, []interface{}, error) {
+ if opts.Page <= 0 {
+ return "", nil, fmt.Errorf("invalid page number: %d", opts.Page)
+ }
+ if opts.PageSize <= 0 {
+ return "", nil, fmt.Errorf("invalid page size: %d", opts.PageSize)
+ }
+
var filters []Filter
if filtersJSON != "" {
if err := json.Unmarshal([]byte(filtersJSON), &filters); err != nil {
- return "", nil, fmt.Errorf("invalid filters JSON: %v", err)
+ return "", nil, fmt.Errorf("invalid filters JSON: %w", err)
}
}
- // Apply filters
- query, args, err := applyFilters(baseQuery, existingArgs, filters, allowedFields)
+ whereClause, filterArgs, err := buildWhereClause(filters, existingArgs, allowedFields)
if err != nil {
return "", nil, err
}
- // Calculate offset
- offset := (opts.Page - 1) * opts.PageSize
+ query := baseQuery
+ args := existingArgs
- // Prepare the order by clause
- var orderByClause string
- if opts.OrderBy != "" {
- orderByClause = fmt.Sprintf("ORDER BY %s", opts.OrderBy)
- if opts.Order != "" {
- switch strings.ToUpper(opts.Order) {
- case ASC, DESC:
- orderByClause += " " + strings.ToUpper(opts.Order)
- default:
- return "", nil, fmt.Errorf("invalid order direction: %s", opts.Order)
- }
- }
+ if whereClause != "" {
+ query += " AND " + whereClause
+ args = append(args, filterArgs...)
}
- // Append pagination to the query
- query = fmt.Sprintf("%s %s LIMIT $%d OFFSET $%d",
- query,
- orderByClause,
- len(args)+1,
- len(args)+2,
- )
+ if opts.OrderBy != "" {
+ order := strings.ToUpper(opts.Order)
+ if order != "" && order != ASC && order != DESC {
+ return "", nil, fmt.Errorf("invalid order direction: %s", opts.Order)
+ }
+ query += fmt.Sprintf(" ORDER BY %s %s NULLS LAST", opts.OrderBy, order)
+ }
- // Append pagination arguments
+ offset := (opts.Page - 1) * opts.PageSize
+ query += fmt.Sprintf(" LIMIT $%d OFFSET $%d", len(args)+1, len(args)+2)
args = append(args, opts.PageSize, offset)
return query, args, nil
}
-// applyFilters applies passed filters to the based query.
-func applyFilters(baseQuery string, existingArgs []interface{}, filters []Filter, allowedFields AllowedFields) (string, []interface{}, error) {
- var conditions []string
- args := make([]interface{}, len(existingArgs))
- copy(args, existingArgs)
+// buildWhereClause builds a WHERE clause from the given filters and returns the WHERE clause and the arguments to be passed to the query.
+func buildWhereClause(filters []Filter, existingArgs []interface{}, allowedFields AllowedFields) (string, []interface{}, error) {
+ conditions := []string{}
+ args := []interface{}{}
+ paramCount := len(existingArgs) + 1
- operatorMap := map[string]string{
- "=": "=",
- "!=": "!=",
- ">": ">",
- "<": "<",
- ">=": ">=",
- "<=": "<=",
- }
-
- // Build the conditions
- for _, filter := range filters {
- modelFields, ok := allowedFields[filter.Model]
+ for _, f := range filters {
+ modelFields, ok := allowedFields[f.Model]
if !ok {
- return "", nil, fmt.Errorf("invalid model in filter: %s", filter.Model)
+ return "", nil, fmt.Errorf("invalid model: %s", f.Model)
}
- if !slices.Contains(modelFields, filter.Field) {
- return "", nil, fmt.Errorf("invalid field in filter: %s for model: %s", filter.Field, filter.Model)
- }
- op, ok := operatorMap[filter.Operator]
- if !ok {
- return "", nil, fmt.Errorf("invalid operator: %s", filter.Operator)
+ if !slices.Contains(modelFields, f.Field) {
+ return "", nil, fmt.Errorf("invalid field: %s for model: %s", f.Field, f.Model)
}
- var condition string
- if op == "!=" {
- // For != operator, include NULL values using OR IS NULL
- condition = fmt.Sprintf("(%s.%s %s $%d OR %s.%s IS NULL)",
- filter.Model, filter.Field, op, len(args)+1,
- filter.Model, filter.Field)
- } else {
- condition = fmt.Sprintf("%s.%s %s $%d",
- filter.Model, filter.Field, op, len(args)+1)
- }
+ field := fmt.Sprintf("%s.%s", f.Model, f.Field)
- conditions = append(conditions, condition)
- args = append(args, filter.Value)
- }
-
- if len(conditions) > 0 {
- if strings.Contains(baseQuery, "WHERE") {
- baseQuery += " AND " + strings.Join(conditions, " AND ")
- } else {
- baseQuery += " WHERE " + strings.Join(conditions, " AND ")
+ switch f.Operator {
+ case "equals":
+ conditions = append(conditions, field+fmt.Sprintf(" = $%d", paramCount))
+ args = append(args, f.Value)
+ paramCount++
+ case "not equals":
+ conditions = append(conditions, field+fmt.Sprintf(" != $%d", paramCount))
+ args = append(args, f.Value)
+ paramCount++
+ case "set":
+ conditions = append(conditions, field+" IS NOT NULL")
+ case "not set":
+ conditions = append(conditions, field+" IS NULL")
+ case "in":
+ var arr []string
+ if err := json.Unmarshal([]byte(f.Value), &arr); err != nil {
+ return "", nil, fmt.Errorf("invalid array format for 'in' operator: %v", err)
+ }
+ placeholders := make([]string, len(arr))
+ for i, v := range arr {
+ placeholders[i] = fmt.Sprintf("$%d", paramCount)
+ args = append(args, v)
+ paramCount++
+ }
+ conditions = append(conditions, field+" IN ("+strings.Join(placeholders, ",")+")")
+ case "between":
+ values := strings.Split(f.Value, ",")
+ if len(values) != 2 {
+ return "", nil, fmt.Errorf("between requires 2 values")
+ }
+ conditions = append(conditions, fmt.Sprintf("%s BETWEEN $%d AND $%d", field, paramCount, paramCount+1))
+ args = append(args, strings.TrimSpace(values[0]), strings.TrimSpace(values[1]))
+ paramCount += 2
+ default:
+ return "", nil, fmt.Errorf("invalid operator: %s", f.Operator)
}
}
- return baseQuery, args, nil
+ if len(conditions) == 0 {
+ return "", nil, nil
+ }
+
+ return strings.Join(conditions, " AND "), args, nil
}
diff --git a/internal/dbutil/dbutil.go b/internal/dbutil/dbutil.go
index 9f7f1fea..7a825723 100644
--- a/internal/dbutil/dbutil.go
+++ b/internal/dbutil/dbutil.go
@@ -12,3 +12,14 @@ func IsForeignKeyError(err error) bool {
}
return false
}
+
+// IsUniqueViolationError checks if the given error is a PostgreSQL unique violation (error code 23505)
+func IsUniqueViolationError(err error) bool {
+ if err == nil {
+ return false
+ }
+ if pqErr, ok := err.(*pq.Error); ok {
+ return pqErr.Code == "23505"
+ }
+ return false
+}
diff --git a/internal/dbutil/scanner.go b/internal/dbutil/scanner.go
index 573df83f..f9d731bb 100644
--- a/internal/dbutil/scanner.go
+++ b/internal/dbutil/scanner.go
@@ -2,7 +2,6 @@
package dbutil
import (
- "errors"
"io/fs"
"github.com/jmoiron/sqlx"
@@ -10,11 +9,6 @@ import (
goyesqlx "github.com/knadh/goyesql/v2/sqlx"
)
-var (
- // ErrUniqueViolation indicates a unique constraint violation.
- ErrUniqueViolation = errors.New("unique constraint violation")
-)
-
// ScanSQLFile scans a goyesql .sql file from the given fs and prepares the queries in the given struct.
func ScanSQLFile(path string, o interface{}, db *sqlx.DB, f fs.FS) error {
// Read the SQL file from the embedded filesystem.
diff --git a/internal/image/image.go b/internal/image/image.go
index 6a9102c8..ddb9f878 100644
--- a/internal/image/image.go
+++ b/internal/image/image.go
@@ -10,7 +10,8 @@ import (
)
var (
- Exts = []string{"gif", "png", "jpg", "jpeg"}
+ Exts = []string{"gif", "png", "jpg", "jpeg"}
+ DefThumbSize = 150
)
// GetDimensions returns the width and height of the image in the provided file.
diff --git a/internal/inbox/channel/email/email.go b/internal/inbox/channel/email/email.go
index de40fe70..f603e6e8 100644
--- a/internal/inbox/channel/email/email.go
+++ b/internal/inbox/channel/email/email.go
@@ -5,7 +5,7 @@ import (
"context"
"sync"
- "github.com/abhinavxd/artemis/internal/inbox"
+ "github.com/abhinavxd/libredesk/internal/inbox"
"github.com/knadh/smtppool"
"github.com/zerodha/logf"
)
diff --git a/internal/inbox/channel/email/imap.go b/internal/inbox/channel/email/imap.go
index 12595476..d47e5e86 100644
--- a/internal/inbox/channel/email/imap.go
+++ b/internal/inbox/channel/email/imap.go
@@ -2,14 +2,16 @@ package email
import (
"context"
+ "encoding/json"
"fmt"
"strings"
"time"
- "github.com/abhinavxd/artemis/internal/attachment"
- cmodels "github.com/abhinavxd/artemis/internal/contact/models"
- "github.com/abhinavxd/artemis/internal/conversation"
- "github.com/abhinavxd/artemis/internal/conversation/models"
+ "github.com/abhinavxd/libredesk/internal/attachment"
+ "github.com/abhinavxd/libredesk/internal/conversation"
+ "github.com/abhinavxd/libredesk/internal/conversation/models"
+ "github.com/abhinavxd/libredesk/internal/user"
+ umodels "github.com/abhinavxd/libredesk/internal/user/models"
"github.com/emersion/go-imap/v2"
"github.com/emersion/go-imap/v2/imapclient"
"github.com/jhillyerd/enmime"
@@ -36,16 +38,17 @@ func (e *Email) ReadIncomingMessages(ctx context.Context, cfg IMAPConfig) error
case <-ctx.Done():
return nil
case <-readTicker.C:
- if err := e.processMailbox(cfg); err != nil {
+ e.lo.Debug("processing emails from mailbox", "mailbox", cfg.Mailbox, "inbox_id", e.Identifier())
+ if err := e.processMailbox(ctx, cfg); err != nil && err != context.Canceled {
e.lo.Error("error processing mailbox", "error", err)
}
+ e.lo.Debug("finished processing emails from mailbox", "mailbox", cfg.Mailbox, "inbox_id", e.Identifier())
}
}
}
// processMailbox processes emails in the specified mailbox.
-func (e *Email) processMailbox(cfg IMAPConfig) error {
- e.lo.Debug("processing emails from mailbox", "mailbox", cfg.Mailbox, "inbox_id", e.Identifier())
+func (e *Email) processMailbox(ctx context.Context, cfg IMAPConfig) error {
client, err := imapclient.DialTLS(cfg.Host+":"+fmt.Sprint(cfg.Port), &imapclient.Options{})
if err != nil {
return fmt.Errorf("error connecting to IMAP server: %w", err)
@@ -60,14 +63,15 @@ func (e *Email) processMailbox(cfg IMAPConfig) error {
return fmt.Errorf("error selecting mailbox: %w", err)
}
- since := time.Now().Add(-12 * time.Hour)
+ // TODO: Set value from config.
+ since := time.Now().Add(-24 * time.Hour)
searchData, err := e.searchMessages(client, since)
if err != nil {
return fmt.Errorf("error searching messages: %w", err)
}
- return e.fetchAndProcessMessages(client, searchData, e.Identifier())
+ return e.fetchAndProcessMessages(ctx, client, searchData, e.Identifier())
}
// searchMessages searches for messages in the specified time range.
@@ -86,11 +90,11 @@ func (e *Email) searchMessages(client *imapclient.Client, since time.Time) (*ima
}
// fetchAndProcessMessages fetches and processes messages based on the search results.
-func (e *Email) fetchAndProcessMessages(client *imapclient.Client, searchData *imap.SearchData, inboxID int) error {
+func (e *Email) fetchAndProcessMessages(ctx context.Context, client *imapclient.Client, searchData *imap.SearchData, inboxID int) error {
seqSet := imap.SeqSet{}
seqSet.AddRange(searchData.Min, searchData.Max)
- // Fetch only envelope.
+ // Fetch only envelope, body is fetch later.
fetchOptions := &imap.FetchOptions{
Envelope: true,
}
@@ -98,25 +102,48 @@ func (e *Email) fetchAndProcessMessages(client *imapclient.Client, searchData *i
fetchCmd := client.Fetch(seqSet, fetchOptions)
for {
- msg := fetchCmd.Next()
- if msg == nil {
- break
+ // Check for context cancellation before fetching the next message.
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ default:
}
- for fetchItem := msg.Next(); fetchItem != nil; fetchItem = msg.Next() {
+ // Fetch the next message.
+ msg := fetchCmd.Next()
+ if msg == nil {
+ // No more messages to process.
+ return nil
+ }
+
+ // Process message envelope.
+ for {
+ // Check for context cancellation before processing the next item.
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ default:
+ }
+
+ // Fetch the next item in the message.
+ fetchItem := msg.Next()
+ if fetchItem == nil {
+ // No message items left to process.
+ break
+ }
+
+ // Process the envelope item.
if item, ok := fetchItem.(imapclient.FetchItemDataEnvelope); ok {
- if err := e.processEnvelope(client, item.Envelope, msg.SeqNum, inboxID); err != nil {
+ if err := e.processEnvelope(ctx, client, item.Envelope, msg.SeqNum, inboxID); err != nil && err != context.Canceled {
e.lo.Error("error processing envelope", "error", err)
}
}
}
}
-
- return nil
}
// processEnvelope processes an email envelope.
-func (e *Email) processEnvelope(client *imapclient.Client, env *imap.Envelope, seqNum uint32, inboxID int) error {
+func (e *Email) processEnvelope(ctx context.Context, client *imapclient.Client, env *imap.Envelope, seqNum uint32, inboxID int) error {
if len(env.From) == 0 {
e.lo.Warn("no sender received for email", "message_id", env.MessageID)
return nil
@@ -125,24 +152,41 @@ func (e *Email) processEnvelope(client *imapclient.Client, env *imap.Envelope, s
exists, err := e.messageStore.MessageExists(env.MessageID)
if err != nil {
e.lo.Error("error checking if message exists", "message_id", env.MessageID)
- return err
+ return fmt.Errorf("checking if message exists in DB: %w", err)
}
if exists {
- e.lo.Debug("message already exists", "message_id", env.MessageID)
return nil
}
e.lo.Debug("message does not exist", "message_id", env.MessageID)
- var contact = cmodels.Contact{
- Source: e.Channel(),
- SourceID: env.From[0].Addr(),
- Email: env.From[0].Addr(),
- InboxID: inboxID,
+ // Make contact.
+ firstName, lastName := getContactName(env.From[0])
+ var contact = umodels.User{
+ InboxID: inboxID,
+ FirstName: firstName,
+ LastName: lastName,
+ SourceChannel: null.NewString(e.Channel(), true),
+ SourceChannelID: null.NewString(env.From[0].Addr(), true),
+ Email: null.NewString(env.From[0].Addr(), true),
+ Type: user.UserTypeContact,
}
- contact.FirstName, contact.LastName = getContactName(env.From[0])
+ // Set CC addresses in meta.
+ var ccAddr = make([]string, 0, len(env.Cc))
+ for _, cc := range env.Cc {
+ if cc.Addr() != "" {
+ ccAddr = append(ccAddr, cc.Addr())
+ }
+ }
+ meta, err := json.Marshal(map[string]interface{}{
+ "cc": ccAddr,
+ })
+ if err != nil {
+ e.lo.Error("error marshalling meta", "error", err)
+ return fmt.Errorf("marshalling meta: %w", err)
+ }
incomingMsg := models.IncomingMessage{
Message: models.Message{
Channel: e.Channel(),
@@ -152,6 +196,7 @@ func (e *Email) processEnvelope(client *imapclient.Client, env *imap.Envelope, s
Status: conversation.MessageStatusReceived,
Subject: env.Subject,
SourceID: null.StringFrom(env.MessageID),
+ Meta: string(meta),
},
Contact: contact,
InboxID: inboxID,
@@ -169,14 +214,25 @@ func (e *Email) processEnvelope(client *imapclient.Client, env *imap.Envelope, s
return nil
}
- for fullFetchItem := fullMsg.Next(); fullFetchItem != nil; fullFetchItem = fullMsg.Next() {
+ // Fetch full message.
+ for {
+ // Check for context cancellation before processing the next item.
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ default:
+ }
+
+ fullFetchItem := fullMsg.Next()
+ if fullFetchItem == nil {
+ return nil
+ }
+
if fullItem, ok := fullFetchItem.(imapclient.FetchItemDataBodySection); ok {
e.lo.Debug("fetching full message body", "message_id", env.MessageID)
return e.processFullMessage(fullItem, incomingMsg)
}
}
-
- return nil
}
// processFullMessage processes the full email message.
@@ -195,6 +251,7 @@ func (e *Email) processFullMessage(item imapclient.FetchItemDataBodySection, inc
incomingMsg.Message.ContentType = conversation.ContentTypeText
}
+ // Remove the angle brackets from the In-Reply-To and References headers.
inReplyTo := strings.ReplaceAll(strings.ReplaceAll(envelope.GetHeader("In-Reply-To"), "<", ""), ">", "")
references := strings.Fields(envelope.GetHeader("References"))
for i, ref := range references {
@@ -209,6 +266,7 @@ func (e *Email) processFullMessage(item imapclient.FetchItemDataBodySection, inc
Name: att.FileName,
Content: att.Content,
ContentType: att.ContentType,
+ ContentID: att.ContentID,
Size: len(att.Content),
Disposition: attachment.DispositionAttachment,
})
@@ -223,7 +281,7 @@ func (e *Email) processFullMessage(item imapclient.FetchItemDataBodySection, inc
Disposition: attachment.DispositionInline,
})
}
- e.lo.Debug("enqueuing message", "message_id", incomingMsg.Message.SourceID, "attachments", len(envelope.Attachments), "inlines", len(envelope.Inlines))
+ e.lo.Debug("enqueuing incoming email message for inserting in DB", "message_id", incomingMsg.Message.SourceID.String, "attachments", len(envelope.Attachments), "inlines", len(envelope.Inlines))
if err := e.messageStore.EnqueueIncoming(incomingMsg); err != nil {
return err
}
diff --git a/internal/inbox/channel/email/smtp.go b/internal/inbox/channel/email/smtp.go
index 4795d0f1..8ced84a7 100644
--- a/internal/inbox/channel/email/smtp.go
+++ b/internal/inbox/channel/email/smtp.go
@@ -7,7 +7,7 @@ import (
"net/smtp"
"net/textproto"
- "github.com/abhinavxd/artemis/internal/conversation/models"
+ "github.com/abhinavxd/libredesk/internal/conversation/models"
"github.com/knadh/smtppool"
)
@@ -95,6 +95,8 @@ func (e *Email) Send(m models.Message) error {
email := smtppool.Email{
From: m.From,
To: m.To,
+ Cc: m.CC,
+ Bcc: m.BCC,
Subject: m.Subject,
Attachments: attachments,
Headers: textproto.MIMEHeader{},
diff --git a/internal/inbox/inbox.go b/internal/inbox/inbox.go
index 3f6750f7..d8f01f6a 100644
--- a/internal/inbox/inbox.go
+++ b/internal/inbox/inbox.go
@@ -9,10 +9,10 @@ import (
"fmt"
"sync"
- "github.com/abhinavxd/artemis/internal/conversation/models"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- imodels "github.com/abhinavxd/artemis/internal/inbox/models"
+ "github.com/abhinavxd/libredesk/internal/conversation/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ imodels "github.com/abhinavxd/libredesk/internal/inbox/models"
"github.com/jmoiron/sqlx"
"github.com/zerodha/logf"
)
@@ -82,7 +82,7 @@ type Manager struct {
// Prepared queries.
type queries struct {
- GetByID *sqlx.Stmt `query:"get-by-id"`
+ GetInbox *sqlx.Stmt `query:"get-inbox"`
GetActive *sqlx.Stmt `query:"get-active-inboxes"`
GetAll *sqlx.Stmt `query:"get-all-inboxes"`
Update *sqlx.Stmt `query:"update"`
@@ -119,11 +119,10 @@ func (m *Manager) Register(i Inbox) {
m.inboxes[i.Identifier()] = i
}
-// Get returns the inbox with the given ID.
+// Get retrieves the initialized inbox instance with the specified ID from memory.
func (m *Manager) Get(id int) (Inbox, error) {
m.mu.RLock()
defer m.mu.RUnlock()
-
i, ok := m.inboxes[id]
if !ok {
return nil, ErrInboxNotFound
@@ -131,10 +130,10 @@ func (m *Manager) Get(id int) (Inbox, error) {
return i, nil
}
-// GetByID returns an inbox from the DB by the given ID.
-func (m *Manager) GetByID(id int) (imodels.Inbox, error) {
+// GetDBRecord returns the inbox record from the DB.
+func (m *Manager) GetDBRecord(id int) (imodels.Inbox, error) {
var inbox imodels.Inbox
- if err := m.queries.GetByID.Get(&inbox, id); err != nil {
+ if err := m.queries.GetInbox.Get(&inbox, id); err != nil {
m.lo.Error("error fetching inbox", "error", err)
return inbox, envelope.NewError(envelope.GeneralError, "Error fetching inbox", nil)
}
@@ -163,7 +162,7 @@ func (m *Manager) GetAll() ([]imodels.Inbox, error) {
// Create creates an inbox in the DB.
func (m *Manager) Create(inbox imodels.Inbox) error {
- if _, err := m.queries.InsertInbox.Exec(inbox.Channel, inbox.Config, inbox.Name, inbox.From); err != nil {
+ if _, err := m.queries.InsertInbox.Exec(inbox.Channel, inbox.Config, inbox.Name, inbox.From, inbox.CSATEnabled); err != nil {
m.lo.Error("error creating inbox", "error", err)
return envelope.NewError(envelope.GeneralError, "Error creating inbox", nil)
}
@@ -195,7 +194,7 @@ func (m *Manager) InitInboxes(initFn initFn) error {
return nil
}
-// Reload reloads inboxes with the provided initialization function.
+// Reload hot reloads the inboxes with the given init function.
func (m *Manager) Reload(ctx context.Context, initFn initFn) error {
m.mu.Lock()
defer m.mu.Unlock()
@@ -248,7 +247,7 @@ func (m *Manager) Reload(ctx context.Context, initFn initFn) error {
// Update updates an inbox in the DB.
func (m *Manager) Update(id int, inbox imodels.Inbox) error {
- current, err := m.GetByID(id)
+ current, err := m.GetDBRecord(id)
if err != nil {
return err
}
@@ -301,7 +300,7 @@ func (m *Manager) Update(id int, inbox imodels.Inbox) error {
inbox.Config = updatedConfig
}
- if _, err := m.queries.Update.Exec(id, inbox.Channel, inbox.Config, inbox.Name, inbox.From); err != nil {
+ if _, err := m.queries.Update.Exec(id, inbox.Channel, inbox.Config, inbox.Name, inbox.From, inbox.CSATEnabled, inbox.Enabled); err != nil {
m.lo.Error("error updating inbox", "error", err)
return envelope.NewError(envelope.GeneralError, "Error updating inbox", nil)
}
diff --git a/internal/inbox/models/models.go b/internal/inbox/models/models.go
index 0db70c2a..59670d9b 100644
--- a/internal/inbox/models/models.go
+++ b/internal/inbox/models/models.go
@@ -5,54 +5,55 @@ import (
"strings"
"time"
- "github.com/abhinavxd/artemis/internal/stringutil"
+ "github.com/abhinavxd/libredesk/internal/stringutil"
)
// Inbox represents a inbox record in DB.
type Inbox struct {
- ID int `db:"id" json:"id"`
- CreatedAt time.Time `db:"created_at" json:"created_at"`
- UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
- Name string `db:"name" json:"name"`
- Channel string `db:"channel" json:"channel"`
- Disabled bool `db:"disabled" json:"disabled"`
- From string `db:"from" json:"from"`
- Config json.RawMessage `db:"config" json:"config"`
+ ID int `db:"id" json:"id"`
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+ Name string `db:"name" json:"name"`
+ Channel string `db:"channel" json:"channel"`
+ Enabled bool `db:"enabled" json:"enabled"`
+ CSATEnabled bool `db:"csat_enabled" json:"csat_enabled"`
+ From string `db:"from" json:"from"`
+ Config json.RawMessage `db:"config" json:"config"`
}
// ClearPasswords masks all config passwords
func (m *Inbox) ClearPasswords() error {
- switch m.Channel {
- case "email":
- var cfg struct {
- IMAP []map[string]interface{} `json:"imap"`
- SMTP []map[string]interface{} `json:"smtp"`
- }
-
- if err := json.Unmarshal(m.Config, &cfg); err != nil {
- return err
- }
-
- dummyPassword := strings.Repeat(stringutil.PasswordDummy, 10)
-
- for i := range cfg.IMAP {
- cfg.IMAP[i]["password"] = dummyPassword
- }
-
- for i := range cfg.SMTP {
- cfg.SMTP[i]["password"] = dummyPassword
- }
-
- clearedConfig, err := json.Marshal(cfg)
- if err != nil {
- return err
- }
-
- m.Config = clearedConfig
-
- default:
- return nil
- }
-
- return nil
-}
\ No newline at end of file
+ switch m.Channel {
+ case "email":
+ var cfg struct {
+ IMAP []map[string]interface{} `json:"imap"`
+ SMTP []map[string]interface{} `json:"smtp"`
+ }
+
+ if err := json.Unmarshal(m.Config, &cfg); err != nil {
+ return err
+ }
+
+ dummyPassword := strings.Repeat(stringutil.PasswordDummy, 10)
+
+ for i := range cfg.IMAP {
+ cfg.IMAP[i]["password"] = dummyPassword
+ }
+
+ for i := range cfg.SMTP {
+ cfg.SMTP[i]["password"] = dummyPassword
+ }
+
+ clearedConfig, err := json.Marshal(cfg)
+ if err != nil {
+ return err
+ }
+
+ m.Config = clearedConfig
+
+ default:
+ return nil
+ }
+
+ return nil
+}
diff --git a/internal/inbox/queries.sql b/internal/inbox/queries.sql
index b68a583d..0cc195e9 100644
--- a/internal/inbox/queries.sql
+++ b/internal/inbox/queries.sql
@@ -1,20 +1,20 @@
-- name: get-active-inboxes
-SELECT * from inboxes where disabled is NOT TRUE and deleted_at is NULL;
+SELECT * from inboxes where enabled is TRUE and deleted_at is NULL;
-- name: get-all-inboxes
-SELECT id, name, channel, disabled, updated_at from inboxes where deleted_at is NULL;
+SELECT id, created_at, updated_at, name, channel, enabled from inboxes where deleted_at is NULL;
-- name: insert-inbox
INSERT INTO inboxes
-(channel, config, "name", "from")
-VALUES($1, $2, $3, $4);
+(channel, config, "name", "from", csat_enabled)
+VALUES($1, $2, $3, $4, $5)
--- name: get-by-id
+-- name: get-inbox
SELECT * from inboxes where id = $1 and deleted_at is NULL;
-- name: update
UPDATE inboxes
-set channel = $2, config = $3, "name" = $4, "from" = $5, updated_at = now()
+set channel = $2, config = $3, "name" = $4, "from" = $5, csat_enabled = $6, enabled = $7, updated_at = now()
where id = $1 and deleted_at is NULL;
-- name: soft-delete
@@ -22,5 +22,5 @@ UPDATE inboxes set deleted_at = now(), config = '{}' where id = $1 and deleted_a
-- name: toggle
UPDATE inboxes
-SET disabled = NOT disabled, updated_at = NOW()
+SET enabled = NOT enabled, updated_at = NOW()
WHERE id = $1;
\ No newline at end of file
diff --git a/internal/macro/macro.go b/internal/macro/macro.go
new file mode 100644
index 00000000..fd77104d
--- /dev/null
+++ b/internal/macro/macro.go
@@ -0,0 +1,117 @@
+// Package macro provides functionality for managing templated text responses and actions.
+package macro
+
+import (
+ "embed"
+ "encoding/json"
+
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/macro/models"
+ "github.com/jmoiron/sqlx"
+ "github.com/zerodha/logf"
+)
+
+var (
+ //go:embed queries.sql
+ efs embed.FS
+)
+
+// Manager is the macro manager.
+type Manager struct {
+ q queries
+ lo *logf.Logger
+}
+
+// Predefined queries.
+type queries struct {
+ Get *sqlx.Stmt `query:"get"`
+ GetAll *sqlx.Stmt `query:"get-all"`
+ Create *sqlx.Stmt `query:"create"`
+ Update *sqlx.Stmt `query:"update"`
+ Delete *sqlx.Stmt `query:"delete"`
+ IncUsageCount *sqlx.Stmt `query:"increment-usage-count"`
+}
+
+// Opts contains the dependencies for the macro manager.
+type Opts struct {
+ DB *sqlx.DB
+ Lo *logf.Logger
+}
+
+// New initializes a macro manager.
+func New(opts Opts) (*Manager, error) {
+ var q queries
+ err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs)
+ if err != nil {
+ return nil, err
+ }
+ return &Manager{q: q, lo: opts.Lo}, nil
+}
+
+// Get returns a macro by ID.
+func (m *Manager) Get(id int) (models.Macro, error) {
+ macro := models.Macro{}
+ err := m.q.Get.Get(¯o, id)
+ if err != nil {
+ m.lo.Error("error getting macro", "error", err)
+ return macro, envelope.NewError(envelope.GeneralError, "Error getting macro", nil)
+ }
+ return macro, nil
+}
+
+// Create adds a new macro.
+func (m *Manager) Create(name, messageContent string, userID, teamID *int, visibility string, actions json.RawMessage) error {
+ _, err := m.q.Create.Exec(name, messageContent, userID, teamID, visibility, actions)
+ if err != nil {
+ m.lo.Error("error creating macro", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error creating macro", nil)
+ }
+ return nil
+}
+
+// Update modifies an existing macro.
+func (m *Manager) Update(id int, name, messageContent string, userID, teamID *int, visibility string, actions json.RawMessage) error {
+ result, err := m.q.Update.Exec(id, name, messageContent, userID, teamID, visibility, actions)
+ if err != nil {
+ m.lo.Error("error updating macro", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error updating macro", nil)
+ }
+ if rows, _ := result.RowsAffected(); rows == 0 {
+ return envelope.NewError(envelope.NotFoundError, "Macro not found", nil)
+ }
+ return nil
+}
+
+// GetAll returns all macros.
+func (m *Manager) GetAll() ([]models.Macro, error) {
+ macros := make([]models.Macro, 0)
+ err := m.q.GetAll.Select(¯os)
+ if err != nil {
+ m.lo.Error("error fetching macros", "error", err)
+ return nil, envelope.NewError(envelope.GeneralError, "Error fetching macros", nil)
+ }
+ return macros, nil
+}
+
+// Delete deletes a macro by ID.
+func (m *Manager) Delete(id int) error {
+ result, err := m.q.Delete.Exec(id)
+ if err != nil {
+ m.lo.Error("error deleting macro", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error deleting macro", nil)
+ }
+ if rows, _ := result.RowsAffected(); rows == 0 {
+ return envelope.NewError(envelope.NotFoundError, "Macro not found", nil)
+ }
+ return nil
+}
+
+// IncrementUsageCount increments the usage count of a macro.
+func (m *Manager) IncrementUsageCount(id int) error {
+ if _, err := m.q.IncUsageCount.Exec(id); err != nil {
+ m.lo.Error("error incrementing usage count", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error incrementing macro usage count", nil)
+ }
+ return nil
+}
diff --git a/internal/macro/models/models.go b/internal/macro/models/models.go
new file mode 100644
index 00000000..1ed30aad
--- /dev/null
+++ b/internal/macro/models/models.go
@@ -0,0 +1,19 @@
+package models
+
+import (
+ "encoding/json"
+ "time"
+)
+
+type Macro struct {
+ ID int `db:"id" json:"id"`
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+ Name string `db:"name" json:"name"`
+ MessageContent string `db:"message_content" json:"message_content"`
+ Visibility string `db:"visibility" json:"visibility"`
+ UserID *int `db:"user_id" json:"user_id,string"`
+ TeamID *int `db:"team_id" json:"team_id,string"`
+ UsageCount int `db:"usage_count" json:"usage_count"`
+ Actions json.RawMessage `db:"actions" json:"actions"`
+}
diff --git a/internal/macro/queries.sql b/internal/macro/queries.sql
new file mode 100644
index 00000000..80dd1f31
--- /dev/null
+++ b/internal/macro/queries.sql
@@ -0,0 +1,67 @@
+-- name: get
+SELECT
+ id,
+ name,
+ message_content,
+ created_at,
+ updated_at,
+ visibility,
+ user_id,
+ team_id,
+ actions,
+ usage_count
+FROM
+ macros
+WHERE
+ id = $1;
+
+-- name: get-all
+SELECT
+ id,
+ name,
+ message_content,
+ created_at,
+ updated_at,
+ visibility,
+ user_id,
+ team_id,
+ actions,
+ usage_count
+FROM
+ macros
+ORDER BY
+ updated_at DESC;
+
+-- name: create
+INSERT INTO
+ macros (name, message_content, user_id, team_id, visibility, actions)
+VALUES
+ ($1, $2, $3, $4, $5, $6);
+
+-- name: update
+UPDATE
+ macros
+SET
+ name = $2,
+ message_content = $3,
+ user_id = $4,
+ team_id = $5,
+ visibility = $6,
+ actions = $7,
+ updated_at = NOW()
+WHERE
+ id = $1;
+
+-- name: delete
+DELETE FROM
+ macros
+WHERE
+ id = $1;
+
+-- name: increment-usage-count
+UPDATE
+ macros
+SET
+ usage_count = usage_count + 1
+WHERE
+ id = $1;
\ No newline at end of file
diff --git a/internal/media/media.go b/internal/media/media.go
index fe74a9ea..ee66ca15 100644
--- a/internal/media/media.go
+++ b/internal/media/media.go
@@ -10,11 +10,12 @@ import (
"io"
"time"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/abhinavxd/artemis/internal/media/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/media/models"
"github.com/google/uuid"
"github.com/jmoiron/sqlx"
+ "github.com/volatiletech/null/v9"
"github.com/zerodha/logf"
)
@@ -72,14 +73,14 @@ type queries struct {
}
// UploadAndInsert uploads file on storage and inserts an entry in db.
-func (m *Manager) UploadAndInsert(srcFilename, contentType, contentID, modelType string, modelID int, content io.ReadSeeker, fileSize int, disposition string, meta []byte) (models.Media, error) {
+func (m *Manager) UploadAndInsert(srcFilename, contentType, contentID string, modelType null.String, modelID null.Int, content io.ReadSeeker, fileSize int, disposition null.String, meta []byte) (models.Media, error) {
var uuid = uuid.New()
_, err := m.Upload(uuid.String(), contentType, content)
if err != nil {
return models.Media{}, err
}
- media, err := m.Insert(srcFilename, contentType, contentID, modelType, disposition, uuid.String(), modelID, fileSize, meta)
+ media, err := m.Insert(disposition, srcFilename, contentType, contentID, modelType, uuid.String(), modelID, fileSize, meta)
if err != nil {
m.store.Delete(uuid.String())
return models.Media{}, err
@@ -98,7 +99,7 @@ func (m *Manager) Upload(fileName, contentType string, content io.ReadSeeker) (s
}
// Insert inserts media details into the database and returns the inserted media record.
-func (m *Manager) Insert(fileName, contentType, contentID, modelType, disposition, uuid string, modelID int, fileSize int, meta []byte) (models.Media, error) {
+func (m *Manager) Insert(disposition null.String, fileName, contentType, contentID string, modelType null.String, uuid string, modelID null.Int, fileSize int, meta []byte) (models.Media, error) {
var id int
if err := m.queries.Insert.QueryRow(m.store.Name(), fileName, contentType, fileSize, meta, modelID, modelType, disposition, contentID, uuid).Scan(&id); err != nil {
m.lo.Error("error inserting media", "error", err)
@@ -154,8 +155,8 @@ func (m *Manager) GetURL(name string) string {
// Attach associates a media file with a specific model by its ID and model name.
func (m *Manager) Attach(id int, model string, modelID int) error {
if _, err := m.queries.Attach.Exec(id, model, modelID); err != nil {
- m.lo.Error("error attaching media to model", "model", model, "model_id", modelID, "error", err)
- return err
+ m.lo.Error("error attaching media to model", "model", model, "model_id", modelID, "media_id", id, "error", err)
+ return fmt.Errorf("attaching media;%d to model:%s model_id:%d: %w", id, model, modelID, err)
}
return nil
}
@@ -184,27 +185,14 @@ func (m *Manager) Delete(name string) error {
return nil
}
-// Delete deletes a media file from both the storage backend and the database.
-func (m *Manager) DeleteByUUID(uuid string) error {
- if err := m.store.Delete(uuid); err != nil {
- m.lo.Error("error deleting media from store", "error", err)
- return envelope.NewError(envelope.GeneralError, "Error deleting media from store", nil)
- }
- if _, err := m.queries.Delete.Exec(uuid); err != nil {
- m.lo.Error("error deleting media from db", "error", err)
- return envelope.NewError(envelope.GeneralError, "Error deleting media from DB", nil)
- }
- return nil
-}
-
-// DeleteUnlinkedMessageMedia is a blocking function that periodically deletes media files that are not linked to any conversation message.
-func (m *Manager) DeleteUnlinkedMessageMedia(ctx context.Context) {
+// DeleteUnlinkedMedia is a blocking function that periodically deletes media files that are not linked to any conversation message.
+func (m *Manager) DeleteUnlinkedMedia(ctx context.Context) {
m.deleteUnlinkedMessageMedia()
for {
select {
case <-ctx.Done():
return
- case <-time.After(24 * time.Hour):
+ case <-time.After(2 * time.Hour):
m.lo.Info("deleting unlinked message media")
if err := m.deleteUnlinkedMessageMedia(); err != nil {
m.lo.Error("error deleting unlinked media", "error", err)
@@ -221,7 +209,7 @@ func (m *Manager) deleteUnlinkedMessageMedia() error {
return err
}
for _, mm := range media {
- if err := m.DeleteByUUID(mm.UUID); err != nil {
+ if err := m.Delete(mm.UUID); err != nil {
return err
}
}
diff --git a/internal/media/models/models.go b/internal/media/models/models.go
index 782397e5..f4a05734 100644
--- a/internal/media/models/models.go
+++ b/internal/media/models/models.go
@@ -24,7 +24,7 @@ type Media struct {
ModelID null.Int `db:"model_id" json:"-"`
Size int `db:"size" json:"size"`
Store string `db:"store" json:"store"`
- Disposition string `db:"disposition" json:"disposition"`
+ Disposition null.String `db:"disposition" json:"disposition"`
URL string `json:"url"`
ContentID string `json:"-"`
Content []byte `json:"-"`
diff --git a/internal/media/queries.sql b/internal/media/queries.sql
index c43bf028..3220b9ae 100644
--- a/internal/media/queries.sql
+++ b/internal/media/queries.sql
@@ -15,12 +15,12 @@ VALUES(
RETURNING id;
-- name: get-media
-SELECT id, created_at, "uuid", store, filename, content_type, model_id, model_type, "size", COALESCE(disposition, '') AS disposition
+SELECT id, created_at, "uuid", store, filename, content_type, model_id, model_type, "size", disposition
FROM media
WHERE id = $1;
-- name: get-media-by-uuid
-SELECT id, created_at, "uuid", store, filename, content_type, model_id, model_type, "size", COALESCE(disposition, '') AS disposition
+SELECT id, created_at, "uuid", store, filename, content_type, model_id, model_type, "size", disposition
FROM media
WHERE uuid = $1;
@@ -35,13 +35,13 @@ SET model_type = $2,
WHERE id = $1;
-- name: get-model-media
-SELECT id, created_at, "uuid", store, filename, content_type, model_id, model_type, "size", COALESCE(disposition, '') AS disposition
+SELECT id, created_at, "uuid", store, filename, content_type, model_id, model_type, "size", disposition
FROM media
WHERE model_type = $1
AND model_id = $2;
-- name: get-unlinked-message-media
-SELECT id, created_at, "uuid", store, filename, content_type, model_id, model_type, "size", COALESCE(disposition, '') AS disposition
+SELECT id, created_at, "uuid", store, filename, content_type, model_id, model_type, "size", disposition
FROM media
WHERE model_type = 'messages'
AND model_id IS NULL or model_id = 0 AND created_at < NOW() - INTERVAL '1 day';
diff --git a/internal/media/stores/localfs/fs.go b/internal/media/stores/localfs/fs.go
index e877ff8c..372f386f 100644
--- a/internal/media/stores/localfs/fs.go
+++ b/internal/media/stores/localfs/fs.go
@@ -6,7 +6,7 @@ import (
"os"
"path/filepath"
- "github.com/abhinavxd/artemis/internal/media"
+ "github.com/abhinavxd/libredesk/internal/media"
)
// Opts holds fs options.
diff --git a/internal/media/stores/s3/s3.go b/internal/media/stores/s3/s3.go
index ca183e36..9c19b069 100644
--- a/internal/media/stores/s3/s3.go
+++ b/internal/media/stores/s3/s3.go
@@ -10,7 +10,7 @@ import (
"strings"
"time"
- "github.com/abhinavxd/artemis/internal/media"
+ "github.com/abhinavxd/libredesk/internal/media"
"github.com/rhnvrm/simples3"
)
diff --git a/internal/notification/notification.go b/internal/notification/notification.go
index 4c1972ed..7c9d6bce 100644
--- a/internal/notification/notification.go
+++ b/internal/notification/notification.go
@@ -5,7 +5,7 @@ import (
"fmt"
"sync"
- "github.com/abhinavxd/artemis/internal/attachment"
+ "github.com/abhinavxd/libredesk/internal/attachment"
"github.com/zerodha/logf"
)
diff --git a/internal/notification/providers/email/email.go b/internal/notification/providers/email/email.go
index 9a90ce91..7ffa40fa 100644
--- a/internal/notification/providers/email/email.go
+++ b/internal/notification/providers/email/email.go
@@ -5,9 +5,9 @@ import (
"math/rand"
"net/textproto"
- "github.com/abhinavxd/artemis/internal/attachment"
- "github.com/abhinavxd/artemis/internal/inbox/channel/email"
- notifier "github.com/abhinavxd/artemis/internal/notification"
+ "github.com/abhinavxd/libredesk/internal/attachment"
+ "github.com/abhinavxd/libredesk/internal/inbox/channel/email"
+ notifier "github.com/abhinavxd/libredesk/internal/notification"
"github.com/knadh/smtppool"
"github.com/zerodha/logf"
)
diff --git a/internal/oidc/models/models.go b/internal/oidc/models/models.go
index a91898da..82dcb86c 100644
--- a/internal/oidc/models/models.go
+++ b/internal/oidc/models/models.go
@@ -10,9 +10,9 @@ type OIDC struct {
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
Name string `db:"name" json:"name"`
- Disabled bool `db:"disabled" json:"disabled"`
- ClientID string `db:"client_id" json:"client_id"`
- ClientSecret string `db:"client_secret" json:"client_secret"`
+ Enabled bool `db:"enabled" json:"enabled"`
+ ClientID string `db:"client_id" json:"client_id,omitempty"`
+ ClientSecret string `db:"client_secret" json:"client_secret,omitempty"`
Provider string `db:"provider" json:"provider"`
ProviderURL string `db:"provider_url" json:"provider_url"`
RedirectURI string `db:"-" json:"redirect_uri"`
@@ -22,7 +22,6 @@ type OIDC struct {
// providerLogos holds known provider logos.
var providerLogos = map[string]string{
"Google": "/images/google-logo.png",
- "Github": "/images/github-logo.png",
"Custom": "",
}
diff --git a/internal/oidc/oidc.go b/internal/oidc/oidc.go
index c4d7561b..ec4d4dc0 100644
--- a/internal/oidc/oidc.go
+++ b/internal/oidc/oidc.go
@@ -2,25 +2,28 @@ package oidc
import (
"embed"
+ "fmt"
"strings"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/abhinavxd/artemis/internal/oidc/models"
- "github.com/abhinavxd/artemis/internal/stringutil"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/oidc/models"
+ "github.com/abhinavxd/libredesk/internal/stringutil"
"github.com/jmoiron/sqlx"
"github.com/zerodha/logf"
)
var (
//go:embed queries.sql
- efs embed.FS
+ efs embed.FS
+ redirectURL = "/api/v1/oidc/%d/finish"
)
// Manager handles oidc-related operations.
type Manager struct {
- q queries
- lo *logf.Logger
+ q queries
+ lo *logf.Logger
+ setting settingsStore
}
// Opts contains options for initializing the Manager.
@@ -31,36 +34,47 @@ type Opts struct {
// queries contains prepared SQL queries.
type queries struct {
- GetAllOIDC *sqlx.Stmt `query:"get-all-oidc"`
- GetOIDC *sqlx.Stmt `query:"get-oidc"`
- InsertOIDC *sqlx.Stmt `query:"insert-oidc"`
- UpdateOIDC *sqlx.Stmt `query:"update-oidc"`
- DeleteOIDC *sqlx.Stmt `query:"delete-oidc"`
+ GetAllOIDC *sqlx.Stmt `query:"get-all-oidc"`
+ GetAllEnabled *sqlx.Stmt `query:"get-all-enabled"`
+ GetOIDC *sqlx.Stmt `query:"get-oidc"`
+ InsertOIDC *sqlx.Stmt `query:"insert-oidc"`
+ UpdateOIDC *sqlx.Stmt `query:"update-oidc"`
+ DeleteOIDC *sqlx.Stmt `query:"delete-oidc"`
+}
+
+type settingsStore interface {
+ GetAppRootURL() (string, error)
}
// New creates and returns a new instance of the oidc Manager.
-func New(opts Opts) (*Manager, error) {
+func New(opts Opts, setting settingsStore) (*Manager, error) {
var q queries
-
if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
return nil, err
}
-
return &Manager{
- q: q,
- lo: opts.Lo,
+ q: q,
+ lo: opts.Lo,
+ setting: setting,
}, nil
}
// Get returns an oidc by id.
-func (o *Manager) Get(id int) (models.OIDC, error) {
+func (o *Manager) Get(id int, includeSecret bool) (models.OIDC, error) {
var oidc models.OIDC
if err := o.q.GetOIDC.Get(&oidc, id); err != nil {
o.lo.Error("error fetching oidc", "error", err)
return oidc, envelope.NewError(envelope.GeneralError, "Error fetching OIDC", nil)
}
+ // Set logo and redirect URL.
oidc.SetProviderLogo()
- if oidc.ClientSecret != "" {
+ rootURL, err := o.setting.GetAppRootURL()
+ if err != nil {
+ return models.OIDC{}, err
+ }
+ oidc.RedirectURI = fmt.Sprintf(rootURL+redirectURL, oidc.ID)
+ // If secret is not to be included, replace it with dummy characters.
+ if oidc.ClientSecret != "" && !includeSecret {
oidc.ClientSecret = strings.Repeat(stringutil.PasswordDummy, 10)
}
return oidc, nil
@@ -73,6 +87,28 @@ func (o *Manager) GetAll() ([]models.OIDC, error) {
o.lo.Error("error fetching oidc", "error", err)
return oidc, envelope.NewError(envelope.GeneralError, "Error fetching OIDC", nil)
}
+
+ // Get root URL of the app.
+ rootURL, err := o.setting.GetAppRootURL()
+ if err != nil {
+ return nil, err
+ }
+
+ // Set logo and redirect URL.
+ for i := range oidc {
+ oidc[i].RedirectURI = fmt.Sprintf(rootURL+redirectURL, oidc[i].ID)
+ oidc[i].SetProviderLogo()
+ }
+ return oidc, nil
+}
+
+// GetAllEnabled retrieves all enabled oidc.
+func (o *Manager) GetAllEnabled() ([]models.OIDC, error) {
+ var oidc = make([]models.OIDC, 0)
+ if err := o.q.GetAllEnabled.Select(&oidc); err != nil {
+ o.lo.Error("error fetching oidc", "error", err)
+ return oidc, envelope.NewError(envelope.GeneralError, "Error fetching OIDC", nil)
+ }
for i := range oidc {
oidc[i].SetProviderLogo()
}
@@ -90,14 +126,14 @@ func (o *Manager) Create(oidc models.OIDC) error {
// Create updates a oidc by id.
func (o *Manager) Update(id int, oidc models.OIDC) error {
- current, err := o.Get(id)
+ current, err := o.Get(id, true)
if err != nil {
return err
}
if oidc.ClientSecret == "" {
oidc.ClientSecret = current.ClientSecret
}
- if _, err := o.q.UpdateOIDC.Exec(id, oidc.Name, oidc.Provider, oidc.ProviderURL, oidc.ClientID, oidc.ClientSecret, oidc.Disabled); err != nil {
+ if _, err := o.q.UpdateOIDC.Exec(id, oidc.Name, oidc.Provider, oidc.ProviderURL, oidc.ClientID, oidc.ClientSecret, oidc.Enabled); err != nil {
o.lo.Error("error updating oidc", "error", err)
return envelope.NewError(envelope.GeneralError, "Error updating OIDC", nil)
}
diff --git a/internal/oidc/queries.sql b/internal/oidc/queries.sql
index 760380b1..1a9506c8 100644
--- a/internal/oidc/queries.sql
+++ b/internal/oidc/queries.sql
@@ -1,5 +1,8 @@
-- name: get-all-oidc
-SELECT id, name, disabled, provider, updated_at FROM oidc order by updated_at desc;
+SELECT id, created_at, updated_at, name, provider, provider_url, client_id, client_secret, enabled FROM oidc order by updated_at desc;
+
+-- name: get-all-enabled
+SELECT id, name, enabled, provider, updated_at FROM oidc WHERE enabled = true order by updated_at desc;
-- name: get-oidc
SELECT * FROM oidc WHERE id = $1;
@@ -10,7 +13,7 @@ VALUES ($1, $2, $3, $4, $5);
-- name: update-oidc
UPDATE oidc
-SET name = $2, provider = $3, provider_url = $4, client_id = $5, client_secret = $6, disabled = $7, updated_at = now()
+SET name = $2, provider = $3, provider_url = $4, client_id = $5, client_secret = $6, enabled = $7, updated_at = now()
WHERE id = $1;
-- name: delete-oidc
diff --git a/internal/role/models/models.go b/internal/role/models/models.go
index 9a809323..6b43efe3 100644
--- a/internal/role/models/models.go
+++ b/internal/role/models/models.go
@@ -6,10 +6,14 @@ import (
"github.com/lib/pq"
)
-// Default roles
-var Roles = []string{
- "Admin",
- "Agent",
+const (
+ RoleAdmin = "Admin"
+ RoleAgent = "Agent"
+)
+
+var DefaultRoles = []string{
+ RoleAdmin,
+ RoleAgent,
}
type Role struct {
diff --git a/internal/role/role.go b/internal/role/role.go
index 5e42f177..a972a325 100644
--- a/internal/role/role.go
+++ b/internal/role/role.go
@@ -3,11 +3,12 @@ package role
import (
"embed"
+ "fmt"
- amodels "github.com/abhinavxd/artemis/internal/authz/models"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/abhinavxd/artemis/internal/role/models"
+ amodels "github.com/abhinavxd/libredesk/internal/authz/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/role/models"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
"github.com/zerodha/logf"
@@ -75,12 +76,12 @@ func (t *Manager) Get(id int) (models.Role, error) {
// Delete deletes a role by ID.
func (t *Manager) Delete(id int) error {
- // Disallow deletion of predefined roles.
+ // Disallow deletion of default roles.
role, err := t.Get(id)
if err != nil {
return err
}
- for _, r := range models.Roles {
+ for _, r := range models.DefaultRoles {
if role.Name == r {
return envelope.NewError(envelope.InputError, "Cannot delete default roles", nil)
}
@@ -95,10 +96,13 @@ func (t *Manager) Delete(id int) error {
// Create creates a new role.
func (u *Manager) Create(r models.Role) error {
- if !u.areValidPerms(r.Permissions) {
- return envelope.NewError(envelope.InputError, "Invalid permissions", nil)
+ if err := u.validatePermissions(r.Permissions); err != nil {
+ return err
}
if _, err := u.q.Insert.Exec(r.Name, r.Description, pq.Array(r.Permissions)); err != nil {
+ if dbutil.IsUniqueViolationError(err) {
+ return envelope.NewError(envelope.InputError, "Role with this name already exists", nil)
+ }
u.lo.Error("error inserting role", "error", err)
return envelope.NewError(envelope.GeneralError, "Error creating role", nil)
}
@@ -107,9 +111,10 @@ func (u *Manager) Create(r models.Role) error {
// Update updates an existing role.
func (u *Manager) Update(id int, r models.Role) error {
- if !u.areValidPerms(r.Permissions) {
- return envelope.NewError(envelope.InputError, "Invalid permissions", nil)
+ if err := u.validatePermissions(r.Permissions); err != nil {
+ return err
}
+
if _, err := u.q.Update.Exec(id, r.Name, r.Description, pq.Array(r.Permissions)); err != nil {
u.lo.Error("error updating role", "error", err)
return envelope.NewError(envelope.GeneralError, "Error updating role", nil)
@@ -117,13 +122,16 @@ func (u *Manager) Update(id int, r models.Role) error {
return nil
}
-// areValidPerms returns true if the permissions are one of the valid permissions
-func (u *Manager) areValidPerms(permissions []string) bool {
+// validatePermissions returns true if all given permissions are valid
+func (u *Manager) validatePermissions(permissions []string) error {
+ if len(permissions) == 0 {
+ return envelope.NewError(envelope.InputError, "Permissions cannot be empty", nil)
+ }
for _, perm := range permissions {
if !amodels.IsValidPermission(perm) {
- u.lo.Error("invalid permission", "permission", perm)
- return false
+ u.lo.Error("error unknown permission", "permission", perm)
+ return envelope.NewError(envelope.InputError, fmt.Sprintf("Unknown permission: %s", perm), nil)
}
}
- return true
+ return nil
}
diff --git a/internal/search/models/models.go b/internal/search/models/models.go
new file mode 100644
index 00000000..469723d4
--- /dev/null
+++ b/internal/search/models/models.go
@@ -0,0 +1,18 @@
+package models
+
+import "time"
+
+type Conversation struct {
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UUID string `db:"uuid" json:"uuid"`
+ ReferenceNumber string `db:"reference_number" json:"reference_number"`
+ Subject string `db:"subject" json:"subject"`
+}
+
+type Message struct {
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ TextContent string `db:"text_content" json:"text_content"`
+ ConversationCreatedAt time.Time `db:"conversation_created_at" json:"conversation_created_at"`
+ ConversationUUID string `db:"conversation_uuid" json:"conversation_uuid"`
+ ConversationReferenceNumber string `db:"conversation_reference_number" json:"conversation_reference_number"`
+}
diff --git a/internal/search/queries.sql b/internal/search/queries.sql
new file mode 100644
index 00000000..7b10c18b
--- /dev/null
+++ b/internal/search/queries.sql
@@ -0,0 +1,18 @@
+-- name: search-conversations
+SELECT
+ conversations.created_at,
+ conversations.uuid,
+ conversations.reference_number,
+ conversations.subject
+FROM conversations
+WHERE reference_number::text = $1;
+
+-- name: search-messages
+SELECT
+ c.created_at as "conversation_created_at",
+ c.reference_number as "conversation_reference_number",
+ c.uuid as "conversation_uuid",
+ m.text_content
+FROM conversation_messages m
+ JOIN conversations c ON m.conversation_id = c.id
+WHERE m.type != 'activity' and m.text_content ILIKE '%' || $1 || '%';
\ No newline at end of file
diff --git a/internal/search/search.go b/internal/search/search.go
new file mode 100644
index 00000000..cc7e5f5f
--- /dev/null
+++ b/internal/search/search.go
@@ -0,0 +1,64 @@
+// Package search provides search functionality.
+package search
+
+import (
+ "embed"
+
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ models "github.com/abhinavxd/libredesk/internal/search/models"
+ "github.com/jmoiron/sqlx"
+ "github.com/zerodha/logf"
+)
+
+var (
+ //go:embed queries.sql
+ efs embed.FS
+)
+
+// Manager is the search manager
+type Manager struct {
+ q queries
+ lo *logf.Logger
+}
+
+// Opts contains the options for creating a new search manager
+type Opts struct {
+ DB *sqlx.DB
+ Lo *logf.Logger
+}
+
+// queries contains all the prepared queries
+type queries struct {
+ SearchConversations *sqlx.Stmt `query:"search-conversations"`
+ SearchMessages *sqlx.Stmt `query:"search-messages"`
+}
+
+// New creates a new search manager
+func New(opts Opts) (*Manager, error) {
+ var q queries
+ if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
+ return nil, err
+ }
+ return &Manager{q: q, lo: opts.Lo}, nil
+}
+
+// Conversations searches conversations based on the query
+func (s *Manager) Conversations(query string) ([]models.Conversation, error) {
+ var results = make([]models.Conversation, 0)
+ if err := s.q.SearchConversations.Select(&results, query); err != nil {
+ s.lo.Error("error searching conversations", "error", err)
+ return nil, envelope.NewError(envelope.GeneralError, "Error searching conversations", nil)
+ }
+ return results, nil
+}
+
+// Messages searches messages based on the query
+func (s *Manager) Messages(query string) ([]models.Message, error) {
+ var results = make([]models.Message, 0)
+ if err := s.q.SearchMessages.Select(&results, query); err != nil {
+ s.lo.Error("error searching messages", "error", err)
+ return nil, envelope.NewError(envelope.GeneralError, "Error searching messages", nil)
+ }
+ return results, nil
+}
diff --git a/internal/setting/models/models.go b/internal/setting/models/models.go
index e82d2db4..b5281580 100644
--- a/internal/setting/models/models.go
+++ b/internal/setting/models/models.go
@@ -5,8 +5,11 @@ type General struct {
Lang string `json:"app.lang"`
MaxFileUploadSize int `json:"app.max_file_upload_size"`
FaviconURL string `json:"app.favicon_url"`
+ LogoURL string `json:"app.logo_url"`
RootURL string `json:"app.root_url"`
AllowedFileUploadExtensions []string `json:"app.allowed_file_upload_extensions"`
+ Timezone string `json:"app.timezone"`
+ BusinessHoursID string `json:"app.business_hours_id"`
}
type EmailNotification struct {
diff --git a/internal/setting/queries.sql b/internal/setting/queries.sql
index 6d9a41ed..ad58aeee 100644
--- a/internal/setting/queries.sql
+++ b/internal/setting/queries.sql
@@ -11,4 +11,7 @@ WHERE s.key = c.key;
-- name: get-by-prefix
SELECT JSON_OBJECT_AGG(key, value) AS settings
FROM settings
-WHERE key LIKE $1 || '%';
\ No newline at end of file
+WHERE key LIKE $1 || '%';
+
+-- name: get
+SELECT value FROM settings WHERE key = $1;
\ No newline at end of file
diff --git a/internal/setting/setting.go b/internal/setting/setting.go
index 88c4fd43..63fedb95 100644
--- a/internal/setting/setting.go
+++ b/internal/setting/setting.go
@@ -4,10 +4,11 @@ package setting
import (
"embed"
"encoding/json"
+ "strings"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/abhinavxd/artemis/internal/setting/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/setting/models"
"github.com/jmoiron/sqlx"
"github.com/jmoiron/sqlx/types"
"github.com/zerodha/logf"
@@ -32,6 +33,7 @@ type Opts struct {
// queries contains prepared SQL queries.
type queries struct {
+ Get *sqlx.Stmt `query:"get"`
GetAll *sqlx.Stmt `query:"get-all"`
Update *sqlx.Stmt `query:"update"`
GetByPrefix *sqlx.Stmt `query:"get-by-prefix"`
@@ -72,11 +74,9 @@ func (m *Manager) GetAll() (models.Settings, error) {
// GetAllJSON retrieves all settings as JSON.
func (m *Manager) GetAllJSON() (types.JSONText, error) {
var b types.JSONText
-
if err := m.q.GetAll.Get(&b); err != nil {
return b, err
}
-
return b, nil
}
@@ -87,12 +87,10 @@ func (m *Manager) Update(s interface{}) error {
if err != nil {
return envelope.NewError(envelope.GeneralError, "Error updating settings", nil)
}
-
// Update the settings in the DB.
if _, err := m.q.Update.Exec(b); err != nil {
return envelope.NewError(envelope.GeneralError, "Error updating settings", nil)
}
-
return nil
}
@@ -101,7 +99,27 @@ func (m *Manager) GetByPrefix(prefix string) (types.JSONText, error) {
var b types.JSONText
if err := m.q.GetByPrefix.Get(&b, prefix+"%"); err != nil {
m.lo.Error("error fetching settings", "prefix", prefix, "error", err)
- return b, err
+ return b, envelope.NewError(envelope.GeneralError, "Error fetching settings", nil)
}
return b, nil
}
+
+// Get retrieves a setting by key as JSON.
+func (m *Manager) Get(key string) (types.JSONText, error) {
+ var b types.JSONText
+ if err := m.q.Get.Get(&b, key); err != nil {
+ m.lo.Error("error fetching setting", "key", key, "error", err)
+ return b, envelope.NewError(envelope.GeneralError, "Error fetching setting", nil)
+ }
+ return b, nil
+}
+
+// GetAppRootURL returns the root URL of the app.
+func (m *Manager) GetAppRootURL() (string, error) {
+ rootURL, err := m.Get("app.root_url")
+ if err != nil {
+ m.lo.Error("error fetching root URL", "error", err)
+ return "", envelope.NewError(envelope.GeneralError, "Error fetching app root URL", nil)
+ }
+ return strings.Trim(string(rootURL), "\""), nil
+}
diff --git a/internal/sla/calculator.go b/internal/sla/calculator.go
new file mode 100644
index 00000000..43ac7dcc
--- /dev/null
+++ b/internal/sla/calculator.go
@@ -0,0 +1,132 @@
+package sla
+
+import (
+ "encoding/json"
+ "fmt"
+ "time"
+
+ "github.com/abhinavxd/libredesk/internal/business_hours/models"
+)
+
+var (
+ ErrInvalidSLADuration = fmt.Errorf("invalid SLA duration")
+ ErrMaxIterations = fmt.Errorf("sla: exceeded maximum iterations - check configuration")
+)
+
+// CalculateDeadline computes the SLA deadline from a start time and SLA duration in minutes
+// considering the provided holidays, working hours, and time zone.
+func (m *Manager) CalculateDeadline(start time.Time, slaMinutes int, businessHours models.BusinessHours, timeZone string) (time.Time, error) {
+ if slaMinutes <= 0 {
+ return time.Time{}, ErrInvalidSLADuration
+ }
+
+ // If business is always open, return the deadline as the start time plus the SLA duration.
+ if businessHours.IsAlwaysOpen {
+ return start.Add(time.Duration(slaMinutes) * time.Minute), nil
+ }
+
+ // Load the specified time zone.
+ loc, err := time.LoadLocation(timeZone)
+ if err != nil {
+ return time.Time{}, fmt.Errorf("invalid time zone %s: %v", timeZone, err)
+ }
+
+ // Convert start time to the specified time zone.
+ currentTime := start.In(loc)
+ remainingMinutes := slaMinutes
+ maxIterations := ((slaMinutes+59)/60)*24 + 1
+
+ // Unmarshal working hours.
+ var workingHours map[string]models.WorkingHours
+ if err := json.Unmarshal(businessHours.Hours, &workingHours); err != nil {
+ return time.Time{}, fmt.Errorf("could not unmarshal working hours for SLA deadline calcuation: %v", err)
+ }
+
+ // Unmarshal holidays.
+ var holidays = []models.Holiday{}
+ if err := json.Unmarshal(businessHours.Holidays, &holidays); err != nil {
+ return time.Time{}, fmt.Errorf("could not unmarshal holidays for SLA deadline calcuation: %v", err)
+ }
+
+ // Create a map of holidays.
+ holidaysMap := make(map[string]struct{})
+ for _, holiday := range holidays {
+ holidaysMap[holiday.Date] = struct{}{}
+ }
+
+ iterations := 0
+ for remainingMinutes > 0 {
+ iterations++
+ if iterations > maxIterations {
+ return time.Time{}, ErrMaxIterations
+ }
+
+ // Skip holidays.
+ dateStr := currentTime.Format(time.DateOnly)
+ if _, isHoliday := holidaysMap[dateStr]; isHoliday {
+ currentTime = nextDay(currentTime, loc)
+ continue
+ }
+
+ // Get working hours for the current day.
+ dayOfWeek := currentTime.Weekday().String()
+ workHours, exists := workingHours[dayOfWeek]
+ if !exists || workHours.ClosedAllDay {
+ currentTime = nextDay(currentTime, loc)
+ continue
+ }
+
+ // OpenAllDay scenario.
+ var startOfWork, endOfWork time.Time
+ if workHours.OpenAllDay {
+ startOfWork = time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 0, 0, 0, 0, loc)
+ endOfWork = time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 23, 59, 59, 0, loc)
+ } else {
+ var err error
+ startOfWork, err = parseTime(currentTime, workHours.Open, loc)
+ if err != nil {
+ return time.Time{}, fmt.Errorf("invalid open time %s for %s: %v", workHours.Open, dayOfWeek, err)
+ }
+ endOfWork, err = parseTime(currentTime, workHours.Close, loc)
+ if err != nil {
+ return time.Time{}, fmt.Errorf("invalid close time %s for %s: %v", workHours.Close, dayOfWeek, err)
+ }
+ }
+
+ // Adjust to start of work if current time is before it.
+ if currentTime.Before(startOfWork) {
+ currentTime = startOfWork
+ }
+
+ // Move to next day if current time is after end of work.
+ if currentTime.After(endOfWork) {
+ currentTime = nextDay(startOfWork, loc)
+ continue
+ }
+
+ // Deduct minutes worked today from remaining SLA time.
+ workMinutesLeft := int(endOfWork.Sub(currentTime).Minutes())
+ if workMinutesLeft > remainingMinutes {
+ return currentTime.Add(time.Duration(remainingMinutes) * time.Minute), nil
+ }
+
+ remainingMinutes -= workMinutesLeft
+ currentTime = nextDay(startOfWork, loc)
+ }
+
+ return currentTime, nil
+}
+
+// nextDay advances the time to the start of the next day in the specified time zone.
+func nextDay(t time.Time, loc *time.Location) time.Time {
+ return time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, loc)
+}
+
+// parseTime parses a time string in "HH:MM" format and returns a time.Time object for the given date and location.
+func parseTime(date time.Time, timeStr string, loc *time.Location) (time.Time, error) {
+ parsedTime, err := time.ParseInLocation("15:04", timeStr, loc)
+ if err != nil {
+ return time.Time{}, err
+ }
+ return time.Date(date.Year(), date.Month(), date.Day(), parsedTime.Hour(), parsedTime.Minute(), 0, 0, loc), nil
+}
diff --git a/internal/sla/models/models.go b/internal/sla/models/models.go
new file mode 100644
index 00000000..9f089167
--- /dev/null
+++ b/internal/sla/models/models.go
@@ -0,0 +1,33 @@
+package models
+
+import (
+ "time"
+
+ "github.com/volatiletech/null/v9"
+)
+
+// SLAPolicy represents a service level agreement policy definition
+type SLAPolicy struct {
+ ID int `db:"id" json:"id"`
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+ Name string `db:"name" json:"name"`
+ Description string `db:"description" json:"description"`
+ FirstResponseTime string `db:"first_response_time" json:"first_response_time"`
+ EveryResponseTime string `db:"every_response_time" json:"every_response_time"`
+ ResolutionTime string `db:"resolution_time" json:"resolution_time"`
+}
+
+// AppliedSLA represents an SLA policy applied to a conversation with its deadlines and breach status
+type AppliedSLA struct {
+ ID int `db:"id"`
+ CreatedAt time.Time `db:"created_at"`
+ ConversationID int `db:"conversation_id"`
+ SLAPolicyID int `db:"sla_policy_id"`
+ FirstResponseDeadlineAt time.Time `db:"first_response_deadline_at"`
+ ResolutionDeadlineAt time.Time `db:"resolution_deadline_at"`
+ FirstResponseBreachedAt null.Time `db:"first_response_breached_at"`
+ ResolutionBreachedAt null.Time `db:"resolution_breached_at"`
+ FirstResponseAt null.Time `db:"first_response_at"`
+ ResolvedAt null.Time `db:"resolved_at"`
+}
diff --git a/internal/sla/queries.sql b/internal/sla/queries.sql
new file mode 100644
index 00000000..55ad45f1
--- /dev/null
+++ b/internal/sla/queries.sql
@@ -0,0 +1,73 @@
+-- name: get-sla-policy
+SELECT * FROM sla_policies WHERE id = $1;
+
+-- name: get-all-sla-policies
+SELECT * FROM sla_policies ORDER BY updated_at DESC;
+
+-- name: insert-sla-policy
+INSERT INTO sla_policies (
+ name,
+ description,
+ first_response_time,
+ resolution_time
+) VALUES ($1, $2, $3, $4);
+
+-- name: delete-sla-policy
+DELETE FROM sla_policies WHERE id = $1;
+
+-- name: update-sla-policy
+UPDATE sla_policies SET
+ name = $2,
+ description = $3,
+ first_response_time = $4,
+ resolution_time = $5,
+ updated_at = NOW()
+WHERE id = $1;
+
+-- name: apply-sla
+WITH new_sla AS (
+ INSERT INTO applied_slas (
+ conversation_id,
+ sla_policy_id,
+ first_response_deadline_at,
+ resolution_deadline_at
+ ) VALUES ($1, $2, $3, $4)
+ RETURNING conversation_id
+)
+UPDATE conversations
+SET sla_policy_id = $2,
+next_sla_deadline_at = LEAST(
+ NULLIF($3, NULL),
+ NULLIF($4, NULL)
+)
+WHERE id IN (SELECT conversation_id FROM new_sla);
+
+-- name: get-pending-slas
+-- Get all the applied SLAs that are not yet breached or met and is also set on the conversation.
+-- This make sure when SLA is changed, we don't update the breached or met status of the previous SLA.
+SELECT a.id, a.first_response_deadline_at, c.first_reply_at as first_response_at,
+a.resolution_deadline_at, c.resolved_at as resolved_at
+FROM applied_slas a
+JOIN conversations c ON a.conversation_id = c.id and c.sla_policy_id = a.sla_policy_id
+WHERE (first_response_breached_at IS NULL AND first_response_met_at IS NULL)
+ OR (resolution_breached_at IS NULL AND resolution_met_at IS NULL);
+
+-- name: update-breach
+UPDATE applied_slas SET
+ first_response_breached_at = CASE WHEN $2 = 'first_response' THEN NOW() ELSE first_response_breached_at END,
+ resolution_breached_at = CASE WHEN $2 = 'resolution' THEN NOW() ELSE resolution_breached_at END,
+ updated_at = NOW()
+WHERE id = $1;
+
+-- name: update-met
+UPDATE applied_slas SET
+ first_response_met_at = CASE WHEN $2 = 'first_response' THEN NOW() ELSE first_response_met_at END,
+ resolution_met_at = CASE WHEN $2 = 'resolution' THEN NOW() ELSE resolution_met_at END,
+ updated_at = NOW()
+WHERE id = $1;
+
+-- name: get-latest-sla-deadlines
+SELECT first_response_deadline_at, resolution_deadline_at
+FROM applied_slas
+WHERE conversation_id = $1
+ORDER BY created_at DESC LIMIT 1;
\ No newline at end of file
diff --git a/internal/sla/sla.go b/internal/sla/sla.go
new file mode 100644
index 00000000..c042c125
--- /dev/null
+++ b/internal/sla/sla.go
@@ -0,0 +1,350 @@
+package sla
+
+import (
+ "context"
+ "database/sql"
+ "embed"
+ "encoding/json"
+ "fmt"
+ "strconv"
+ "sync"
+ "time"
+
+ businessHours "github.com/abhinavxd/libredesk/internal/business_hours"
+ bmodels "github.com/abhinavxd/libredesk/internal/business_hours/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ models "github.com/abhinavxd/libredesk/internal/sla/models"
+ tmodels "github.com/abhinavxd/libredesk/internal/team/models"
+ "github.com/jmoiron/sqlx"
+ "github.com/jmoiron/sqlx/types"
+ "github.com/volatiletech/null/v9"
+ "github.com/zerodha/logf"
+)
+
+var (
+ //go:embed queries.sql
+ efs embed.FS
+)
+
+const (
+ SLATypeFirstResponse = "first_response"
+ SLATypeResolution = "resolution"
+)
+
+// Manager manages SLA policies and calculations.
+type Manager struct {
+ q queries
+ lo *logf.Logger
+ teamStore teamStore
+ appSettingsStore appSettingsStore
+ businessHrsStore businessHrsStore
+ wg sync.WaitGroup
+ opts Opts
+}
+
+// Opts defines the options for creating SLA manager.
+type Opts struct {
+ DB *sqlx.DB
+ Lo *logf.Logger
+}
+
+// Deadlines holds the deadlines for an SLA policy.
+type Deadlines struct {
+ FirstResponse time.Time
+ Resolution time.Time
+}
+
+type teamStore interface {
+ Get(id int) (tmodels.Team, error)
+}
+
+type appSettingsStore interface {
+ GetByPrefix(prefix string) (types.JSONText, error)
+}
+
+type businessHrsStore interface {
+ Get(id int) (bmodels.BusinessHours, error)
+}
+
+// queries hold prepared SQL queries.
+type queries struct {
+ GetSLA *sqlx.Stmt `query:"get-sla-policy"`
+ GetAllSLA *sqlx.Stmt `query:"get-all-sla-policies"`
+ InsertSLA *sqlx.Stmt `query:"insert-sla-policy"`
+ DeleteSLA *sqlx.Stmt `query:"delete-sla-policy"`
+ UpdateSLA *sqlx.Stmt `query:"update-sla-policy"`
+ ApplySLA *sqlx.Stmt `query:"apply-sla"`
+ GetPendingSLAs *sqlx.Stmt `query:"get-pending-slas"`
+ UpdateBreach *sqlx.Stmt `query:"update-breach"`
+ UpdateMet *sqlx.Stmt `query:"update-met"`
+ GetLatestDeadlines *sqlx.Stmt `query:"get-latest-sla-deadlines"`
+}
+
+// New creates a new SLA manager.
+func New(opts Opts, teamStore teamStore, appSettingsStore appSettingsStore, businessHrsStore businessHrsStore) (*Manager, error) {
+ var q queries
+ if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
+ return nil, err
+ }
+ return &Manager{q: q, lo: opts.Lo, teamStore: teamStore, appSettingsStore: appSettingsStore, businessHrsStore: businessHrsStore, opts: opts}, nil
+}
+
+// Get retrieves an SLA by ID.
+func (m *Manager) Get(id int) (models.SLAPolicy, error) {
+ var sla models.SLAPolicy
+ if err := m.q.GetSLA.Get(&sla, id); err != nil {
+ m.lo.Error("error fetching SLA", "error", err)
+ return sla, envelope.NewError(envelope.GeneralError, "Error fetching SLA", nil)
+ }
+ return sla, nil
+}
+
+// GetAll fetches all SLA policies.
+func (m *Manager) GetAll() ([]models.SLAPolicy, error) {
+ var slas = make([]models.SLAPolicy, 0)
+ if err := m.q.GetAllSLA.Select(&slas); err != nil {
+ m.lo.Error("error fetching SLAs", "error", err)
+ return nil, envelope.NewError(envelope.GeneralError, "Error fetching SLAs", nil)
+ }
+ return slas, nil
+}
+
+// Create creates a new SLA policy.
+func (m *Manager) Create(name, description string, firstResponseTime, resolutionTime string) error {
+ if _, err := m.q.InsertSLA.Exec(name, description, firstResponseTime, resolutionTime); err != nil {
+ m.lo.Error("error inserting SLA", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error creating SLA", nil)
+ }
+ return nil
+}
+
+// Delete deletes an SLA policy.
+func (m *Manager) Delete(id int) error {
+ if _, err := m.q.DeleteSLA.Exec(id); err != nil {
+ m.lo.Error("error deleting SLA", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error deleting SLA", nil)
+ }
+ return nil
+}
+
+// Update updates an existing SLA policy.
+func (m *Manager) Update(id int, name, description string, firstResponseTime, resolutionTime string) error {
+ if _, err := m.q.UpdateSLA.Exec(id, name, description, firstResponseTime, resolutionTime); err != nil {
+ m.lo.Error("error updating SLA", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error updating SLA", nil)
+ }
+ return nil
+}
+
+// getBusinessHoursAndTimezone returns the business hours ID and timezone for a team, falling back to app settings.
+func (m *Manager) getBusinessHoursAndTimezone(assignedTeamID int) (bmodels.BusinessHours, string, error) {
+ var (
+ businessHrsID int
+ timezone string
+ bh bmodels.BusinessHours
+ )
+
+ // Fetch from team if assignedTeamID is provided.
+ if assignedTeamID != 0 {
+ team, err := m.teamStore.Get(assignedTeamID)
+ if err != nil {
+ return bh, "", err
+ }
+ businessHrsID = team.BusinessHoursID.Int
+ timezone = team.Timezone
+ }
+
+ // Else fetch from app settings, this is System default.
+ if businessHrsID == 0 || timezone == "" {
+ settingsJ, err := m.appSettingsStore.GetByPrefix("app")
+ if err != nil {
+ return bh, "", err
+ }
+
+ var out map[string]interface{}
+ if err := json.Unmarshal([]byte(settingsJ), &out); err != nil {
+ return bh, "", fmt.Errorf("parsing settings: %v", err)
+ }
+
+ businessHrsIDStr, _ := out["app.business_hours_id"].(string)
+ businessHrsID, _ = strconv.Atoi(businessHrsIDStr)
+ timezone, _ = out["app.timezone"].(string)
+ }
+
+ // If still not found, return error.
+ if businessHrsID == 0 || timezone == "" {
+ return bh, "", fmt.Errorf("business hours or timezone not configured")
+ }
+
+ bh, err := m.businessHrsStore.Get(businessHrsID)
+ if err != nil {
+ if err == businessHours.ErrBusinessHoursNotFound {
+ m.lo.Warn("business hours not found", "team_id", assignedTeamID)
+ return bh, "", fmt.Errorf("business hours not found")
+ }
+ m.lo.Error("error fetching business hours for SLA", "error", err)
+ return bh, "", err
+ }
+ return bh, timezone, nil
+}
+
+// CalculateDeadline calculates the deadline for a given start time and duration.
+func (m *Manager) CalculateDeadlines(startTime time.Time, slaPolicyID, assignedTeamID int) (Deadlines, error) {
+ var deadlines Deadlines
+
+ businessHrs, timezone, err := m.getBusinessHoursAndTimezone(assignedTeamID)
+ if err != nil {
+ return deadlines, err
+ }
+
+ m.lo.Info("calculating deadlines", "timezone", timezone, "business_hours_always_open", businessHrs.IsAlwaysOpen, "business_hours", businessHrs.Hours)
+
+ sla, err := m.Get(slaPolicyID)
+ if err != nil {
+ return deadlines, err
+ }
+
+ // Helper function to calculate deadlines by parsing the duration string.
+ calculateDeadline := func(durationStr string) (time.Time, error) {
+ if durationStr == "" {
+ return time.Time{}, nil
+ }
+ dur, err := time.ParseDuration(durationStr)
+ if err != nil {
+ return time.Time{}, fmt.Errorf("parsing SLA duration: %v", err)
+ }
+ deadline, err := m.CalculateDeadline(startTime, int(dur.Minutes()), businessHrs, timezone)
+ if err != nil {
+ return time.Time{}, err
+ }
+ return deadline, nil
+ }
+
+ if deadlines.FirstResponse, err = calculateDeadline(sla.FirstResponseTime); err != nil {
+ return deadlines, err
+ }
+ if deadlines.Resolution, err = calculateDeadline(sla.ResolutionTime); err != nil {
+ return deadlines, err
+ }
+ return deadlines, nil
+}
+
+// ApplySLA applies an SLA policy to a conversation.
+func (m *Manager) ApplySLA(startTime time.Time, conversationID, assignedTeamID, slaPolicyID int) (models.SLAPolicy, error) {
+ var sla models.SLAPolicy
+
+ deadlines, err := m.CalculateDeadlines(startTime, slaPolicyID, assignedTeamID)
+ if err != nil {
+ return sla, err
+ }
+ if _, err := m.q.ApplySLA.Exec(
+ conversationID,
+ slaPolicyID,
+ deadlines.FirstResponse,
+ deadlines.Resolution,
+ ); err != nil {
+ m.lo.Error("error applying SLA", "error", err)
+ return sla, envelope.NewError(envelope.GeneralError, "Error applying SLA", nil)
+ }
+ sla, err = m.Get(slaPolicyID)
+ if err != nil {
+ return sla, err
+ }
+ return sla, nil
+}
+
+// GetLatestDeadlines returns the latest deadlines for a conversation.
+func (m *Manager) GetLatestDeadlines(conversationID int) (time.Time, time.Time, error) {
+ var first, resolution time.Time
+ err := m.q.GetLatestDeadlines.QueryRow(conversationID).Scan(&first, &resolution)
+ if err == sql.ErrNoRows {
+ return first, resolution, nil
+ }
+ return first, resolution, err
+}
+
+// Run starts the SLA evaluation loop and evaluates pending SLAs.
+func (m *Manager) Run(ctx context.Context, evalInterval time.Duration) {
+ m.wg.Add(1)
+ defer m.wg.Done()
+
+ ticker := time.NewTicker(evalInterval)
+ defer ticker.Stop()
+
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case <-ticker.C:
+ if err := m.evaluatePendingSLAs(ctx); err != nil {
+ m.lo.Error("error processing pending SLAs", "error", err)
+ }
+ }
+ }
+}
+
+// Close closes the SLA evaluation loop by stopping the worker pool.
+func (m *Manager) Close() error {
+ m.wg.Wait()
+ return nil
+}
+
+// evaluatePendingSLAs fetches unbreached SLAs and evaluates them.
+// Here evaluation means checking if the SLA deadlines have been met or breached and updating timestamps accordingly.
+func (m *Manager) evaluatePendingSLAs(ctx context.Context) error {
+ var pendingSLAs []models.AppliedSLA
+ if err := m.q.GetPendingSLAs.SelectContext(ctx, &pendingSLAs); err != nil {
+ m.lo.Error("error fetching pending SLAs", "error", err)
+ return err
+ }
+ m.lo.Info("evaluating pending SLAs", "count", len(pendingSLAs))
+ for _, sla := range pendingSLAs {
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ default:
+ if err := m.evaluateSLA(sla); err != nil {
+ m.lo.Error("error evaluating SLA", "error", err)
+ }
+ }
+ }
+ m.lo.Info("evaluated pending SLAs", "count", len(pendingSLAs))
+ return nil
+}
+
+// evaluateSLA evaluates an SLA policy on an applied SLA.
+func (m *Manager) evaluateSLA(sla models.AppliedSLA) error {
+ now := time.Now()
+ checkDeadline := func(deadline time.Time, metAt null.Time, slaType string) error {
+ if deadline.IsZero() {
+ return nil
+ }
+ if !metAt.Valid && now.After(deadline) {
+ if _, err := m.q.UpdateBreach.Exec(sla.ID, slaType); err != nil {
+ return fmt.Errorf("updating SLA breach: %w", err)
+ }
+ return nil
+ }
+ if metAt.Valid {
+ if metAt.Time.After(deadline) {
+ if _, err := m.q.UpdateBreach.Exec(sla.ID, slaType); err != nil {
+ return fmt.Errorf("updating SLA breach: %w", err)
+ }
+ } else {
+ if _, err := m.q.UpdateMet.Exec(sla.ID, slaType); err != nil {
+ return fmt.Errorf("updating SLA met: %w", err)
+ }
+ }
+ }
+ return nil
+ }
+
+ if err := checkDeadline(sla.FirstResponseDeadlineAt, sla.FirstResponseAt, SLATypeFirstResponse); err != nil {
+ return err
+ }
+ if err := checkDeadline(sla.ResolutionDeadlineAt, sla.ResolvedAt, SLATypeResolution); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/internal/stringutil/stringutil.go b/internal/stringutil/stringutil.go
index f52329a8..777c0ba3 100644
--- a/internal/stringutil/stringutil.go
+++ b/internal/stringutil/stringutil.go
@@ -41,8 +41,8 @@ func SanitizeFilename(fName string) string {
return filepath.Base(name)
}
-// RandomAlNumString generates a random alphanumeric string of length n.
-func RandomAlNumString(n int) (string, error) {
+// RandomAlphanumeric generates a random alphanumeric string of length n.
+func RandomAlphanumeric(n int) (string, error) {
const dictionary = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
bytes := make([]byte, n)
@@ -58,8 +58,8 @@ func RandomAlNumString(n int) (string, error) {
return string(bytes), nil
}
-// RandomNumericString generates a random numeric string of length n.
-func RandomNumericString(n int) (string, error) {
+// RandomNumeric generates a random numeric string of length n.
+func RandomNumeric(n int) (string, error) {
const dictionary = "0123456789"
bytes := make([]byte, n)
@@ -76,10 +76,21 @@ func RandomNumericString(n int) (string, error) {
}
// GetPathFromURL extracts the path from a URL.
-func GetPathFromURL(rawURL string) (string, error) {
- parsedURL, err := url.Parse(rawURL)
+func GetPathFromURL(u string) (string, error) {
+ parsedURL, err := url.Parse(u)
if err != nil {
return "", err
}
return parsedURL.Path, nil
}
+
+// RemoveEmpty removes empty strings from a slice of strings.
+func RemoveEmpty(s []string) []string {
+ var r []string
+ for _, str := range s {
+ if str != "" {
+ r = append(r, str)
+ }
+ }
+ return r
+}
diff --git a/internal/tag/models/models.go b/internal/tag/models/models.go
index ab5807e0..02cb048d 100644
--- a/internal/tag/models/models.go
+++ b/internal/tag/models/models.go
@@ -5,5 +5,6 @@ import "time"
type Tag struct {
ID int `db:"id" json:"id"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdateAt time.Time `db:"updated_at" json:"updated_at"`
Name string `db:"name" json:"name"`
}
diff --git a/internal/tag/queries.sql b/internal/tag/queries.sql
index 2660fe21..f2bef48b 100644
--- a/internal/tag/queries.sql
+++ b/internal/tag/queries.sql
@@ -1,14 +1,29 @@
-- name: get-all-tags
-select id,
+select
+ id,
created_at,
+ updated_at,
name
-from tags;
+from
+ tags;
-- name: insert-tag
-INSERT into tags (name) values ($1);
+INSERT into
+ tags (name)
+values
+ ($1);
-- name: delete-tag
-DELETE from tags where id = $1;
+DELETE from
+ tags
+where
+ id = $1;
-- name: update-tag
-UPDATE tags set name = $2 where id = $1;
\ No newline at end of file
+UPDATE
+ tags
+set
+ name = $2,
+ updated_at = now()
+where
+ id = $1;
\ No newline at end of file
diff --git a/internal/tag/tag.go b/internal/tag/tag.go
index 7517a364..706dc097 100644
--- a/internal/tag/tag.go
+++ b/internal/tag/tag.go
@@ -4,9 +4,9 @@ package tag
import (
"embed"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/abhinavxd/artemis/internal/tag/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/tag/models"
"github.com/jmoiron/sqlx"
"github.com/zerodha/logf"
)
diff --git a/internal/team/models/models.go b/internal/team/models/models.go
index 21e0d60e..b542dd1f 100644
--- a/internal/team/models/models.go
+++ b/internal/team/models/models.go
@@ -5,14 +5,21 @@ import (
"encoding/json"
"fmt"
"time"
+
+ "github.com/volatiletech/null/v9"
)
type Team struct {
- ID int `db:"id" json:"id"`
- CreatedAt time.Time `db:"created_at" json:"created_at"`
- UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
- Name string `db:"name" json:"name"`
- AutoAssignConversations bool `db:"auto_assign_conversations" json:"auto_assign_conversations"`
+ ID int `db:"id" json:"id"`
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+ Emoji null.String `db:"emoji" json:"emoji"`
+ Name string `db:"name" json:"name"`
+ ConversationAssignmentType string `db:"conversation_assignment_type" json:"conversation_assignment_type,omitempty"`
+ Timezone string `db:"timezone" json:"timezone,omitempty"`
+ BusinessHoursID null.Int `db:"business_hours_id" json:"business_hours_id,omitempty"`
+ SLAPolicyID null.Int `db:"sla_policy_id" json:"sla_policy_id,omitempty"`
+ MaxAutoAssignedConversations int `db:"max_auto_assigned_conversations" json:"max_auto_assigned_conversations"`
}
type Teams []Team
@@ -48,9 +55,9 @@ func (t Teams) Names() []string {
// IDs returns a slice of all team IDs in the Teams slice.
func (t Teams) IDs() []int {
- ids := make([]int, len(t))
- for i, team := range t {
- ids[i] = team.ID
- }
- return ids
-}
\ No newline at end of file
+ ids := make([]int, len(t))
+ for i, team := range t {
+ ids[i] = team.ID
+ }
+ return ids
+}
diff --git a/internal/team/queries.sql b/internal/team/queries.sql
index becbf823..a32dd493 100644
--- a/internal/team/queries.sql
+++ b/internal/team/queries.sql
@@ -1,24 +1,27 @@
-- name: get-teams
-SELECT id, created_at, updated_at, name, auto_assign_conversations, disabled from teams order by updated_at desc;
+SELECT id, emoji, created_at, updated_at, name, conversation_assignment_type, timezone, max_auto_assigned_conversations from teams order by updated_at desc;
-- name: get-teams-compact
-SELECT id, name from teams order by name;
+SELECT id, name, emoji from teams order by name;
+
+-- name: get-user-teams
+SELECT id, emoji, created_at, updated_at, name, conversation_assignment_type, timezone, max_auto_assigned_conversations from teams WHERE id IN (SELECT team_id FROM team_members WHERE user_id = $1) order by updated_at desc;
-- name: get-team
-SELECT id, name, auto_assign_conversations from teams where id = $1;
+SELECT id, emoji, name, conversation_assignment_type, timezone, business_hours_id, sla_policy_id, max_auto_assigned_conversations from teams where id = $1;
-- name: get-team-members
SELECT u.id, t.id as team_id
FROM users u
JOIN team_members tm ON tm.user_id = u.id
JOIN teams t ON t.id = tm.team_id
-WHERE t.name = $1;
+WHERE t.id = $1;
-- name: insert-team
-INSERT INTO teams (name) values($1);
+INSERT INTO teams (name, timezone, conversation_assignment_type, business_hours_id, sla_policy_id, emoji, max_auto_assigned_conversations) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id;
-- name: update-team
-UPDATE teams set name = $2, auto_assign_conversations = $3, updated_at = now() where id = $1;
+UPDATE teams set name = $2, timezone = $3, conversation_assignment_type = $4, business_hours_id = $5, sla_policy_id = $6, emoji = $7, max_auto_assigned_conversations = $8, updated_at = now() where id = $1;
-- name: upsert-user-teams
WITH delete_old_teams AS (
@@ -36,4 +39,7 @@ insert_new_teams AS (
SELECT 1;
-- name: delete-team
-DELETE FROM teams where id = $1;
\ No newline at end of file
+DELETE FROM teams where id = $1;
+
+-- name: user-belongs-to-team
+SELECT EXISTS(SELECT 1 FROM team_members WHERE team_id = $1 AND user_id = $2);
\ No newline at end of file
diff --git a/internal/team/team.go b/internal/team/team.go
index df8c483e..6e658148 100644
--- a/internal/team/team.go
+++ b/internal/team/team.go
@@ -7,12 +7,13 @@ import (
"errors"
"fmt"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/abhinavxd/artemis/internal/team/models"
- umodels "github.com/abhinavxd/artemis/internal/user/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/team/models"
+ umodels "github.com/abhinavxd/libredesk/internal/user/models"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
+ "github.com/volatiletech/null/v9"
"github.com/zerodha/logf"
)
@@ -35,24 +36,24 @@ type Opts struct {
// queries contains prepared SQL queries.
type queries struct {
- GetTeams *sqlx.Stmt `query:"get-teams"`
- GetTeamsCompact *sqlx.Stmt `query:"get-teams-compact"`
- GetTeam *sqlx.Stmt `query:"get-team"`
- InsertTeam *sqlx.Stmt `query:"insert-team"`
- UpdateTeam *sqlx.Stmt `query:"update-team"`
- DeleteTeam *sqlx.Stmt `query:"delete-team"`
- GetTeamMembers *sqlx.Stmt `query:"get-team-members"`
- UpsertUserTeams *sqlx.Stmt `query:"upsert-user-teams"`
+ GetTeams *sqlx.Stmt `query:"get-teams"`
+ GetUserTeams *sqlx.Stmt `query:"get-user-teams"`
+ GetTeamsCompact *sqlx.Stmt `query:"get-teams-compact"`
+ GetTeam *sqlx.Stmt `query:"get-team"`
+ InsertTeam *sqlx.Stmt `query:"insert-team"`
+ UpdateTeam *sqlx.Stmt `query:"update-team"`
+ DeleteTeam *sqlx.Stmt `query:"delete-team"`
+ GetTeamMembers *sqlx.Stmt `query:"get-team-members"`
+ UpsertUserTeams *sqlx.Stmt `query:"upsert-user-teams"`
+ UserBelongsToTeam *sqlx.Stmt `query:"user-belongs-to-team"`
}
// New creates and returns a new instance of the Manager.
func New(opts Opts) (*Manager, error) {
var q queries
-
if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
return nil, err
}
-
return &Manager{
q: q,
lo: opts.Lo,
@@ -66,7 +67,7 @@ func (u *Manager) GetAll() ([]models.Team, error) {
if errors.Is(err, sql.ErrNoRows) {
return teams, nil
}
- u.lo.Error("error fetching teams from db", "error", err)
+ u.lo.Error("error fetching teams", "error", err)
return teams, envelope.NewError(envelope.GeneralError, "Error fetching teams", nil)
}
return teams, nil
@@ -79,19 +80,19 @@ func (u *Manager) GetAllCompact() ([]models.Team, error) {
if errors.Is(err, sql.ErrNoRows) {
return teams, nil
}
- u.lo.Error("error fetching teams from db", "error", err)
+ u.lo.Error("error fetching teams", "error", err)
return teams, envelope.NewError(envelope.GeneralError, "Error fetching teams", nil)
}
return teams, nil
}
-// GetTeam retrieves a team by ID.
-func (u *Manager) GetTeam(id int) (models.Team, error) {
+// Get retrieves a team by ID.
+func (u *Manager) Get(id int) (models.Team, error) {
var team models.Team
if err := u.q.GetTeam.Get(&team, id); err != nil {
if errors.Is(err, sql.ErrNoRows) {
u.lo.Error("team not found", "id", id, "error", err)
- return team, nil
+ return team, envelope.NewError(envelope.InputError, "Team not found", nil)
}
u.lo.Error("error fetching team", "id", id, "error", err)
return team, envelope.NewError(envelope.GeneralError, "Error fetching team", nil)
@@ -99,26 +100,29 @@ func (u *Manager) GetTeam(id int) (models.Team, error) {
return team, nil
}
-// CreateTeam creates a new team.
-func (u *Manager) CreateTeam(t models.Team) error {
- if _, err := u.q.InsertTeam.Exec(t.Name); err != nil {
+// Create creates a new team.
+func (u *Manager) Create(name, timezone, conversationAssignmentType string, businessHrsID, slaPolicyID null.Int, emoji string, maxAutoAssignedConversations int) error {
+ if _, err := u.q.InsertTeam.Exec(name, timezone, conversationAssignmentType, businessHrsID, slaPolicyID, emoji, maxAutoAssignedConversations); err != nil {
+ if dbutil.IsUniqueViolationError(err) {
+ return envelope.NewError(envelope.GeneralError, "Team with the same name already exists", nil)
+ }
u.lo.Error("error inserting team", "error", err)
return envelope.NewError(envelope.GeneralError, "Error creating team", nil)
}
return nil
}
-// UpdateTeam updates an existing team.
-func (u *Manager) UpdateTeam(id int, t models.Team) error {
- if _, err := u.q.UpdateTeam.Exec(id, t.Name, t.AutoAssignConversations); err != nil {
+// Update updates an existing team.
+func (u *Manager) Update(id int, name, timezone, conversationAssignmentType string, businessHrsID, slaPolicyID null.Int, emoji string, maxAutoAssignedConversations int) error {
+ if _, err := u.q.UpdateTeam.Exec(id, name, timezone, conversationAssignmentType, businessHrsID, slaPolicyID, emoji, maxAutoAssignedConversations); err != nil {
u.lo.Error("error updating team", "error", err)
return envelope.NewError(envelope.GeneralError, "Error updating team", nil)
}
return nil
}
-// DeleteTeam deletes a team by ID also deletes all the team members and unassigns all the conversations belonging to the team.
-func (u *Manager) DeleteTeam(id int) error {
+// Delete deletes a team by ID also deletes all the team members and unassigns all the conversations belonging to the team.
+func (u *Manager) Delete(id int) error {
if _, err := u.q.DeleteTeam.Exec(id); err != nil {
u.lo.Error("error deleting team", "error", err)
return envelope.NewError(envelope.GeneralError, "Error deleting team", nil)
@@ -126,17 +130,17 @@ func (u *Manager) DeleteTeam(id int) error {
return nil
}
-// GetTeamMembers retrieves members of a team by team name.
-func (u *Manager) GetTeamMembers(name string) ([]umodels.User, error) {
- var users []umodels.User
- if err := u.q.GetTeamMembers.Select(&users, name); err != nil {
+// GetUserTeams retrieves teams of a user by user ID.
+func (u *Manager) GetUserTeams(userID int) ([]models.Team, error) {
+ var teams = make([]models.Team, 0)
+ if err := u.q.GetUserTeams.Select(&teams, userID); err != nil {
if errors.Is(err, sql.ErrNoRows) {
- return users, nil
+ return teams, nil
}
- u.lo.Error("error fetching team members from db", "team_name", name, "error", err)
- return users, fmt.Errorf("fetching team members: %w", err)
+ u.lo.Error("error fetching teams", "user_id", userID, "error", err)
+ return teams, envelope.NewError(envelope.GeneralError, "Error fetching teams", nil)
}
- return users, nil
+ return teams, nil
}
// UpsertUserTeams updates/inserts exists user teams
@@ -147,3 +151,26 @@ func (u *Manager) UpsertUserTeams(id int, teamNames []string) error {
}
return nil
}
+
+// UserBelongsToTeam returns true if the user belongs to the team.
+func (u *Manager) UserBelongsToTeam(teamID, userID int) (bool, error) {
+ var exists bool
+ if err := u.q.UserBelongsToTeam.Get(&exists, teamID, userID); err != nil {
+ u.lo.Error("error fetching team members", "team_id", teamID, "user_id", userID, "error", err)
+ return false, envelope.NewError(envelope.GeneralError, "Error fetching team members", nil)
+ }
+ return exists, nil
+}
+
+// GetMembers retrieves members of a team.
+func (u *Manager) GetMembers(id int) ([]umodels.User, error) {
+ var users []umodels.User
+ if err := u.q.GetTeamMembers.Select(&users, id); err != nil {
+ if errors.Is(err, sql.ErrNoRows) {
+ return users, nil
+ }
+ u.lo.Error("error fetching team members", "team_id", id, "error", err)
+ return users, fmt.Errorf("fetching team members: %w", err)
+ }
+ return users, nil
+}
diff --git a/internal/template/models/models.go b/internal/template/models/models.go
index 1d138462..61b000ab 100644
--- a/internal/template/models/models.go
+++ b/internal/template/models/models.go
@@ -1,12 +1,19 @@
package models
-import "time"
+import (
+ "time"
+
+ "github.com/volatiletech/null/v9"
+)
type Template struct {
- ID int `db:"id" json:"id"`
- CreatedAt time.Time `db:"created_at" json:"created_at"`
- UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
- Name string `db:"name" json:"name"`
- Body string `db:"body" json:"body"`
- IsDefault bool `db:"is_default" json:"is_default"`
+ ID int `db:"id" json:"id"`
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+ Type string `db:"type" json:"type"`
+ Name string `db:"name" json:"name"`
+ Subject null.String `db:"subject" json:"subject"`
+ Body string `db:"body" json:"body"`
+ IsDefault bool `db:"is_default" json:"is_default"`
+ IsBuiltIn bool `db:"is_builtin" json:"is_builtin"`
}
diff --git a/internal/template/queries.sql b/internal/template/queries.sql
index 269db789..a69c43af 100644
--- a/internal/template/queries.sql
+++ b/internal/template/queries.sql
@@ -1,25 +1,38 @@
-- name: insert
-INSERT INTO templates ("name", body, is_default)
-VALUES ($1, $2, $3);
+INSERT INTO templates ("name", body, is_default, subject, type)
+VALUES ($1, $2, $3, $4, $5);
-- name: update
WITH u AS (
- UPDATE templates
- SET name = $2, body = $3, is_default = $4, updated_at = NOW()
+ UPDATE templates
+ SET
+ name = CASE WHEN $6::template_type = 'email_outgoing' THEN $2 ELSE name END,
+ body = $3,
+ is_default = $4,
+ subject = $5,
+ type = $6::template_type,
+ updated_at = NOW()
WHERE id = $1
+ RETURNING id
)
-UPDATE templates
-SET is_default = FALSE
+UPDATE templates
+SET is_default = FALSE
WHERE id != $1 AND $4 = TRUE;
-- name: get-default
-SELECT id, name, body FROM templates WHERE is_default = TRUE;
+SELECT id, type, name, body, subject FROM templates WHERE is_default is TRUE;
-- name: get-all
-SELECT * FROM templates ORDER BY updated_at DESC;
+SELECT id, type, name, is_default, updated_at FROM templates WHERE type = $1 ORDER BY updated_at DESC;
-- name: get-template
-SELECT * FROM templates WHERE id = $1;
+SELECT id, type, name, body, subject, is_default, type FROM templates WHERE id = $1;
-- name: delete
DELETE FROM templates WHERE id = $1;
+
+-- name: get-by-name
+SELECT id, type, name, body, subject, is_default, type FROM templates WHERE name = $1;
+
+-- name: is-builtin
+SELECT EXISTS(SELECT 1 FROM templates WHERE id = $1 AND is_builtin is TRUE);
\ No newline at end of file
diff --git a/internal/template/render.go b/internal/template/render.go
index a548ad8e..7b300eca 100644
--- a/internal/template/render.go
+++ b/internal/template/render.go
@@ -6,65 +6,157 @@ import (
"strings"
"text/template"
- "github.com/abhinavxd/artemis/internal/conversation/models"
+ "github.com/valyala/fasthttp"
)
const (
- TmplConversationAssigned = "conversation-assigned"
- TmplResetPassword = "reset-password"
- TmplWelcome = "welcome"
- TmplBase = "base"
- TmplContent = "content"
+ // Built-in templates names stored in the database.
+ TmplConversationAssigned = "Conversation assigned"
+
+ // Built-in templates fetched from memory stored in `static` directory.
+ TmplResetPassword = "reset-password"
+ TmplWelcome = "welcome"
+
+ // Template names for rendering.
+ TmplBase = "base"
+ TmplContent = "content"
)
-// RenderEmail renders a message into the base email template. It combines the base template
-// with message content and conversation data to produce the final email HTML.
-// The base template must contain a {{ template "content" . }} block where the message
-// will be inserted.
-func (m *Manager) RenderEmail(conversation models.Conversation, messageContent string) (string, error) {
- tmpl, err := m.GetDefault()
+// RenderWithBaseTemplate merges the given content with the default outgoing email template, if available.
+func (m *Manager) RenderWithBaseTemplate(data any, content string) (string, error) {
+ m.mutex.RLock()
+ defer m.mutex.RUnlock()
+ defaultTmpl, err := m.getDefaultOutgoingEmailTemplate()
if err != nil {
if err == ErrTemplateNotFound {
- m.lo.Warn("default email template not found, using message content as is")
- return messageContent, nil
+ m.lo.Warn("default outgoing email template not found, rendering content any template")
+ return content, nil
}
return "", err
}
- // Parse base template first
- baseTmpl, err := template.New(TmplBase).Parse(tmpl.Body)
+ baseTemplate, err := template.New(TmplBase).Funcs(m.funcMap).Parse(defaultTmpl.Body)
if err != nil {
return "", fmt.Errorf("parsing base template: %w", err)
}
- // Parse message template
- msgTmpl, err := template.New(TmplContent).Parse(messageContent)
+ contentTemplate, err := template.New(TmplContent).Funcs(m.funcMap).Parse(content)
if err != nil {
- return "", fmt.Errorf("parsing message template: %w", err)
+ return "", fmt.Errorf("parsing content template: %w", err)
}
- // Add message template to base
- baseTmpl, err = baseTmpl.AddParseTree(TmplContent, msgTmpl.Tree)
+ baseTemplate, err = baseTemplate.AddParseTree(TmplContent, contentTemplate.Tree)
if err != nil {
- return "", fmt.Errorf("adding content template to base: %w", err)
+ return "", fmt.Errorf("adding content template: %w", err)
}
- var out strings.Builder
- if err := baseTmpl.ExecuteTemplate(&out, TmplBase, conversation); err != nil {
- return "", fmt.Errorf("executing template: %w", err)
- }
-
- return out.String(), nil
-}
-
-// Render executes a named template with the provided data.
-func (m *Manager) Render(name string, data interface{}) (string, error) {
- var rendered bytes.Buffer
-
- err := m.tpls.ExecuteTemplate(&rendered, name, data)
- if err != nil {
- return "", fmt.Errorf("executing template %s: %w", name, err)
+ var rendered strings.Builder
+ if err := baseTemplate.ExecuteTemplate(&rendered, TmplBase, data); err != nil {
+ return "", fmt.Errorf("executing base template: %w", err)
}
return rendered.String(), nil
}
+
+// RenderNamedTemplate fetches a named template from DB and merges it with the default base template, if available.
+func (m *Manager) RenderNamedTemplate(name string, data any) (string, string, error) {
+ tmpl, err := m.getByName(name)
+ if err != nil {
+ if err == ErrTemplateNotFound {
+ return "", "", fmt.Errorf("template %s not found", name)
+ }
+ return "", "", err
+ }
+
+ executeContentTemplate := func(tmplBody string) (string, error) {
+ var sb strings.Builder
+ t, err := template.New(name).Funcs(m.funcMap).Parse(tmplBody)
+ if err != nil {
+ return "", fmt.Errorf("parsing content template: %w", err)
+ }
+ if err := t.Execute(&sb, data); err != nil {
+ return "", fmt.Errorf("executing content template: %w", err)
+ }
+ return sb.String(), nil
+ }
+
+ executeSubjectTemplate := func(subject string) (string, error) {
+ var sb strings.Builder
+ subjectTmpl, err := template.New("subject").Funcs(m.funcMap).Parse(subject)
+ if err != nil {
+ return "", fmt.Errorf("parsing subject template: %w", err)
+ }
+ if err := subjectTmpl.Execute(&sb, data); err != nil {
+ return "", fmt.Errorf("executing subject template: %w", err)
+ }
+ return sb.String(), nil
+ }
+
+ defaultTmpl, err := m.getDefaultOutgoingEmailTemplate()
+ if err != nil {
+ if err == ErrTemplateNotFound {
+ m.lo.Warn("default outgoing email template not found, rendering content any template")
+ content, err := executeContentTemplate(tmpl.Body)
+ if err != nil {
+ return "", "", err
+ }
+ subject, err := executeSubjectTemplate(tmpl.Subject.String)
+ if err != nil {
+ return "", "", err
+ }
+ return content, subject, nil
+ }
+ return "", "", err
+ }
+
+ baseTemplate, err := template.New(TmplBase).Funcs(m.funcMap).Parse(defaultTmpl.Body)
+ if err != nil {
+ return "", "", fmt.Errorf("parsing base template: %w", err)
+ }
+
+ contentTemplate, err := template.New(TmplContent).Funcs(m.funcMap).Parse(tmpl.Body)
+ if err != nil {
+ return "", "", fmt.Errorf("parsing content template: %w", err)
+ }
+
+ baseTemplate, err = baseTemplate.AddParseTree(TmplContent, contentTemplate.Tree)
+ if err != nil {
+ return "", "", fmt.Errorf("adding content template: %w", err)
+ }
+
+ var rendered strings.Builder
+ if err := baseTemplate.ExecuteTemplate(&rendered, TmplBase, data); err != nil {
+ return "", "", fmt.Errorf("executing base template: %w", err)
+ }
+
+ subject, err := executeSubjectTemplate(tmpl.Subject.String)
+ if err != nil {
+ return "", "", err
+ }
+
+ return rendered.String(), subject, nil
+}
+
+// RenderTemplate executes a named in-memory template with the provided data.
+func (m *Manager) RenderTemplate(name string, data interface{}) (string, error) {
+ m.mutex.RLock()
+ defer m.mutex.RUnlock()
+ var buf bytes.Buffer
+ if err := m.tpls.ExecuteTemplate(&buf, name, data); err != nil {
+ return "", fmt.Errorf("executing in-memory template %q: %w", name, err)
+ }
+ return buf.String(), nil
+}
+
+// RenderWebPage renders a template to the http.ResponseWriter with data.
+func (m *Manager) RenderWebPage(ctx *fasthttp.RequestCtx, tmplFile string, data map[string]interface{}) error {
+ m.mutex.RLock()
+ defer m.mutex.RUnlock()
+ ctx.SetContentType("text/html; charset=utf-8")
+ ctx.SetStatusCode(fasthttp.StatusOK)
+ // Add no-cache headers
+ ctx.Response.Header.Set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0")
+ ctx.Response.Header.Set("Pragma", "no-cache")
+ ctx.Response.Header.Set("Expires", "0")
+ return m.webTpls.ExecuteTemplate(ctx, tmplFile, data)
+}
diff --git a/internal/template/template.go b/internal/template/template.go
index d119732b..d2a989db 100644
--- a/internal/template/template.go
+++ b/internal/template/template.go
@@ -6,26 +6,31 @@ import (
"embed"
"errors"
"html/template"
+ "sync"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/abhinavxd/artemis/internal/template/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/template/models"
"github.com/jmoiron/sqlx"
"github.com/zerodha/logf"
)
var (
//go:embed queries.sql
- efs embed.FS
-
- ErrTemplateNotFound = errors.New("template not found")
+ efs embed.FS
+ ErrTemplateNotFound = errors.New("template not found")
+ TypeEmailOutgoing = "email_outgoing"
+ TypeEmailNotification = "email_notification"
)
// Manager handles template-related operations.
type Manager struct {
- tpls *template.Template
- q queries
- lo *logf.Logger
+ mutex sync.RWMutex
+ tpls *template.Template
+ webTpls *template.Template
+ funcMap template.FuncMap
+ q queries
+ lo *logf.Logger
}
// queries contains prepared SQL queries.
@@ -36,20 +41,29 @@ type queries struct {
GetDefaultTemplate *sqlx.Stmt `query:"get-default"`
GetAllTemplates *sqlx.Stmt `query:"get-all"`
GetTemplate *sqlx.Stmt `query:"get-template"`
+ GetByName *sqlx.Stmt `query:"get-by-name"`
+ IsBuiltIn *sqlx.Stmt `query:"is-builtin"`
}
// New creates and returns a new instance of the Manager.
-func New(lo *logf.Logger, db *sqlx.DB, tpls *template.Template) (*Manager, error) {
+func New(lo *logf.Logger, db *sqlx.DB, webTpls *template.Template, tpls *template.Template, funcMap template.FuncMap) (*Manager, error) {
var q queries
if err := dbutil.ScanSQLFile("queries.sql", &q, db, efs); err != nil {
return nil, err
}
- return &Manager{tpls, q, lo}, nil
+ return &Manager{
+ mutex: sync.RWMutex{},
+ tpls: tpls,
+ webTpls: webTpls,
+ funcMap: funcMap,
+ q: q,
+ lo: lo,
+ }, nil
}
// Update updates a new template with the given name, and body.
func (m *Manager) Update(id int, t models.Template) error {
- if _, err := m.q.UpdateTemplate.Exec(id, t.Name, t.Body, t.IsDefault); err != nil {
+ if _, err := m.q.UpdateTemplate.Exec(id, t.Name, t.Body, t.IsDefault, t.Subject, t.Type); err != nil {
m.lo.Error("error updating template", "error", err)
return envelope.NewError(envelope.GeneralError, "Error updating template", nil)
}
@@ -58,15 +72,71 @@ func (m *Manager) Update(id int, t models.Template) error {
// Create creates a template.
func (m *Manager) Create(t models.Template) error {
- if _, err := m.q.InsertTemplate.Exec(t.Name, t.Body, t.IsDefault); err != nil {
+ if t.IsDefault {
+ t.Type = TypeEmailOutgoing
+ }
+ if _, err := m.q.InsertTemplate.Exec(t.Name, t.Body, t.IsDefault, t.Subject, t.Type); err != nil {
+ if dbutil.IsUniqueViolationError(err) && t.IsDefault {
+ return envelope.NewError(envelope.GeneralError, "Default template already exists", nil)
+ }
m.lo.Error("error inserting template", "error", err)
return envelope.NewError(envelope.GeneralError, "Error creating template", nil)
}
return nil
}
-// GetDefault retrieves the default template.
-func (m *Manager) GetDefault() (models.Template, error) {
+// GetAll returns all templates by type.
+func (m *Manager) GetAll(typ string) ([]models.Template, error) {
+ var templates = make([]models.Template, 0)
+ if err := m.q.GetAllTemplates.Select(&templates, typ); err != nil {
+ m.lo.Error("error fetching templates", "error", err)
+ return templates, envelope.NewError(envelope.GeneralError, "Error fetching templates", nil)
+ }
+ return templates, nil
+}
+
+// Get returns a template by id.
+func (m *Manager) Get(id int) (models.Template, error) {
+ var templates = models.Template{}
+ if err := m.q.GetTemplate.Get(&templates, id); err != nil {
+ if err == sql.ErrNoRows {
+ return templates, envelope.NewError(envelope.NotFoundError, "Template not found", nil)
+ }
+ m.lo.Error("error fetching template", "error", err)
+ return templates, envelope.NewError(envelope.GeneralError, "Error fetching template", nil)
+ }
+ return templates, nil
+}
+
+// Delete deletes a template by id.
+func (m *Manager) Delete(id int) error {
+ // Do not allow deletion of built-in templates.
+ isBuiltIn, err := m.isBuiltIn(id)
+ if err != nil {
+ return err
+ }
+ if isBuiltIn {
+ return envelope.NewError(envelope.PermissionError, "Cannot delete built-in templates", nil)
+ }
+ if _, err := m.q.DeleteTemplate.Exec(id); err != nil {
+ m.lo.Error("error deleting template", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error deleting template", nil)
+ }
+ return nil
+}
+
+// isBuiltIn returns true if the template is built-in.
+func (m *Manager) isBuiltIn(id int) (bool, error) {
+ var isBuiltIn bool
+ if err := m.q.IsBuiltIn.Get(&isBuiltIn, id); err != nil {
+ m.lo.Error("error fetching template", "error", err)
+ return false, envelope.NewError(envelope.GeneralError, "Error fetching template", nil)
+ }
+ return isBuiltIn, nil
+}
+
+// getDefaultOutgoingEmailTemplate returns the default outgoing email template.
+func (m *Manager) getDefaultOutgoingEmailTemplate() (models.Template, error) {
var template models.Template
if err := m.q.GetDefaultTemplate.Get(&template); err != nil {
if err == sql.ErrNoRows {
@@ -78,31 +148,25 @@ func (m *Manager) GetDefault() (models.Template, error) {
return template, nil
}
-// GetAll returns all templates.
-func (m *Manager) GetAll() ([]models.Template, error) {
- var templates = make([]models.Template, 0)
- if err := m.q.GetAllTemplates.Select(&templates); err != nil {
- m.lo.Error("error fetching templates", "error", err)
- return templates, envelope.NewError(envelope.GeneralError, "Error fetching templates", nil)
+// getByName returns a template by name.
+func (m *Manager) getByName(name string) (models.Template, error) {
+ var template models.Template
+ if err := m.q.GetByName.Get(&template, name); err != nil {
+ if err == sql.ErrNoRows {
+ return template, ErrTemplateNotFound
+ }
+ m.lo.Error("error fetching default template", "error", err)
+ return template, envelope.NewError(envelope.GeneralError, "Error fetching template", nil)
}
- return templates, nil
+ return template, nil
}
-// Get returns a template by id.
-func (m *Manager) Get(id int) (models.Template, error) {
- var templates = models.Template{}
- if err := m.q.GetTemplate.Get(&templates, id); err != nil {
- m.lo.Error("error fetching template", "error", err)
- return templates, envelope.NewError(envelope.GeneralError, "Error fetching template", nil)
- }
- return templates, nil
-}
-
-// Delete deletes a template by id.
-func (m *Manager) Delete(id int) error {
- if _, err := m.q.DeleteTemplate.Exec(id); err != nil {
- m.lo.Error("error deleting template", "error", err)
- return envelope.NewError(envelope.GeneralError, "Error deleting template", nil)
- }
+// Reload reloads the templates and function map.
+func (m *Manager) Reload(webTpls, tpls *template.Template, funcMap template.FuncMap) error {
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+ m.webTpls = webTpls
+ m.tpls = tpls
+ m.funcMap = funcMap
return nil
}
diff --git a/internal/user/contact.go b/internal/user/contact.go
new file mode 100644
index 00000000..6195f64f
--- /dev/null
+++ b/internal/user/contact.go
@@ -0,0 +1,27 @@
+package user
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/abhinavxd/libredesk/internal/user/models"
+ "github.com/volatiletech/null/v9"
+)
+
+// CreateContact creates a new contact user.
+func (u *Manager) CreateContact(user *models.User) error {
+ password, err := u.generatePassword()
+ if err != nil {
+ u.lo.Error("generating password", "error", err)
+ return fmt.Errorf("generating password: %w", err)
+ }
+
+ // Normalize email address.
+ user.Email = null.NewString(strings.ToLower(user.Email.String), user.Email.Valid)
+
+ if err := u.q.InsertContact.QueryRow(user.Email, user.FirstName, user.LastName, password, user.AvatarURL, user.InboxID, user.SourceChannelID).Scan(&user.ID, &user.ContactChannelID); err != nil {
+ u.lo.Error("error inserting contact", "error", err)
+ return fmt.Errorf("insert contact: %w", err)
+ }
+ return nil
+}
diff --git a/internal/user/models/models.go b/internal/user/models/models.go
index dd6a819c..ef15aee9 100644
--- a/internal/user/models/models.go
+++ b/internal/user/models/models.go
@@ -3,26 +3,34 @@ package models
import (
"time"
- tmodels "github.com/abhinavxd/artemis/internal/team/models"
+ tmodels "github.com/abhinavxd/libredesk/internal/team/models"
"github.com/lib/pq"
"github.com/volatiletech/null/v9"
)
type User struct {
- ID int `db:"id" json:"id"`
+ ID int `db:"id" json:"id,omitempty"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
FirstName string `db:"first_name" json:"first_name"`
LastName string `db:"last_name" json:"last_name"`
- Email string `db:"email" json:"email,omitempty"`
+ Email null.String `db:"email" json:"email,omitempty"`
+ Type string `db:"type" json:"type"`
+ PhoneNumber null.String `db:"phone_number" json:"phone_number,omitempty"`
AvatarURL null.String `db:"avatar_url" json:"avatar_url"`
- Disabled bool `db:"disabled" json:"disabled"`
+ Enabled bool `db:"enabled" json:"enabled"`
Password string `db:"password" json:"-"`
+ Roles pq.StringArray `db:"roles" json:"roles,omitempty"`
+ Permissions pq.StringArray `db:"permissions" json:"permissions,omitempty"`
+ Meta pq.StringArray `db:"meta" json:"meta,omitempty"`
+ CustomAttributes pq.StringArray `db:"custom_attributes" json:"custom_attributes,omitempty"`
+ Teams tmodels.Teams `db:"teams" json:"teams,omitempty"`
+ ContactChannelID int `db:"contact_channel_id" json:"contact_channel_id,omitempty"`
NewPassword string `db:"-" json:"new_password,omitempty"`
SendWelcomeEmail bool `db:"-" json:"send_welcome_email,omitempty"`
- Roles pq.StringArray `db:"roles" json:"roles"`
- Permissions pq.StringArray `db:"permissions" json:"permissions"`
- Teams tmodels.Teams `db:"teams" json:"teams"`
+ InboxID int `json:"-"`
+ SourceChannel null.String `json:"-"`
+ SourceChannelID null.String `json:"-"`
}
func (u *User) FullName() string {
diff --git a/internal/user/queries.sql b/internal/user/queries.sql
index a35e3916..12431f36 100644
--- a/internal/user/queries.sql
+++ b/internal/user/queries.sql
@@ -1,89 +1,135 @@
-- name: get-users
-SELECT u.id, u.updated_at, u.first_name, u.last_name, u.email, u.disabled
-FROM users u where u.email != 'System' and u.deleted_at is null
+SELECT u.id, u.updated_at, u.first_name, u.last_name, u.email, u.enabled
+FROM users u
+WHERE u.email != 'System' AND u.deleted_at IS NULL AND u.type = 'agent'
ORDER BY u.updated_at DESC;
-- name: soft-delete-user
-UPDATE users SET deleted_at = now() WHERE id = $1;
+UPDATE users
+SET deleted_at = now(), updated_at = now()
+WHERE id = $1 AND type = 'agent';
-- name: get-users-compact
-SELECT u.id, u.first_name, u.last_name, u.disabled
-FROM users u where u.email != 'System' and u.deleted_at is null
+SELECT u.id, u.first_name, u.last_name, u.enabled, u.avatar_url
+FROM users u
+WHERE u.email != 'System' AND u.deleted_at IS NULL AND u.type = 'agent'
ORDER BY u.updated_at DESC;
-- name: get-email
-SELECT email from users where id = $1 and deleted_at is null;
+SELECT email
+FROM users
+WHERE id = $1 AND deleted_at IS NULL AND type = 'agent';
-- name: get-user-by-email
-SELECT u.id, u.email, u.password, u.avatar_url, u.first_name, u.last_name, r.permissions
+SELECT u.id, u.email, u.password, u.avatar_url, u.first_name, u.last_name, u.enabled,
+ array_agg(DISTINCT r.name) as roles,
+ array_agg(DISTINCT p) as permissions
FROM users u
-JOIN roles r ON r.name = ANY(u.roles)
-WHERE u.email = $1 and u.deleted_at is null;
+JOIN user_roles ur ON ur.user_id = u.id
+JOIN roles r ON r.id = ur.role_id,
+ unnest(r.permissions) p
+WHERE u.email = $1 AND u.deleted_at IS NULL AND u.type = 'agent'
+GROUP BY u.id;
-- name: get-user
SELECT
- u.id,
- u.email,
- u.avatar_url,
- u.first_name,
- u.last_name,
- u.roles,
- COALESCE(
- (SELECT json_agg(json_build_object('id', t.id, 'name', t.name))
- FROM team_members tm
- JOIN teams t ON tm.team_id = t.id
- WHERE tm.user_id = u.id),
- '[]'
- ) AS teams,
- COALESCE(
- ARRAY(
- SELECT DISTINCT unnest(r.permissions)
- FROM roles r
- WHERE r.name = ANY(u.roles)
- ),
- ARRAY[]::text[]
- ) AS permissions
-FROM
- users u
-WHERE
- u.id = $1 and u.deleted_at is null;
+ u.id,
+ u.created_at,
+ u.updated_at,
+ u.enabled,
+ u.email,
+ u.avatar_url,
+ u.first_name,
+ u.last_name,
+ array_agg(DISTINCT r.name) as roles,
+ COALESCE(
+ (SELECT json_agg(json_build_object('id', t.id, 'name', t.name, 'emoji', t.emoji))
+ FROM team_members tm
+ JOIN teams t ON tm.team_id = t.id
+ WHERE tm.user_id = u.id),
+ '[]'
+ ) AS teams,
+ array_agg(DISTINCT p) as permissions
+FROM users u
+LEFT JOIN user_roles ur ON ur.user_id = u.id
+LEFT JOIN roles r ON r.id = ur.role_id,
+ unnest(r.permissions) p
+WHERE u.id = $1 AND u.deleted_at IS NULL AND u.type = 'agent'
+GROUP BY u.id;
-- name: set-user-password
-update users set password = $1, updated_at = now() where id = $2;
-
--- name: create-user
-INSERT INTO users
-(email, first_name, last_name, "password", avatar_url, roles)
-VALUES($1, $2, $3, $4, $5, $6)
-RETURNING id;
+UPDATE users
+SET password = $1, updated_at = now()
+WHERE id = $2 AND type = 'agent';
-- name: update-user
+WITH not_removed_roles AS (
+ SELECT r.id FROM unnest($5::text[]) role_name
+ JOIN roles r ON r.name = role_name
+),
+old_roles AS (
+ DELETE FROM user_roles
+ WHERE user_id = $1
+ AND role_id NOT IN (SELECT id FROM not_removed_roles)
+),
+new_roles AS (
+ INSERT INTO user_roles (user_id, role_id)
+ SELECT $1, r.id FROM not_removed_roles r
+ ON CONFLICT (user_id, role_id) DO NOTHING
+)
UPDATE users
SET first_name = COALESCE($2, first_name),
- last_name = COALESCE($3, last_name),
- email = COALESCE($4, email),
- roles = COALESCE($5, roles),
- avatar_url = COALESCE($6, avatar_url),
- password = COALESCE($7, password),
- updated_at = now()
-WHERE id = $1
+ last_name = COALESCE($3, last_name),
+ email = COALESCE($4, email),
+ avatar_url = COALESCE($6, avatar_url),
+ password = COALESCE($7, password),
+ enabled = COALESCE($8, enabled),
+ updated_at = now()
+WHERE id = $1 AND type = 'agent';
-- name: update-avatar
-UPDATE users
-SET avatar_url = $2, updated_at = now() WHERE id = $1;
+UPDATE users
+SET avatar_url = $2, updated_at = now()
+WHERE id = $1 AND type = 'agent';
-- name: get-permissions
-SELECT unnest(r.permissions)
+SELECT DISTINCT unnest(r.permissions)
FROM users u
-JOIN roles r ON r.name = ANY(u.roles)
-WHERE u.id = $1
+JOIN user_roles ur ON ur.user_id = u.id
+JOIN roles r ON r.id = ur.role_id
+WHERE u.id = $1 AND u.type = 'agent';
-- name: set-reset-password-token
UPDATE users
SET reset_password_token = $2, reset_password_token_expiry = now() + interval '1 day'
-WHERE id = $1
+WHERE id = $1 AND type = 'agent';
-- name: reset-password
-UPDATE users
+UPDATE users
SET password = $1, reset_password_token = NULL, reset_password_token_expiry = NULL
-WHERE reset_password_token = $2 AND reset_password_token_expiry > now()
\ No newline at end of file
+WHERE reset_password_token = $2 AND reset_password_token_expiry > now() AND type = 'agent';
+
+-- name: insert-agent
+WITH inserted_user AS (
+ INSERT INTO users (email, type, first_name, last_name, "password", avatar_url)
+ VALUES ($1, 'agent', $2, $3, $4, $5)
+ RETURNING id AS user_id
+)
+INSERT INTO user_roles (user_id, role_id)
+SELECT inserted_user.user_id, r.id
+FROM inserted_user, unnest($6::text[]) role_name
+JOIN roles r ON r.name = role_name
+RETURNING user_id;
+
+-- name: insert-contact
+WITH contact AS (
+ INSERT INTO users (email, type, first_name, last_name, "password", avatar_url)
+ VALUES ($1, 'contact', $2, $3, $4, $5)
+ ON CONFLICT (email, type) WHERE deleted_at IS NULL
+ DO UPDATE SET updated_at = now()
+ RETURNING id
+)
+INSERT INTO contact_channels (contact_id, inbox_id, identifier)
+VALUES ((SELECT id FROM contact), $6, $7)
+ON CONFLICT (contact_id, inbox_id) DO UPDATE SET updated_at = now()
+RETURNING contact_id, id;
\ No newline at end of file
diff --git a/internal/user/user.go b/internal/user/user.go
index 6998694d..00bf8f85 100644
--- a/internal/user/user.go
+++ b/internal/user/user.go
@@ -2,17 +2,20 @@
package user
import (
+ "context"
"database/sql"
"embed"
"errors"
"fmt"
+ "os"
"regexp"
"strings"
- "github.com/abhinavxd/artemis/internal/dbutil"
- "github.com/abhinavxd/artemis/internal/envelope"
- "github.com/abhinavxd/artemis/internal/stringutil"
- "github.com/abhinavxd/artemis/internal/user/models"
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ rmodels "github.com/abhinavxd/libredesk/internal/role/models"
+ "github.com/abhinavxd/libredesk/internal/stringutil"
+ "github.com/abhinavxd/libredesk/internal/user/models"
"github.com/jmoiron/sqlx"
"github.com/knadh/go-i18n"
"github.com/lib/pq"
@@ -34,6 +37,8 @@ const (
SystemUserEmail = "System"
MinSystemUserPasswordLen = 8
MaxSystemUserPasswordLen = 50
+ UserTypeAgent = "agent"
+ UserTypeContact = "contact"
)
// Manager handles user-related operations.
@@ -51,7 +56,6 @@ type Opts struct {
// queries contains prepared SQL queries.
type queries struct {
- CreateUser *sqlx.Stmt `query:"create-user"`
GetUsers *sqlx.Stmt `query:"get-users"`
GetUserCompact *sqlx.Stmt `query:"get-users-compact"`
GetUser *sqlx.Stmt `query:"get-user"`
@@ -64,16 +68,16 @@ type queries struct {
SetUserPassword *sqlx.Stmt `query:"set-user-password"`
SetResetPasswordToken *sqlx.Stmt `query:"set-reset-password-token"`
ResetPassword *sqlx.Stmt `query:"reset-password"`
+ InsertAgent *sqlx.Stmt `query:"insert-agent"`
+ InsertContact *sqlx.Stmt `query:"insert-contact"`
}
// New creates and returns a new instance of the Manager.
func New(i18n *i18n.I18n, opts Opts) (*Manager, error) {
var q queries
-
if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
return nil, err
}
-
return &Manager{
q: q,
lo: opts.Lo,
@@ -81,8 +85,8 @@ func New(i18n *i18n.I18n, opts Opts) (*Manager, error) {
}, nil
}
-// Login authenticates a user by email and password.
-func (u *Manager) Login(email string, password []byte) (models.User, error) {
+// VerifyPassword authenticates a user by email and password.
+func (u *Manager) VerifyPassword(email string, password []byte) (models.User, error) {
var user models.User
if err := u.q.GetUserByEmail.Get(&user, email); err != nil {
@@ -128,15 +132,18 @@ func (u *Manager) GetAllCompact() ([]models.User, error) {
return users, nil
}
-// Create creates a new user.
-func (u *Manager) Create(user *models.User) error {
+// CreateAgent creates a new agent user.
+func (u *Manager) CreateAgent(user *models.User) error {
password, err := u.generatePassword()
if err != nil {
u.lo.Error("error generating password", "error", err)
return envelope.NewError(envelope.GeneralError, "Error creating user", nil)
}
- user.Email = strings.ToLower(strings.TrimSpace(user.Email))
- if err := u.q.CreateUser.QueryRow(user.Email, user.FirstName, user.LastName, password, user.AvatarURL, pq.Array(user.Roles)).Scan(&user.ID); err != nil {
+ user.Email = null.NewString(strings.TrimSpace(strings.ToLower(user.Email.String)), user.Email.Valid)
+ if err := u.q.InsertAgent.QueryRow(user.Email, user.FirstName, user.LastName, password, user.AvatarURL, pq.Array(user.Roles)).Scan(&user.ID); err != nil {
+ if dbutil.IsUniqueViolationError(err) {
+ return envelope.NewError(envelope.GeneralError, "User with the same email already exists", nil)
+ }
u.lo.Error("error creating user", "error", err)
return envelope.NewError(envelope.GeneralError, "Error creating user", nil)
}
@@ -162,10 +169,10 @@ func (u *Manager) GetByEmail(email string) (models.User, error) {
var user models.User
if err := u.q.GetUserByEmail.Get(&user, email); err != nil {
if errors.Is(err, sql.ErrNoRows) {
- return user, fmt.Errorf("user not found")
+ return user, envelope.NewError(envelope.GeneralError, "User not found", nil)
}
u.lo.Error("error fetching user from db", "error", err)
- return user, err
+ return user, envelope.NewError(envelope.GeneralError, "Error fetching user", nil)
}
return user, nil
}
@@ -203,14 +210,14 @@ func (u *Manager) Update(id int, user models.User) error {
u.lo.Debug("setting new password for user", "user_id", id)
}
- if _, err := u.q.UpdateUser.Exec(id, user.FirstName, user.LastName, user.Email, pq.Array(user.Roles), user.AvatarURL, hashedPassword); err != nil {
+ if _, err := u.q.UpdateUser.Exec(id, user.FirstName, user.LastName, user.Email, pq.Array(user.Roles), user.AvatarURL, hashedPassword, user.Enabled); err != nil {
u.lo.Error("error updating user", "error", err)
return envelope.NewError(envelope.GeneralError, "Error updating user", nil)
}
return nil
}
-// Delete deletes a user by ID.
+// SoftDelete soft deletes a user.
func (u *Manager) SoftDelete(id int) error {
// Disallow if user is system user.
systemUser, err := u.GetSystemUser()
@@ -243,7 +250,7 @@ func (u *Manager) GetEmail(id int) (string, error) {
// SetResetPasswordToken sets a reset password token for a user and returns the token.
func (u *Manager) SetResetPasswordToken(id int) (string, error) {
- token, err := stringutil.RandomAlNumString(32)
+ token, err := stringutil.RandomAlphanumeric(32)
if err != nil {
u.lo.Error("error generating reset password token", "error", err)
return "", envelope.NewError(envelope.GeneralError, "Error generating reset password token", nil)
@@ -293,11 +300,11 @@ func (u *Manager) verifyPassword(pwd []byte, pwdHash string) error {
// generatePassword generates a random password and returns its bcrypt hash.
func (u *Manager) generatePassword() ([]byte, error) {
- password, _ := stringutil.RandomAlNumString(16)
+ password, _ := stringutil.RandomAlphanumeric(70)
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
u.lo.Error("error generating bcrypt password", "error", err)
- return nil, fmt.Errorf("error generating bcrypt password: %w", err)
+ return nil, fmt.Errorf("generating bcrypt password: %w", err)
}
return bytes, nil
}
@@ -312,29 +319,10 @@ func (u *Manager) isStrongPassword(password string) bool {
return hasUppercase && hasNumber
}
-// CreateSystemUser inserts a default system user into the users table with the prompted password.
-func CreateSystemUser(db *sqlx.DB) error {
- // Prompt for password and get hashed password
- hashedPassword, err := promptAndHashPassword()
- if err != nil {
- return err
- }
-
- _, err = db.Exec(`
- INSERT INTO users (email, first_name, last_name, password, roles)
- VALUES ($1, $2, $3, $4, $5)`,
- SystemUserEmail, "System", "", hashedPassword, pq.StringArray{"Admin"})
- if err != nil {
- return fmt.Errorf("failed to create system user: %v", err)
- }
- fmt.Println("System user created successfully")
- return nil
-}
-
// ChangeSystemUserPassword updates the system user's password with a newly prompted one.
-func ChangeSystemUserPassword(db *sqlx.DB) error {
+func ChangeSystemUserPassword(ctx context.Context, db *sqlx.DB) error {
// Prompt for password and get hashed password
- hashedPassword, err := promptAndHashPassword()
+ hashedPassword, err := promptAndHashPassword(ctx)
if err != nil {
return err
}
@@ -347,24 +335,56 @@ func ChangeSystemUserPassword(db *sqlx.DB) error {
return nil
}
-// promptAndHashPassword handles password input and validation, and returns the hashed password.
-func promptAndHashPassword() ([]byte, error) {
- var password string
- for {
- fmt.Print("Please set System admin password (min 8, max 50 characters, at least 1 uppercase letter, 1 number): ")
- fmt.Scanf("%s", &password)
- if isStrongSystemUserPassword(password) {
- break
- }
- fmt.Println("Password does not meet the strength requirements.")
- }
-
- // Hash the password using bcrypt.
- hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
+// CreateSystemUser inserts a default system user into the users table with the prompted password.
+func CreateSystemUser(ctx context.Context, db *sqlx.DB) error {
+ hashedPassword, err := promptAndHashPassword(ctx)
if err != nil {
- return nil, fmt.Errorf("failed to hash password: %v", err)
+ return err
+ }
+ _, err = db.Exec(`
+ WITH sys_user AS (
+ INSERT INTO users (email, type, first_name, last_name, password)
+ VALUES ($1, $2, $3, $4, $5)
+ RETURNING id
+ )
+ INSERT INTO user_roles (user_id, role_id)
+ SELECT sys_user.id, roles.id
+ FROM sys_user, roles
+ WHERE roles.name = $6`,
+ SystemUserEmail, UserTypeAgent, "System", "", hashedPassword, rmodels.RoleAdmin)
+ if err != nil {
+ return fmt.Errorf("failed to create system user: %v", err)
+ }
+ fmt.Println("System user created successfully")
+ return nil
+}
+
+// promptAndHashPassword handles password input and validation, and returns the hashed password.
+func promptAndHashPassword(ctx context.Context) ([]byte, error) {
+ for {
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ default:
+ fmt.Print("Please set System admin password (min 8, max 50 characters, at least 1 uppercase letter, 1 number): ")
+ buffer := make([]byte, 256)
+ n, err := os.Stdin.Read(buffer)
+ if err != nil {
+ return nil, fmt.Errorf("error reading input: %v", err)
+ }
+
+ password := strings.TrimSpace(string(buffer[:n]))
+ if isStrongSystemUserPassword(password) {
+ // Hash the password using bcrypt.
+ hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
+ if err != nil {
+ return nil, fmt.Errorf("failed to hash password: %v", err)
+ }
+ return hashedPassword, nil
+ }
+ fmt.Println("Password does not meet the strength requirements.")
+ }
}
- return hashedPassword, nil
}
// updateSystemUserPassword updates the password of the system user in the database.
diff --git a/internal/view/models/models.go b/internal/view/models/models.go
new file mode 100644
index 00000000..8a343f4f
--- /dev/null
+++ b/internal/view/models/models.go
@@ -0,0 +1,15 @@
+package models
+
+import (
+ "encoding/json"
+ "time"
+)
+
+type View struct {
+ ID int `db:"id" json:"id"`
+ CreatedAt time.Time `db:"created_at" json:"created_at"`
+ UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
+ Name string `db:"name" json:"name"`
+ Filters json.RawMessage `db:"filters" json:"filters"`
+ UserID int `db:"user_id" json:"user_id"`
+}
diff --git a/internal/view/queries.sql b/internal/view/queries.sql
new file mode 100644
index 00000000..77b80db7
--- /dev/null
+++ b/internal/view/queries.sql
@@ -0,0 +1,20 @@
+-- name: get-view
+SELECT id, created_at, updated_at, name, filters, user_id
+FROM views WHERE id = $1;
+
+-- name: get-user-views
+SELECT id, created_at, updated_at, name, filters, user_id
+FROM views WHERE user_id = $1;
+
+-- name: insert-view
+INSERT INTO views (name, filters, user_id)
+VALUES ($1, $2, $3);
+
+-- name: delete-view
+DELETE FROM views
+WHERE id = $1;
+
+-- name: update-view
+UPDATE views
+SET name = $2, filters = $3, updated_at = NOW()
+WHERE id = $1
diff --git a/internal/view/view.go b/internal/view/view.go
new file mode 100644
index 00000000..cc11a247
--- /dev/null
+++ b/internal/view/view.go
@@ -0,0 +1,101 @@
+// Package view handles the management of conversation views.
+package view
+
+import (
+ "database/sql"
+ "embed"
+
+ "github.com/abhinavxd/libredesk/internal/dbutil"
+ "github.com/abhinavxd/libredesk/internal/envelope"
+ "github.com/abhinavxd/libredesk/internal/view/models"
+ "github.com/jmoiron/sqlx"
+ "github.com/zerodha/logf"
+)
+
+var (
+ //go:embed queries.sql
+ efs embed.FS
+)
+
+// Manager manages views.
+type Manager struct {
+ q queries
+ lo *logf.Logger
+}
+
+// Opts contains options for initializing the Manager.
+type Opts struct {
+ DB *sqlx.DB
+ Lo *logf.Logger
+}
+
+// queries contains prepared SQL queries.
+type queries struct {
+ GetView *sqlx.Stmt `query:"get-view"`
+ GetUserViews *sqlx.Stmt `query:"get-user-views"`
+ InsertView *sqlx.Stmt `query:"insert-view"`
+ DeleteView *sqlx.Stmt `query:"delete-view"`
+ UpdateView *sqlx.Stmt `query:"update-view"`
+}
+
+// New creates and returns a new instance of the Manager.
+func New(opts Opts) (*Manager, error) {
+ var q queries
+ if err := dbutil.ScanSQLFile("queries.sql", &q, opts.DB, efs); err != nil {
+ return nil, err
+ }
+ return &Manager{
+ q: q,
+ lo: opts.Lo,
+ }, nil
+}
+
+// Get returns a view by ID.
+func (v *Manager) Get(id int) (models.View, error) {
+ var view = models.View{}
+ if err := v.q.GetView.Get(&view, id); err != nil {
+ if err == sql.ErrNoRows {
+ return view, envelope.NewError(envelope.NotFoundError, "View not found", nil)
+ }
+ v.lo.Error("error fetching view", "error", err)
+ return view, envelope.NewError(envelope.GeneralError, "Error fetching view", nil)
+ }
+ return view, nil
+}
+
+// GetUsersViews returns all views for a user.
+func (v *Manager) GetUsersViews(userID int) ([]models.View, error) {
+ views := []models.View{}
+ if err := v.q.GetUserViews.Select(&views, userID); err != nil {
+ v.lo.Error("error fetching views", "error", err)
+ return nil, envelope.NewError(envelope.GeneralError, "Error fetching views", nil)
+ }
+ return views, nil
+}
+
+// Create creates a new view.
+func (v *Manager) Create(name string, filter []byte, userID int) error {
+ if _, err := v.q.InsertView.Exec(name, filter, userID); err != nil {
+ v.lo.Error("error inserting view", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error creating view", nil)
+ }
+ return nil
+}
+
+// Update updates a view by id.
+func (v *Manager) Update(id int, name string, filter []byte) error {
+ if _, err := v.q.UpdateView.Exec(id, name, filter); err != nil {
+ v.lo.Error("error updating view", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error updating view", nil)
+ }
+ return nil
+}
+
+// Delete deletes a view by ID.
+func (v *Manager) Delete(id int) error {
+ if _, err := v.q.DeleteView.Exec(id); err != nil {
+ v.lo.Error("error deleting view", "error", err)
+ return envelope.NewError(envelope.GeneralError, "Error deleting view", nil)
+ }
+ return nil
+}
diff --git a/internal/ws/client.go b/internal/ws/client.go
index 357c07a9..484c3774 100644
--- a/internal/ws/client.go
+++ b/internal/ws/client.go
@@ -7,15 +7,10 @@ import (
"sync"
"time"
- "github.com/abhinavxd/artemis/internal/ws/models"
+ "github.com/abhinavxd/libredesk/internal/ws/models"
"github.com/fasthttp/websocket"
)
-const (
- maxConversationsPagesToSub = 10
- maxConversationsPageSize = 50
-)
-
// SafeBool is a thread-safe boolean.
type SafeBool struct {
flag bool
@@ -50,9 +45,6 @@ type Client struct {
// To prevent pushes to the channel.
Closed SafeBool
- // Currently opened conversation UUID.
- CurrentConversationUUID string
-
// Buffered channel of outbound ws messages.
Send chan models.WSMessage
}
@@ -102,119 +94,19 @@ func (c *Client) Listen() {
// processIncomingMessage processes incoming messages from the client.
func (c *Client) processIncomingMessage(data []byte) {
- var req models.IncomingReq
- if err := json.Unmarshal(data, &req); err != nil {
- c.SendError("error unmarshalling request")
+ if string(data) == "ping" {
+ c.SendMessage([]byte("pong"), websocket.TextMessage)
return
}
-
- switch req.Action {
- case models.ActionConversationsListSub:
- var sReq models.ConversationsListSubscribe
- if err := json.Unmarshal(data, &sReq); err != nil {
- c.SendError("error unmarshalling request")
- return
- }
-
- // First remove all user conversation subscriptions.
- c.RemoveAllUserConversationSubscriptions(c.ID)
-
- // Fetch conversations of this list and subscribe to them
- for page := 1; page <= maxConversationsPagesToSub; page++ {
- conversationUUIDs, err := c.Hub.conversationStore.GetConversationsListUUIDs(c.ID, page, maxConversationsPageSize, sReq.Type)
- if err != nil {
- continue
- }
- c.SubscribeConversations(c.ID, conversationUUIDs)
- }
- case models.ActionSetCurrentConversation:
- var subReq models.ConversationCurrentSet
- if err := json.Unmarshal(data, &subReq); err != nil {
- c.SendError("error unmarshalling request")
- return
- }
-
- if c.CurrentConversationUUID != subReq.UUID {
- c.UnsubscribeConversation(c.ID, c.CurrentConversationUUID)
- c.CurrentConversationUUID = subReq.UUID
- c.SubscribeConversations(c.ID, []string{subReq.UUID})
- }
- case models.ActionUnsetCurrentConversation:
- c.UnsubscribeConversation(c.ID, c.CurrentConversationUUID)
- c.CurrentConversationUUID = ""
- default:
- c.SendError("unknown action")
- }
+ c.SendError("unknown incoming message type")
}
-// close closes the client connection and removes all subscriptions.
+// close closes the client connection.
func (c *Client) close() {
- c.RemoveAllUserConversationSubscriptions(c.ID)
c.Closed.Set(true)
close(c.Send)
}
-// SubscribeConversations subscribes the client to the specified conversations.
-func (c *Client) SubscribeConversations(userID int, conversationUUIDs []string) {
- c.Hub.subMutex.Lock()
- defer c.Hub.subMutex.Unlock()
- for _, conversationUUID := range conversationUUIDs {
- // Initialize the slice if it doesn't exist
- if c.Hub.conversationSubs[conversationUUID] == nil {
- c.Hub.conversationSubs[conversationUUID] = []int{}
- }
-
- // Check if userID already exists
- exists := false
- for _, id := range c.Hub.conversationSubs[conversationUUID] {
- if id == userID {
- exists = true
- break
- }
- }
-
- // Add userID if it doesn't exist
- if !exists {
- c.Hub.conversationSubs[conversationUUID] = append(c.Hub.conversationSubs[conversationUUID], userID)
- }
- }
-}
-
-// RemoveAllUserConversationSubscriptions removes all conversation subscriptions for the user.
-func (c *Client) RemoveAllUserConversationSubscriptions(userID int) {
- c.Hub.subMutex.Lock()
- defer c.Hub.subMutex.Unlock()
- for conversationUUID, userIDs := range c.Hub.conversationSubs {
- for i, id := range userIDs {
- if id == userID {
- c.Hub.conversationSubs[conversationUUID] = append(userIDs[:i], userIDs[i+1:]...)
- break
- }
- }
- if len(c.Hub.conversationSubs[conversationUUID]) == 0 {
- delete(c.Hub.conversationSubs, conversationUUID)
- }
- }
-}
-
-// UnsubscribeConversation unsubscribes the user from the specified conversation.
-func (c *Client) UnsubscribeConversation(userID int, conversationUUID string) {
- c.Hub.subMutex.Lock()
- defer c.Hub.subMutex.Unlock()
- if userIDs, ok := c.Hub.conversationSubs[conversationUUID]; ok {
- for i, id := range userIDs {
- if id == userID {
- c.Hub.conversationSubs[conversationUUID] = append(userIDs[:i], userIDs[i+1:]...)
- break
- }
- }
- // Remove the conversation from the map if no users are subscribed
- if len(c.Hub.conversationSubs[conversationUUID]) == 0 {
- delete(c.Hub.conversationSubs, conversationUUID)
- }
- }
-}
-
// SendError sends an error message to client.
func (c *Client) SendError(msg string) {
out := models.Message{
@@ -223,7 +115,6 @@ func (c *Client) SendError(msg string) {
}
b, _ := json.Marshal(out)
- // Try to send the error message over the Send channel
select {
case c.Send <- models.WSMessage{Data: b, MessageType: websocket.TextMessage}:
default:
diff --git a/internal/ws/models/models.go b/internal/ws/models/models.go
index 53dc8088..8b38b481 100644
--- a/internal/ws/models/models.go
+++ b/internal/ws/models/models.go
@@ -2,10 +2,6 @@ package models
// Action constants for WebSocket messages.
const (
- ActionConversationsListSub = "conversations_list_sub"
- ActionSetCurrentConversation = "conversation_set_current"
- ActionUnsetCurrentConversation = "conversation_unset_current"
-
MessageTypeMessagePropUpdate = "message_prop_update"
MessageTypeConversationPropertyUpdate = "conversation_prop_update"
MessageTypeNewMessage = "new_message"
@@ -30,18 +26,3 @@ type BroadcastMessage struct {
Data []byte `json:"data"`
Users []int `json:"users"`
}
-
-// IncomingReq represents an incoming WebSocket request.
-type IncomingReq struct {
- Action string `json:"action"`
-}
-
-// ConversationsListSubscribe represents a request to subscribe to conversations list
-type ConversationsListSubscribe struct {
- Type string `json:"type"`
-}
-
-// ConversationCurrentSet represents a request to set current conversation
-type ConversationCurrentSet struct {
- UUID string `json:"uuid"`
-}
diff --git a/internal/ws/ws.go b/internal/ws/ws.go
index 80fff005..f8daa1e6 100644
--- a/internal/ws/ws.go
+++ b/internal/ws/ws.go
@@ -4,44 +4,25 @@ package ws
import (
"sync"
- "github.com/abhinavxd/artemis/internal/ws/models"
+ "github.com/abhinavxd/libredesk/internal/ws/models"
"github.com/fasthttp/websocket"
)
-// Hub maintains the set of registered clients and their subscriptions.
+// Hub maintains the set of registered websockets clients.
type Hub struct {
- // Client ID to WS Client map.
+ // Client ID to WS Client map, user can connect from multiple devices and each device will have a separate client.
clients map[int][]*Client
clientsMutex sync.Mutex
-
- // Map of conversation UUID to client id list.
- conversationSubs map[string][]int
- subMutex sync.Mutex
-
- // Store to fetch conversation UUIDs for subscriptions.
- conversationStore ConversationStore
}
-// ConversationStore defines the interface for retrieving conversation UUIDs.
-type ConversationStore interface {
- GetConversationsListUUIDs(userID, page, pageSize int, typ string) ([]string, error)
-}
-
-// NewHub creates a new Hub.
+// NewHub creates a new websocket hub.
func NewHub() *Hub {
return &Hub{
- clients: make(map[int][]*Client, 10000),
- clientsMutex: sync.Mutex{},
- conversationSubs: make(map[string][]int),
- subMutex: sync.Mutex{},
+ clients: make(map[int][]*Client, 10000),
+ clientsMutex: sync.Mutex{},
}
}
-// SetConversationStore sets the conversation store for the hub.
-func (h *Hub) SetConversationStore(store ConversationStore) {
- h.conversationStore = store
-}
-
// AddClient adds a new client to the hub.
func (h *Hub) AddClient(client *Client) {
h.clientsMutex.Lock()
@@ -62,18 +43,27 @@ func (h *Hub) RemoveClient(client *Client) {
}
}
}
+
+// BroadcastMessage broadcasts a message to the specified users.
+// If no users are specified, the message is broadcast to all users.
func (h *Hub) BroadcastMessage(msg models.BroadcastMessage) {
h.clientsMutex.Lock()
defer h.clientsMutex.Unlock()
+
+ // Broadcast to all users if no users are specified.
+ if len(msg.Users) == 0 {
+ for _, clients := range h.clients {
+ for _, client := range clients {
+ client.SendMessage(msg.Data, websocket.TextMessage)
+ }
+ }
+ return
+ }
+
+ // Broadcast to specified users.
for _, userID := range msg.Users {
for _, client := range h.clients[userID] {
client.SendMessage(msg.Data, websocket.TextMessage)
}
}
}
-
-func (h *Hub) GetConversationSubscribers(conversationUUID string) []int {
- h.subMutex.Lock()
- defer h.subMutex.Unlock()
- return h.conversationSubs[conversationUUID]
-}
diff --git a/schema.sql b/schema.sql
index 97fef57f..23375f23 100644
--- a/schema.sql
+++ b/schema.sql
@@ -1,149 +1,55 @@
+CREATE EXTENSION IF NOT EXISTS pg_trgm;
+
DROP TYPE IF EXISTS "channels" CASCADE; CREATE TYPE "channels" AS ENUM ('email');
-DROP TYPE IF EXISTS "media_store" CASCADE; CREATE TYPE "media_store" AS ENUM ('s3', 'fs');
DROP TYPE IF EXISTS "message_type" CASCADE; CREATE TYPE "message_type" AS ENUM ('incoming','outgoing','activity');
-DROP TYPE IF EXISTS "message_sender_type" CASCADE; CREATE TYPE "message_sender_type" AS ENUM ('user','contact');
+DROP TYPE IF EXISTS "message_sender_type" CASCADE; CREATE TYPE "message_sender_type" AS ENUM ('agent','contact');
DROP TYPE IF EXISTS "message_status" CASCADE; CREATE TYPE "message_status" AS ENUM ('received','sent','failed','pending');
DROP TYPE IF EXISTS "content_type" CASCADE; CREATE TYPE "content_type" AS ENUM ('text','html');
+DROP TYPE IF EXISTS "conversation_assignment_type" CASCADE; CREATE TYPE "conversation_assignment_type" AS ENUM ('Round robin','Manual');
+DROP TYPE IF EXISTS "template_type" CASCADE; CREATE TYPE "template_type" AS ENUM ('email_outgoing', 'email_notification');
+DROP TYPE IF EXISTS "user_type" CASCADE; CREATE TYPE "user_type" AS ENUM ('agent', 'contact');
+DROP TYPE IF EXISTS "ai_provider" CASCADE; CREATE TYPE "ai_provider" AS ENUM ('openai');
+DROP TYPE IF EXISTS "automation_execution_mode" CASCADE; CREATE TYPE "automation_execution_mode" AS ENUM ('all', 'first_match');
+DROP TYPE IF EXISTS "macro_visibility" CASCADE; CREATE TYPE "macro_visibility" AS ENUM ('all', 'team', 'user');
+DROP TYPE IF EXISTS "media_disposition" CASCADE; CREATE TYPE "media_disposition" AS ENUM ('inline', 'attachment');
+DROP TYPE IF EXISTS "media_store" CASCADE; CREATE TYPE "media_store" AS ENUM ('s3', 'fs');
-DROP TABLE IF EXISTS teams CASCADE;
-CREATE TABLE teams (
+-- Sequence to generate reference number for conversations.
+DROP SEQUENCE IF EXISTS conversation_reference_number_sequence; CREATE SEQUENCE conversation_reference_number_sequence START 100;
+
+-- Function to generate reference number for conversations with optional prefix.
+CREATE OR REPLACE FUNCTION generate_reference_number(prefix TEXT)
+RETURNS TEXT AS $$
+BEGIN
+ RETURN prefix || nextval('conversation_reference_number_sequence');
+END;
+$$ LANGUAGE plpgsql;
+
+DROP TABLE IF EXISTS sla_policies CASCADE;
+CREATE TABLE sla_policies (
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
- "name" VARCHAR(140) NOT NULL,
- disabled bool DEFAULT false NOT NULL,
- auto_assign_conversations bool DEFAULT false NOT NULL,
- CONSTRAINT constraint_teams_on_name_unique UNIQUE ("name")
+ name TEXT NOT NULL,
+ description TEXT NULL,
+ first_response_time TEXT NOT NULL,
+ resolution_time TEXT NOT NULL,
+ CONSTRAINT constraint_sla_policies_on_name CHECK (length(name) <= 140),
+ CONSTRAINT constraint_sla_policies_on_description CHECK (length(description) <= 300)
);
-DROP TABLE IF EXISTS users CASCADE;
-CREATE TABLE users (
- id SERIAL PRIMARY KEY,
- created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW(),
- deleted_at TIMESTAMPTZ NULL,
- disabled bool DEFAULT false NOT NULL,
- email VARCHAR(254) NOT NULL,
- first_name VARCHAR(100) NOT NULL,
- last_name VARCHAR(100) NULL,
- "password" VARCHAR(150) NULL,
- avatar_url TEXT NULL,
- roles _text DEFAULT '{}'::text [] NOT NULL,
- reset_password_token TEXT NULL,
- reset_password_token_expiry TIMESTAMPTZ NULL,
- CONSTRAINT constraint_users_on_email_unique UNIQUE (email)
-);
-
-DROP TABLE IF EXISTS conversation_statuses CASCADE;
-CREATE TABLE conversation_statuses (
- id SERIAL PRIMARY KEY,
- created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW(),
- "name" TEXT NOT NULL,
- CONSTRAINT constraint_status_on_name_unique UNIQUE ("name")
-);
-
-DROP TABLE IF EXISTS conversation_priorities CASCADE;
-CREATE TABLE conversation_priorities (
- id SERIAL PRIMARY KEY,
- created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW(),
- "name" TEXT NOT NULL,
- CONSTRAINT constraint_priority_on_name_unique UNIQUE ("name")
-);
-
-DROP TABLE IF EXISTS conversations CASCADE;
-CREATE TABLE conversations (
- id BIGSERIAL PRIMARY KEY,
- created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW(),
- "uuid" UUID DEFAULT gen_random_uuid() NOT NULL,
- reference_number TEXT UNIQUE NOT NULL,
- contact_id BIGINT NOT NULL,
- assigned_user_id INT REFERENCES users(id) ON DELETE SET NULL ON UPDATE CASCADE,
- assigned_team_id INT REFERENCES teams(id) ON DELETE SET NULL ON UPDATE CASCADE,
- inbox_id INT NOT NULL,
- meta JSONB DEFAULT '{}'::JSON NOT NULL,
- assignee_last_seen_at TIMESTAMPTZ DEFAULT NOW(),
- first_reply_at TIMESTAMPTZ NULL,
- closed_at TIMESTAMPTZ NULL,
- resolved_at TIMESTAMPTZ NULL,
- status_id INT REFERENCES conversation_statuses(id),
- priority_id INT REFERENCES conversation_priorities(id)
-);
-
-DROP TABLE IF EXISTS conversation_messages CASCADE;
-CREATE TABLE conversation_messages (
- id BIGSERIAL PRIMARY KEY,
- created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW(),
- "uuid" UUID DEFAULT gen_random_uuid() NOT NULL,
- "type" message_type NOT NULL,
- status message_status NOT NULL,
- private BOOL NULL,
- conversation_id BIGSERIAL REFERENCES conversations(id) ON DELETE CASCADE ON UPDATE CASCADE,
- content_type content_type NULL,
- "content" TEXT NULL,
- source_id TEXT NULL,
- sender_id INT NULL,
- sender_type message_sender_type NOT NULL,
- meta JSONB DEFAULT '{}'::JSONB NULL
-);
-
-DROP TABLE IF EXISTS automation_rules CASCADE;
-CREATE TABLE automation_rules (
+DROP TABLE IF EXISTS business_hours CASCADE;
+CREATE TABLE business_hours (
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
- "name" VARCHAR(255) NOT NULL,
- description TEXT NULL,
- "type" VARCHAR NOT NULL,
- rules JSONB NULL,
- events TEXT[] NULL,
- disabled BOOL DEFAULT false NOT NULL,
- CONSTRAINT constraint_automation_rules_on_name CHECK (length("name") <= 100),
- CONSTRAINT constraint_automation_rules_on_description CHECK (length(description) <= 300)
-);
-
-DROP TABLE IF EXISTS canned_responses CASCADE;
-CREATE TABLE canned_responses (
- id SERIAL PRIMARY KEY,
- created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW(),
- title TEXT NOT NULL,
- "content" TEXT NOT NULL,
- CONSTRAINT constraint_canned_responses_on_title CHECK (length(title) <= 100),
- CONSTRAINT constraint_canned_responses_on_content CHECK (length("content") <= 5000)
-);
-
-DROP TABLE IF EXISTS contacts CASCADE;
-CREATE TABLE contacts (
- id BIGSERIAL PRIMARY KEY,
- created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW(),
- first_name TEXT NULL,
- last_name TEXT NULL,
- email VARCHAR(254) NULL,
- phone_number TEXT NULL,
- avatar_url TEXT NULL,
- inbox_id INT NULL,
- source_id TEXT NULL,
- CONSTRAINT constraint_contacts_on_first_name CHECK (length(first_name) <= 100),
- CONSTRAINT constraint_contacts_on_last_name CHECK (length(last_name) <= 100),
- CONSTRAINT constraint_contacts_on_email CHECK (length(email) <= 254),
- CONSTRAINT constraint_contacts_on_phone_number CHECK (length(phone_number) <= 50),
- CONSTRAINT constraint_contacts_on_avatar_url CHECK (length(avatar_url) <= 1000),
- CONSTRAINT constraint_contacts_on_source_id CHECK (length(source_id) <= 5000)
-);
-
-DROP TABLE IF EXISTS conversation_participants CASCADE;
-CREATE TABLE conversation_participants (
- id BIGSERIAL PRIMARY KEY,
- created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW(),
- user_id INT NOT NULL,
- conversation_id BIGINT REFERENCES conversations(id) ON DELETE CASCADE ON UPDATE CASCADE,
- CONSTRAINT constraint_conversation_participants_conversation_id_and_user_id_unique UNIQUE (conversation_id, user_id)
+ name TEXT NOT NULL,
+ description TEXT NULL,
+ is_always_open BOOL DEFAULT false NOT NULL,
+ hours JSONB NOT NULL,
+ holidays JSONB DEFAULT '{}'::jsonb NOT NULL,
+ CONSTRAINT constraint_business_hours_on_name CHECK (length(name) <= 140),
+ CONSTRAINT constraint_business_hours_on_description CHECK (length(description) <= 300)
);
DROP TABLE IF EXISTS inboxes CASCADE;
@@ -151,44 +57,35 @@ CREATE TABLE inboxes (
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
+ "name" TEXT NOT NULL,
deleted_at TIMESTAMPTZ NULL,
- channel "channels" NOT NULL,
- disabled bool DEFAULT false NOT NULL,
+ channel channels NOT NULL,
+ enabled bool DEFAULT TRUE NOT NULL,
+ csat_enabled bool DEFAULT false NOT NULL,
config jsonb DEFAULT '{}'::jsonb NOT NULL,
- "name" VARCHAR(140) NOT NULL,
- "from" VARCHAR(300) NULL
+ "from" TEXT NULL,
+ CONSTRAINT constraint_inboxes_on_name CHECK (length("name") <= 140)
);
-DROP TABLE IF EXISTS media CASCADE;
-CREATE TABLE media (
+DROP TABLE IF EXISTS teams CASCADE;
+CREATE TABLE teams (
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
- "uuid" uuid DEFAULT gen_random_uuid() NOT NULL,
- store "media_store" NOT NULL,
- filename TEXT NOT NULL,
- content_type TEXT NOT NULL,
- model_id INT NULL,
- model_type TEXT NULL,
- disposition VARCHAR(50) NULL,
- content_id TEXT NULL,
- "size" INT NULL,
- meta jsonb DEFAULT '{}'::jsonb NOT NULL,
- CONSTRAINT constraint_media_on_filename CHECK (length(filename) <= 1000),
- CONSTRAINT constraint_media_on_content_id CHECK (length(content_id) <= 100)
-);
+ "name" TEXT NOT NULL,
+ emoji TEXT NULL,
+ conversation_assignment_type conversation_assignment_type NOT NULL,
+ max_auto_assigned_conversations INT DEFAULT 0 NOT NULL,
-DROP TABLE IF EXISTS oidc CASCADE;
-CREATE TABLE oidc (
- id SERIAL PRIMARY KEY,
- created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW(),
- provider_url TEXT NOT NULL,
- client_id TEXT NOT NULL,
- client_secret TEXT NOT NULL,
- disabled bool DEFAULT false NOT NULL,
- provider VARCHAR NULL,
- "name" TEXT NULL
+ -- Set to NULL when business hours or SLA policy is deleted.
+ business_hours_id INT REFERENCES business_hours(id) ON DELETE SET NULL ON UPDATE CASCADE NULL,
+ sla_policy_id INT REFERENCES sla_policies(id) ON DELETE SET NULL ON UPDATE CASCADE NULL,
+
+ timezone TEXT NULL,
+ CONSTRAINT constraint_teams_on_emoji CHECK (length(emoji) <= 10),
+ CONSTRAINT constraint_teams_on_name CHECK (length("name") <= 140),
+ CONSTRAINT constraint_teams_on_timezone CHECK (length(timezone) <= 140),
+ CONSTRAINT constraint_teams_on_name_unique UNIQUE ("name")
);
DROP TABLE IF EXISTS roles CASCADE;
@@ -197,22 +94,246 @@ CREATE TABLE roles (
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
permissions TEXT[] DEFAULT '{}'::TEXT[] NOT NULL,
- "name" TEXT NULL,
- description TEXT NULL
+ "name" TEXT UNIQUE NOT NULL,
+ description TEXT NULL,
+ CONSTRAINT constraint_roles_on_name CHECK (length("name") <= 50),
+ CONSTRAINT constraint_roles_on_description CHECK (length(description) <= 300)
);
--- Roles.
-INSERT INTO roles
-(permissions, "name", description)
-VALUES('{conversations:read,conversations:read_unassigned,conversations:read_assigned,conversations:update_user_assignee,conversations:update_team_assignee,conversations:update_priority,conversations:update_status,conversations:update_tags,messages:read,messages:write}', 'Agent', 'Role for all agents with limited access to conversations.');
-INSERT INTO roles
-(permissions, "name", description)
-VALUES('{conversations:read_unassigned,teams:delete,users:delete,conversations:read_all,conversations:read,conversations:read_assigned,conversations:update_user_assignee,conversations:update_team_assignee,conversations:update_priority,conversations:update_status,conversations:update_tags,messages:read,messages:write,templates:write,templates:read,roles:delete,roles:write,roles:read,inboxes:delete,inboxes:write,inboxes:read,automations:write,automations:delete,automations:read,teams:write,teams:read,users:write,users:read,dashboard_global:read,canned_responses:delete,tags:delete,canned_responses:write,tags:write,status:delete,status:write,status:read,oidc:delete,oidc:read,oidc:write,settings_notifications:read,settings_notifications:write,settings_general:write,templates:delete,admin:read}', 'Admin', 'Role for users who have complete access to everything.');
+DROP TABLE IF EXISTS users CASCADE;
+CREATE TABLE users (
+ id BIGSERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ type user_type NOT NULL,
+ deleted_at TIMESTAMPTZ NULL,
+ enabled BOOL DEFAULT TRUE NOT NULL,
+ email TEXT NULL,
+ first_name TEXT NOT NULL,
+ last_name TEXT NULL,
+ phone_number TEXT NULL,
+ country TEXT NULL,
+ "password" VARCHAR(150) NULL,
+ avatar_url TEXT NULL,
+ custom_attributes JSONB DEFAULT '{}'::jsonb NOT NULL,
+ reset_password_token TEXT NULL,
+ reset_password_token_expiry TIMESTAMPTZ NULL,
+ CONSTRAINT constraint_users_on_country CHECK (LENGTH(country) <= 140),
+ CONSTRAINT constraint_users_on_phone_number CHECK (LENGTH(phone_number) <= 20),
+ CONSTRAINT constraint_users_on_email_length CHECK (LENGTH(email) <= 320),
+ CONSTRAINT constraint_users_on_first_name CHECK (LENGTH(first_name) <= 140),
+ CONSTRAINT constraint_users_on_last_name CHECK (LENGTH(last_name) <= 140)
+);
+CREATE UNIQUE INDEX index_unique_users_on_email_and_type_when_deleted_at_is_null ON users (email, type)
+WHERE deleted_at IS NULL;
+
+DROP TABLE IF EXISTS user_roles CASCADE;
+CREATE TABLE user_roles (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+
+ -- Cascade deletes when user or role is deleted, as they are not useful without each other.
+ user_id INT REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
+ role_id INT REFERENCES roles(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
+
+ CONSTRAINT constraint_user_roles_on_user_id_and_role_id_unique UNIQUE (user_id, role_id)
+);
+CREATE INDEX index_user_roles_on_user_id ON user_roles(user_id);
+
+DROP TABLE IF EXISTS conversation_statuses CASCADE;
+CREATE TABLE conversation_statuses (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ "name" TEXT NOT NULL UNIQUE
+);
+
+DROP TABLE IF EXISTS conversation_priorities CASCADE;
+CREATE TABLE conversation_priorities (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ "name" TEXT NOT NULL UNIQUE
+);
+
+DROP TABLE IF EXISTS contact_channels CASCADE;
+CREATE TABLE contact_channels (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+
+ -- Cascade deletes when contact or inbox is deleted.
+ contact_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ inbox_id INT NOT NULL REFERENCES inboxes(id) ON DELETE CASCADE ON UPDATE CASCADE,
+
+ identifier TEXT NOT NULL,
+ CONSTRAINT constraint_contact_channels_on_identifier CHECK (length(identifier) <= 1000),
+ CONSTRAINT constraint_contact_channels_on_inbox_id_and_contact_id_unique UNIQUE (inbox_id, contact_id)
+);
+
+DROP TABLE IF EXISTS conversations CASCADE;
+CREATE TABLE conversations (
+ id BIGSERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ "uuid" UUID DEFAULT gen_random_uuid() NOT NULL UNIQUE,
+ reference_number TEXT DEFAULT generate_reference_number('') NOT NULL UNIQUE,
+
+ -- Cascade deletes when contact is deleted.
+ contact_id BIGINT REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
+
+ -- Set to NULL when assigned user or team is deleted.
+ assigned_user_id BIGINT REFERENCES users(id) ON DELETE SET NULL ON UPDATE CASCADE,
+ assigned_team_id INT REFERENCES teams(id) ON DELETE SET NULL ON UPDATE CASCADE,
+
+ -- Set to NULL when SLA policy is deleted.
+ sla_policy_id INT REFERENCES sla_policies(id) ON DELETE SET NULL ON UPDATE CASCADE,
+
+ -- Cascade deletes when inbox is deleted.
+ inbox_id INT REFERENCES inboxes(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
+
+ -- Restrict delete.
+ contact_channel_id INT REFERENCES contact_channels(id) ON DELETE RESTRICT ON UPDATE CASCADE NOT NULL,
+ status_id INT REFERENCES conversation_statuses(id) ON DELETE RESTRICT ON UPDATE CASCADE NOT NULL,
+ priority_id INT REFERENCES conversation_priorities(id) ON DELETE RESTRICT ON UPDATE CASCADE,
+
+ meta JSONB DEFAULT '{}'::jsonb NOT NULL,
+ custom_attributes JSONB DEFAULT '{}'::jsonb NOT NULL,
+ assignee_last_seen_at TIMESTAMPTZ DEFAULT NOW(),
+ first_reply_at TIMESTAMPTZ NULL,
+ closed_at TIMESTAMPTZ NULL,
+ resolved_at TIMESTAMPTZ NULL,
+
+ "subject" TEXT NULL,
+ waiting_since TIMESTAMPTZ NULL,
+ last_message_at TIMESTAMPTZ NULL,
+ last_message TEXT NULL,
+ next_sla_deadline_at TIMESTAMPTZ NULL,
+ snoozed_until TIMESTAMPTZ NULL
+);
+CREATE INDEX index_conversations_on_assigned_user_id ON conversations (assigned_user_id);
+CREATE INDEX index_conversations_on_assigned_team_id ON conversations (assigned_team_id);
+CREATE INDEX index_conversations_on_snoozed_until ON conversations (snoozed_until);
+CREATE INDEX index_conversations_on_contact_id ON conversations (contact_id);
+CREATE INDEX index_conversations_on_inbox_id ON conversations (inbox_id);
+CREATE INDEX index_conversations_on_status_id ON conversations (status_id);
+CREATE INDEX index_conversations_on_priority_id ON conversations (priority_id);
+CREATE INDEX index_conversations_on_created_at ON conversations (created_at);
+CREATE INDEX index_conversations_on_last_message_at ON conversations (last_message_at);
+CREATE INDEX index_conversations_on_next_sla_deadline_at ON conversations (next_sla_deadline_at);
+CREATE INDEX index_conversations_on_waiting_since ON conversations (waiting_since);
+
+DROP TABLE IF EXISTS conversation_messages CASCADE;
+CREATE TABLE conversation_messages (
+ id BIGSERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ "uuid" UUID DEFAULT gen_random_uuid() NOT NULL UNIQUE,
+ "type" message_type NOT NULL,
+ status message_status NOT NULL,
+ private BOOL DEFAULT FALSE NOT NULL,
+ conversation_id BIGINT REFERENCES conversations(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
+ content_type content_type NULL,
+ "content" TEXT NULL,
+ text_content TEXT NULL,
+ source_id TEXT NULL,
+ sender_id BIGINT REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
+ sender_type message_sender_type NOT NULL,
+ meta JSONB DEFAULT '{}'::JSONB NULL
+);
+CREATE INDEX index_trgm_conversation_messages_on_text_content ON conversation_messages USING GIN (text_content gin_trgm_ops);
+CREATE INDEX index_conversation_messages_on_conversation_id ON conversation_messages (conversation_id);
+CREATE INDEX index_conversation_messages_on_created_at ON conversation_messages (created_at);
+CREATE INDEX index_conversation_messages_on_source_id ON conversation_messages (source_id);
+CREATE INDEX index_conversation_messages_on_status ON conversation_messages (status);
+
+DROP TABLE IF EXISTS automation_rules CASCADE;
+CREATE TABLE automation_rules (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ "name" TEXT NOT NULL,
+ description TEXT NULL,
+ "type" VARCHAR NOT NULL,
+ rules JSONB NULL,
+ events TEXT[] DEFAULT '{}'::TEXT[] NOT NULL,
+ enabled BOOL DEFAULT TRUE NOT NULL,
+ weight INT DEFAULT 0 NOT NULL,
+ execution_mode automation_execution_mode DEFAULT 'all' NOT NULL,
+ CONSTRAINT constraint_automation_rules_on_name CHECK (length("name") <= 140),
+ CONSTRAINT constraint_automation_rules_on_description CHECK (length(description) <= 300)
+);
+CREATE INDEX index_automation_rules_on_enabled_and_weight ON automation_rules(enabled, weight);
+CREATE INDEX index_automation_rules_on_type_and_weight ON automation_rules(type, weight);
+
+DROP TABLE IF EXISTS macros CASCADE;
+CREATE TABLE macros (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ name TEXT NOT NULL,
+ actions JSONB DEFAULT '{}'::jsonb NOT NULL,
+ visibility macro_visibility NOT NULL,
+ message_content TEXT NOT NULL,
+ -- Cascade deletes when user is deleted.
+ user_id BIGINT REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ team_id BIGINT REFERENCES teams(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ usage_count INT DEFAULT 0 NOT NULL,
+ CONSTRAINT name_length CHECK (length(name) <= 140),
+ CONSTRAINT message_content_length CHECK (length(message_content) <= 5000)
+);
+
+DROP TABLE IF EXISTS conversation_participants CASCADE;
+CREATE TABLE conversation_participants (
+ id BIGSERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ -- Cascade deletes when user or conversation is deleted.
+ user_id BIGINT REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
+ conversation_id BIGINT REFERENCES conversations(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL
+);
+CREATE UNIQUE INDEX index_unique_conversation_participants_on_conversation_id_and_user_id ON conversation_participants (conversation_id, user_id);
+
+DROP TABLE IF EXISTS media CASCADE;
+CREATE TABLE media (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ "uuid" uuid DEFAULT gen_random_uuid() NOT NULL UNIQUE,
+ store "media_store" NOT NULL,
+ filename TEXT NOT NULL,
+ content_type TEXT NOT NULL,
+ content_id TEXT NULL,
+ model_id INT NULL,
+ model_type TEXT NULL,
+ disposition media_disposition NULL,
+ "size" INT NULL,
+ meta jsonb DEFAULT '{}'::jsonb NOT NULL,
+ CONSTRAINT constraint_media_on_filename CHECK (length(filename) <= 1000),
+ CONSTRAINT constraint_media_on_content_id CHECK (length(content_id) <= 300)
+);
+CREATE INDEX index_media_on_model_type_and_model_id ON media(model_type, model_id);
+CREATE INDEX index_media_on_content_id ON media(content_id);
+
+DROP TABLE IF EXISTS oidc CASCADE;
+CREATE TABLE oidc (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ "name" TEXT NULL,
+ provider_url TEXT NOT NULL,
+ client_id TEXT NOT NULL,
+ client_secret TEXT NOT NULL,
+ enabled bool DEFAULT TRUE NOT NULL,
+ provider VARCHAR NULL,
+ CONSTRAINT constraint_oidc_on_name CHECK (length("name") <= 140)
+);
DROP TABLE IF EXISTS settings CASCADE;
CREATE TABLE settings (
updated_at TIMESTAMPTZ DEFAULT NOW(),
- "key" TEXT NOT NULL,
+ "key" TEXT NOT NULL UNIQUE,
value jsonb DEFAULT '{}'::jsonb NOT NULL,
CONSTRAINT settings_key_key UNIQUE ("key")
);
@@ -223,8 +344,8 @@ CREATE TABLE tags (
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
- "name" TEXT NOT NULL,
- CONSTRAINT constraint_tags_on_name_unique UNIQUE ("name")
+ "name" TEXT NOT NULL UNIQUE,
+ CONSTRAINT constraint_tags_on_name CHECK (length("name") <= 140)
);
DROP TABLE IF EXISTS team_members CASCADE;
@@ -232,87 +353,209 @@ CREATE TABLE team_members (
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
- team_id INT REFERENCES teams(id) ON DELETE CASCADE ON UPDATE CASCADE,
- user_id INT NOT NULL,
- CONSTRAINT constraint_team_members_on_team_id_and_user_id_unique UNIQUE (team_id, user_id)
+ -- Cascade deletes when team or user is deleted.
+ team_id BIGINT REFERENCES teams(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
+ user_id BIGINT REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
+ emoji TEXT NULL,
+ CONSTRAINT constraint_team_members_on_emoji CHECK (length(emoji) <= 1)
);
+CREATE UNIQUE INDEX index_unique_team_members_on_team_id_and_user_id ON team_members (team_id, user_id);
DROP TABLE IF EXISTS templates CASCADE;
CREATE TABLE templates (
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
+ type template_type NOT NULL,
body TEXT NOT NULL,
is_default bool DEFAULT false NOT NULL,
- "name" TEXT NULL
+ "name" TEXT NOT NULL,
+ subject TEXT NULL,
+ is_builtin bool DEFAULT false NOT NULL,
+ CONSTRAINT constraint_templates_on_name CHECK (length("name") <= 140),
+ CONSTRAINT constraint_templates_on_subject CHECK (length(subject) <= 1000)
);
-CREATE UNIQUE INDEX unique_index_templates_on_is_default_when_is_default_is_true ON templates USING btree (is_default)
+CREATE UNIQUE INDEX index_unique_templates_on_is_default_when_is_default_is_true ON templates USING btree (is_default)
WHERE (is_default = true);
-DROP TABLE IF EXISTS contact_methods CASCADE;
-CREATE TABLE contact_methods (
- id BIGSERIAL PRIMARY KEY,
- contact_id BIGINT REFERENCES contacts(id) ON DELETE CASCADE ON UPDATE CASCADE,
- "source" TEXT NOT NULL,
- source_id TEXT NOT NULL,
- inbox_id INT NULL,
- created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW(),
- CONSTRAINT constraint_contact_methods_on_source_and_source_id_unique UNIQUE (contact_id, source_id)
-);
-
DROP TABLE IF EXISTS conversation_tags CASCADE;
CREATE TABLE conversation_tags (
id BIGSERIAL PRIMARY KEY,
- tag_id INT REFERENCES tags(id) ON DELETE CASCADE ON UPDATE CASCADE,
- conversation_id BIGSERIAL REFERENCES conversations(id) ON DELETE CASCADE ON UPDATE CASCADE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
- CONSTRAINT constraint_conversation_tags_on_conversation_id_and_tag_id_unique UNIQUE (conversation_id, tag_id)
+ -- Cascade deletes when tag or conversation is deleted.
+ tag_id INT REFERENCES tags(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ conversation_id BIGINT REFERENCES conversations(id) ON DELETE CASCADE ON UPDATE CASCADE
);
+CREATE UNIQUE INDEX index_conversation_tags_on_conversation_id_and_tag_id ON conversation_tags (conversation_id, tag_id);
+
+DROP TABLE IF EXISTS csat_responses CASCADE;
+CREATE TABLE csat_responses (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ uuid UUID DEFAULT gen_random_uuid() NOT NULL UNIQUE,
+
+ -- Keep CSAT responses even if the conversation or agent is deleted.
+ conversation_id BIGINT REFERENCES conversations(id) ON DELETE SET NULL ON UPDATE CASCADE NOT NULL,
+
+ rating INT DEFAULT 0 NOT NULL,
+ feedback TEXT NULL,
+ response_timestamp TIMESTAMPTZ NULL,
+ CONSTRAINT constraint_csat_responses_on_rating CHECK (rating >= 0 AND rating <= 5),
+ CONSTRAINT constraint_csat_responses_on_feedback CHECK (length(feedback) <= 1000)
+);
+CREATE INDEX index_csat_responses_on_uuid ON csat_responses(uuid);
+
+DROP TABLE IF EXISTS views CASCADE;
+CREATE TABLE views (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
+ name TEXT NOT NULL,
+ filters JSONB NOT NULL,
+ -- Delete user views when user is deleted.
+ user_id BIGINT NOT NULL REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT constraint_views_on_name CHECK (length(name) <= 140)
+);
+CREATE INDEX index_views_on_user_id ON views(user_id);
+
+DROP TABLE IF EXISTS applied_slas CASCADE;
+CREATE TABLE applied_slas (
+ id BIGSERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+
+ -- Conversation / SLA policy maybe deleted but for reports the applied SLA should remain.
+ conversation_id BIGINT REFERENCES conversations(id) ON DELETE SET NULL ON UPDATE CASCADE NOT NULL,
+ sla_policy_id INT REFERENCES sla_policies(id) ON DELETE SET NULL ON UPDATE CASCADE NOT NULL,
+
+ first_response_deadline_at TIMESTAMPTZ NULL,
+ resolution_deadline_at TIMESTAMPTZ NULL,
+ first_response_breached_at TIMESTAMPTZ NULL,
+ resolution_breached_at TIMESTAMPTZ NULL,
+ first_response_met_at TIMESTAMPTZ NULL,
+ resolution_met_at TIMESTAMPTZ NULL
+);
+CREATE INDEX index_applied_slas_on_conversation_id ON applied_slas(conversation_id);
+
+DROP TABLE IF EXISTS ai_providers CASCADE;
+CREATE TABLE ai_providers (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ name TEXT NOT NULL UNIQUE,
+ provider ai_provider NOT NULL,
+ config JSONB NOT NULL DEFAULT '{}',
+ is_default BOOLEAN NOT NULL DEFAULT FALSE,
+ CONSTRAINT constraint_ai_providers_on_name CHECK (length(name) <= 140)
+);
+CREATE UNIQUE INDEX index_unique_ai_providers_on_is_default_when_is_default_is_true ON ai_providers USING btree (is_default)
+WHERE (is_default = true);
+
+DROP TABLE IF EXISTS ai_prompts CASCADE;
+CREATE TABLE ai_prompts (
+ id SERIAL PRIMARY KEY,
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
+ title TEXT NOT NULL,
+ key TEXT NOT NULL UNIQUE,
+ content TEXT NOT NULL,
+ CONSTRAINT constraint_prompts_on_title CHECK (length(title) <= 140),
+ CONSTRAINT constraint_prompts_on_key CHECK (length(key) <= 140)
+);
+CREATE INDEX index_ai_prompts_on_key ON ai_prompts USING btree (key);
+
+INSERT INTO ai_providers
+("name", provider, config, is_default)
+VALUES('openai', 'openai', '{"api_key": ""}'::jsonb, true);
+
+-- Default AI prompts
+INSERT INTO ai_prompts ("key", "content", title)
+VALUES
+('make_friendly', 'Modify the text to make it more friendly and approachable.', 'Make Friendly'),
+('make_concise', 'Simplify the text to make it more concise and to the point.', 'Make Concise'),
+('add_empathy', 'Add empathy to the text while retaining the original meaning.', 'Add Empathy'),
+('adjust_positive_tone', 'Adjust the tone of the text to make it sound more positive and reassuring.', 'Adjust Positive Tone'),
+('make_professional', 'Rephrase the text to make it sound more formal and professional and to the point.', 'Make Professional');
-- Default settings
INSERT INTO settings ("key", value)
VALUES
('app.lang', '"en"'::jsonb),
('app.root_url', '"http://localhost:9000"'::jsonb),
- ('app.logo_url', '""'::jsonb),
- ('app.site_name', '"Helpdesk"'::jsonb),
+ ('app.logo_url', '"http://localhost:9000/logo.png"'::jsonb),
+ ('app.site_name', '"Libredesk"'::jsonb),
('app.favicon_url', '"http://localhost:9000/favicon.ico"'::jsonb),
('app.max_file_upload_size', '20'::jsonb),
('app.allowed_file_upload_extensions', '["*"]'::jsonb),
+ ('app.timezone', '"Asia/Calcutta"'::jsonb),
+ ('app.business_hours_id', '""'::jsonb),
('notification.email.username', '"admin@yourcompany.com"'::jsonb),
- ('notification.email.host', '""'::jsonb),
+ ('notification.email.host', '"smtp.gmail.com"'::jsonb),
('notification.email.port', '587'::jsonb),
('notification.email.password', '""'::jsonb),
('notification.email.max_conns', '1'::jsonb),
('notification.email.idle_timeout', '"5s"'::jsonb),
('notification.email.wait_timeout', '"5s"'::jsonb),
- ('notification.email.auth_protocol', '"Plain"'::jsonb),
- ('notification.email.email_address', '""'::jsonb),
+ ('notification.email.auth_protocol', '"plain"'::jsonb),
+ ('notification.email.email_address', '"admin@yourcompany.com"'::jsonb),
('notification.email.max_msg_retries', '3'::jsonb),
('notification.email.enabled', 'false'::jsonb);
+-- Default conversation priorities
+INSERT INTO conversation_priorities (name) VALUES
+('Low'),
+('Medium'),
+('High');
-INSERT INTO conversation_priorities
-("name")
-VALUES('Low');
-INSERT INTO conversation_priorities
-("name")
-VALUES('Medium');
-INSERT INTO conversation_priorities
-("name")
-VALUES('High');
+-- Default conversation statuses
+INSERT INTO conversation_statuses (name) VALUES
+('Open'),
+('In Progress'),
+('Waiting'),
+('Snoozed'),
+('Resolved'),
+('Closed');
-INSERT INTO conversation_statuses
-("name")
-VALUES('Open');
-INSERT INTO conversation_statuses
-("name")
-VALUES('Replied');
-INSERT INTO conversation_statuses
-("name")
-VALUES('Resolved');
-INSERT INTO conversation_statuses
-("name")
-VALUES('Closed');
\ No newline at end of file
+-- Default roles
+INSERT INTO
+ roles ("name", description, permissions)
+VALUES
+ (
+ 'Agent',
+ 'Role for all agents with limited access to conversations.',
+ '{conversations:read_all,conversations:read_unassigned,conversations:read_assigned,conversations:read_team_inbox,conversations:read,conversations:update_user_assignee,conversations:update_team_assignee,conversations:update_priority,conversations:update_status,conversations:update_tags,messages:read,messages:write,view:manage}'
+ );
+
+INSERT INTO
+ roles ("name", description, permissions)
+VALUES
+ (
+ 'Admin',
+ 'Role for users who have complete access to everything.',
+ '{general_settings:manage,notification_settings:manage,oidc:manage,conversations:read_all,conversations:read_unassigned,conversations:read_assigned,conversations:read_team_inbox,conversations:read,conversations:update_user_assignee,conversations:update_team_assignee,conversations:update_priority,conversations:update_status,conversations:update_tags,messages:read,messages:write,view:manage,status:manage,tags:manage,macros:manage,users:manage,teams:manage,automations:manage,inboxes:manage,roles:manage,reports:manage,templates:manage,business_hours:manage,sla:manage}'
+ );
+
+
+-- Email notification templates
+INSERT INTO public.templates
+("type", body, is_default, "name", subject, is_builtin)
+VALUES('email_notification'::public."template_type", '
Hello {{ .agent.full_name }},
+
+
A new conversation has been assigned to you:
+
+
+ Reference number: {{.conversation.reference_number }}
+ Priority: {{.conversation.priority }}
+ Subject: {{.conversation.subject }}
+
+
+
+View Conversation
+
+
+
+ Best regards,
+ Libredesk
+
', false, 'Conversation assigned', 'New conversation assigned to you', true);
\ No newline at end of file
diff --git a/static/email-templates/conversation-assigned.html b/static/email-templates/conversation-assigned.html
deleted file mode 100644
index abe0d96b..00000000
--- a/static/email-templates/conversation-assigned.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{{ define "conversation-assigned" }}
-{{ template "header" . }}
-
-
A new conversation has been assigned to you:
-
-
- {{ if .Conversation.Subject }}Subject: {{ .Conversation.Subject }}{{ end }}
-
-
-
You can view the conversation by clicking the link below:
-
View Conversation
-
-
-{{ template "footer" . }}
-{{ end }}
\ No newline at end of file
diff --git a/static/public/static/style.css b/static/public/static/style.css
new file mode 100644
index 00000000..e1fac2e9
--- /dev/null
+++ b/static/public/static/style.css
@@ -0,0 +1,210 @@
+@import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600&display=swap");
+
+:root {
+ --primary-color: #1a1a1d;
+ --secondary-color: #f4f4f5;
+ --text-color: #0a0a0b;
+ --background-color: #ffffff;
+ --border-color: #e5e5e6;
+ --shadow-color: rgba(26, 26, 29, 0.1);
+}
+
+* {
+ box-sizing: border-box;
+}
+
+html,
+body {
+ padding: 0;
+ margin: 0;
+ min-width: 320px;
+}
+
+body {
+ background: #f9f9f9;
+ font-family: "Plus Jakarta Sans", "Inter", sans-serif;
+ font-size: 16px;
+ line-height: 1.6;
+ color: var(--text-color);
+}
+
+a {
+ color: var(--secondary-color);
+ text-decoration: none;
+ transition: color 0.3s ease;
+}
+
+a:hover {
+ color: var(--primary-color);
+}
+
+label {
+ cursor: pointer;
+ color: var(--text-color);
+ font-weight: 500;
+}
+
+h1,
+h2,
+h3,
+h4 {
+ font-weight: 600;
+ color: var(--primary-color);
+ margin-top: 0;
+}
+
+.section {
+ margin-bottom: 2.5rem;
+}
+
+input[type="text"],
+input[type="email"],
+input[type="password"],
+select {
+ padding: 0.75rem 1rem;
+ border: 1px solid var(--border-color);
+ border-radius: 0.375rem;
+ width: 100%;
+ font-size: 1rem;
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
+}
+
+input:focus,
+select:focus {
+ outline: none;
+ border-color: var(--secondary-color);
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
+}
+
+input:focus::placeholder {
+ color: transparent;
+}
+
+input[disabled] {
+ opacity: 0.6;
+ cursor: not-allowed;
+}
+
+.center {
+ text-align: center;
+}
+
+.right {
+ text-align: right;
+}
+
+.error {
+ color: #ef4444;
+ font-size: 0.875rem;
+}
+
+.button {
+ background: var(--primary-color);
+ padding: 0.75rem 1.5rem;
+ border-radius: 0.375rem;
+ border: 0;
+ cursor: pointer;
+ text-decoration: none;
+ color: #ffffff;
+ display: inline-block;
+ min-width: 150px;
+ font-size: 1rem;
+ font-weight: 500;
+ text-align: center;
+ transition: background-color 0.3s ease, transform 0.1s ease;
+}
+
+.button:hover {
+ background: black;
+ color: #ffffff;
+ transform: translateY(-2px);
+ }
+
+.button.button-outline {
+ background: #ffffff;
+ border: 1px solid var(--primary-color);
+ color: var(--primary-color);
+}
+
+.button.button-outline:hover {
+ background-color: var(--primary-color);
+ color: #ffffff;
+}
+
+.container {
+ margin: 3rem auto;
+ max-width: 600px;
+ padding: 0 1rem;
+}
+
+.wrap {
+ background: #ffffff;
+ padding: 2.5rem;
+ border-radius: 0.5rem;
+ box-shadow: 0 4px 6px var(--shadow-color);
+}
+
+.header {
+ border-bottom: 1px solid var(--border-color);
+ padding-bottom: 1rem;
+ margin-bottom: 2rem;
+}
+
+.header .logo img {
+ width: auto;
+ max-width: 150px;
+}
+
+.row {
+ margin-bottom: 1.5rem;
+}
+
+.form .nonce {
+ display: none;
+}
+
+.form .captcha {
+ margin-top: 2rem;
+}
+
+.archive {
+ list-style-type: none;
+ margin: 1.5rem 0 0 0;
+ padding: 0;
+}
+
+.archive .date {
+ display: block;
+ color: #6b7280;
+ font-size: 0.875rem;
+}
+
+footer.container {
+ margin-top: 2rem;
+ text-align: center;
+ color: #9ca3af;
+ font-size: 0.875rem;
+}
+
+footer a {
+ color: #9ca3af;
+ text-decoration: none;
+}
+
+footer a:hover {
+ color: var(--text-color);
+}
+
+.green {
+ color: #10b981;
+}
+
+@media screen and (max-width: 650px) {
+ .wrap {
+ padding: 1.5rem;
+ }
+
+ .container {
+ margin: 1.5rem auto;
+ }
+}
diff --git a/static/public/web-templates/csat.html b/static/public/web-templates/csat.html
new file mode 100644
index 00000000..3ac08530
--- /dev/null
+++ b/static/public/web-templates/csat.html
@@ -0,0 +1,315 @@
+{{ define "csat" }}
+{{ template "header" . }}
+
+
+
+
+
+{{ template "footer" }}
+{{ end }}
\ No newline at end of file
diff --git a/static/public/web-templates/error.html b/static/public/web-templates/error.html
new file mode 100644
index 00000000..984776ee
--- /dev/null
+++ b/static/public/web-templates/error.html
@@ -0,0 +1,11 @@
+{{ define "error" }}
+{{ template "header" . }}
+
+
+ {{ if .Data.ErrorMessage }}
+ {{ .Data.ErrorMessage }}
+ {{ end }}
+
+
+{{ template "footer" . }}
+{{ end }}
\ No newline at end of file
diff --git a/static/public/web-templates/index.html b/static/public/web-templates/index.html
new file mode 100644
index 00000000..ece24569
--- /dev/null
+++ b/static/public/web-templates/index.html
@@ -0,0 +1,38 @@
+{{ define "header" }}
+
+
+
+
+
{{ .Data.Title }} - {{ SiteName }}
+
+
+
+
+ {{ if ne FaviconURL "" }}
+
+ {{ else }}
+
+ {{ end }}
+
+
+
+
+{{ end }}
+
+{{ define "footer" }}
+
+
+
+
+{{ end }}
\ No newline at end of file
diff --git a/static/public/web-templates/info.html b/static/public/web-templates/info.html
new file mode 100644
index 00000000..1a0ccf79
--- /dev/null
+++ b/static/public/web-templates/info.html
@@ -0,0 +1,13 @@
+{{ define "info" }}
+{{ template "header" . }}
+
+
+ {{ .Data.Title }}
+ {{ if .Data.Message }}
+ {{ .Data.Message }}
+ {{ end }}
+
+
+
+{{ template "footer" . }}
+{{ end }}
\ No newline at end of file