lots of things
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<v-app>
|
||||
<Login v-if="!ircStore.connected" />
|
||||
<Chat v-else />
|
||||
<router-view />
|
||||
|
||||
<!-- <Login v-if="!ircStore.connected" /> -->
|
||||
<!-- <Chat v-else /> -->
|
||||
<!-- <v-dialog max-width="450px" v-model="showRegistration"> -->
|
||||
<!-- <Register @success="showRegistration = false" /> -->
|
||||
<!-- </v-dialog> -->
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
@@ -9,6 +14,10 @@
|
||||
import { useIRCStore } from "@/stores/irc";
|
||||
import Chat from "@/components/Chat.vue";
|
||||
import Login from "@/components/Login.vue";
|
||||
import Register from "@/components/Register.vue";
|
||||
import { useAccountStore } from "./stores/accountStore";
|
||||
|
||||
const ircStore = useIRCStore();
|
||||
const accountStore = useAccountStore();
|
||||
const { showRegistration } = storeToRefs(accountStore);
|
||||
</script>
|
||||
|
||||
@@ -10,6 +10,7 @@ const accountStore = useAccountStore();
|
||||
|
||||
<template>
|
||||
<div class="d-flex flex-row" style="height: 100vh">
|
||||
<router-view />
|
||||
<v-sheet border class="buffers">
|
||||
<UserCard />
|
||||
<v-divider />
|
||||
@@ -27,16 +28,10 @@ const accountStore = useAccountStore();
|
||||
:me="accountStore.account.nick"
|
||||
/>
|
||||
<v-sheet>
|
||||
<!-- <v-text-field -->
|
||||
<!-- variant="outlined" -->
|
||||
<!-- :placeholder="`Message ${store.activeBufferName}`" -->
|
||||
<!-- v-model="inputBuffer" -->
|
||||
<!-- hide-details -->
|
||||
<!-- class="ma-2" -->
|
||||
<!-- @keydown.enter.exact.prevent="send" -->
|
||||
<!-- /> -->
|
||||
|
||||
<InputBuffer @send="ircStore.sendActiveBuffer" />
|
||||
<InputBuffer
|
||||
@raw="(txt: string) => ircStore.client.raw(txt)"
|
||||
@send="ircStore.sendActiveBuffer"
|
||||
/>
|
||||
</v-sheet>
|
||||
</div>
|
||||
<v-sheet class="user-list h-100" border>
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { useIRCStore } from "@/stores/irc";
|
||||
import { useBufferStore } from "@/stores/bufferStore";
|
||||
const emit = defineEmits(["send"]);
|
||||
import { useAccountStore } from "@/stores/accountStore";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const emit = defineEmits(["send", "raw"]);
|
||||
|
||||
const store = useIRCStore();
|
||||
const accountStore = useAccountStore();
|
||||
const { showRegistration } = storeToRefs(accountStore);
|
||||
const router = useRouter();
|
||||
const bufferStore = useBufferStore();
|
||||
const text = ref();
|
||||
const menu = ref({
|
||||
@@ -15,7 +21,7 @@ const menu = ref({
|
||||
const menuList = ref({
|
||||
density: "compact",
|
||||
slim: true,
|
||||
items: [],
|
||||
items: [] as any[],
|
||||
itemTitle: "title",
|
||||
itemValue: "value",
|
||||
selected: [],
|
||||
@@ -30,18 +36,26 @@ const completionPos = ref(0);
|
||||
function clickItem() {}
|
||||
function send() {
|
||||
if (!text.value) return;
|
||||
|
||||
if (text.value.slice(0, 2) === "//") {
|
||||
emit("raw", text.value.substring(2));
|
||||
} else if (text.value[0] === "/") {
|
||||
router.push({ path: "/register" });
|
||||
} else {
|
||||
emit("send", text.value);
|
||||
}
|
||||
|
||||
menu.value.open = false;
|
||||
text.value = "";
|
||||
}
|
||||
|
||||
function filterUsers(s) {
|
||||
function filterUsers(s: string) {
|
||||
if (store.activeBuffer) {
|
||||
return store.activeBuffer.users.filter((u) => u.nick.startsWith(s));
|
||||
}
|
||||
}
|
||||
|
||||
function trigger(ev) {
|
||||
function trigger(ev: KeyboardEvent) {
|
||||
const input = ev.target;
|
||||
const cursor = input.selectionStart;
|
||||
cursorPos.value = cursor;
|
||||
@@ -49,7 +63,18 @@ function trigger(ev) {
|
||||
|
||||
const textBefore = text.slice(0, cursor);
|
||||
const mentionMatch = textBefore.match(/@(\w*)$/);
|
||||
if (mentionMatch) {
|
||||
if (text[0] === "/") {
|
||||
menu.value.open = true;
|
||||
menuList.value.items = [
|
||||
{
|
||||
title: "register",
|
||||
value: "register",
|
||||
cmd: () => {
|
||||
showRegistration.value = true;
|
||||
},
|
||||
},
|
||||
];
|
||||
} else if (mentionMatch) {
|
||||
menu.value.open = true;
|
||||
menuList.value.items = filterUsers(mentionMatch[1]);
|
||||
menuList.value.itemTitle = "nick";
|
||||
|
||||
@@ -2,15 +2,21 @@
|
||||
import { useAccountStore } from "@/stores/accountStore";
|
||||
import { useIRCStore } from "@/stores/irc";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useRouter } from "vue-router";
|
||||
const accountStore = useAccountStore();
|
||||
const ircStore = useIRCStore();
|
||||
|
||||
const { account } = storeToRefs(accountStore);
|
||||
const withAccount = ref(false);
|
||||
const form = ref(false);
|
||||
const connecting = ref(false);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
function login() {
|
||||
ircStore.connect();
|
||||
connecting.value = true;
|
||||
router.push({ name: "Chat" });
|
||||
}
|
||||
|
||||
function required(v: any) {
|
||||
@@ -48,7 +54,13 @@ function required(v: any) {
|
||||
<v-checkbox v-model="withAccount" label="Login with an account" />
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn type="submit" color="success" :disabled="!form">Connect</v-btn>
|
||||
<v-btn
|
||||
:loading="connecting"
|
||||
type="submit"
|
||||
color="success"
|
||||
:disabled="!form"
|
||||
>Connect</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
</v-form>
|
||||
</v-card>
|
||||
|
||||
@@ -51,6 +51,15 @@ watch(
|
||||
<span class="message-time" v-if="!!msg.time">{{
|
||||
formatTime(msg.time)
|
||||
}}</span>
|
||||
<v-chip
|
||||
class="ml-2"
|
||||
v-bind="props"
|
||||
label
|
||||
color="purple-lighten-2"
|
||||
v-if="msg.kind === 'notice'"
|
||||
size="x-small"
|
||||
><v-icon class="mr-2">mdi-eye</v-icon>Only visible to you
|
||||
</v-chip>
|
||||
</v-list-item-title>
|
||||
{{ msg.message }}
|
||||
</v-list-item></template
|
||||
|
||||
88
app/frontend/src/components/Register.vue
Normal file
88
app/frontend/src/components/Register.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<script lang="ts" setup>
|
||||
import { HookStatus, useIRCStore } from "@/stores/irc";
|
||||
import { onBeforeMount, onBeforeUnmount } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
const router = useRouter();
|
||||
const ircStore = useIRCStore();
|
||||
const emit = defineEmits(["success"]);
|
||||
|
||||
const RegistrationSuccess = new RegExp(/Account created/);
|
||||
function interceptNickServMessage(message: { nick: string; message: string }) {
|
||||
if (message.nick !== "NickServ") {
|
||||
return HookStatus.HOOK_OK;
|
||||
}
|
||||
|
||||
registering.value = false;
|
||||
|
||||
if (message.message.match(RegistrationSuccess)) {
|
||||
emit("success");
|
||||
}
|
||||
|
||||
return HookStatus.HOOK_EAT;
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
ircStore.registerHook("message", interceptNickServMessage);
|
||||
ircStore.registerHook("notice", interceptNickServMessage);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
ircStore.unregisterHook("message", interceptNickServMessage);
|
||||
ircStore.unregisterHook("notice", interceptNickServMessage);
|
||||
});
|
||||
|
||||
const newAccount = ref({
|
||||
email: "",
|
||||
username: "",
|
||||
password: "",
|
||||
});
|
||||
|
||||
const form = ref(false);
|
||||
const registering = ref(false);
|
||||
|
||||
function register() {
|
||||
if (!form.value) return;
|
||||
|
||||
const { password, email } = newAccount.value;
|
||||
registering.value = true;
|
||||
ircStore.client.say("NickServ", `REGISTER ${password} ${email}`);
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
router.back();
|
||||
}
|
||||
const show = ref(true);
|
||||
</script>
|
||||
<template>
|
||||
<v-dialog v-model="show" max-width="400px" persistent>
|
||||
<v-card title="Account Registration">
|
||||
<v-form v-model="form" @submit.prevent="register">
|
||||
<v-card-text>
|
||||
<v-text-field
|
||||
:rules="[(v) => !!v || 'Email required']"
|
||||
v-model="newAccount.email"
|
||||
label="Email"
|
||||
role="email"
|
||||
/>
|
||||
<v-text-field
|
||||
:rules="[(v) => !!v || 'Password required']"
|
||||
v-model="newAccount.password"
|
||||
label="Password"
|
||||
role="password"
|
||||
type="password"
|
||||
/>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn
|
||||
:disabled="!form"
|
||||
type="submit"
|
||||
:loading="registering"
|
||||
text="Register"
|
||||
color="success"
|
||||
/>
|
||||
<v-btn @click="cancel">Cancel</v-btn>
|
||||
</v-card-actions>
|
||||
</v-form>
|
||||
</v-card></v-dialog
|
||||
>
|
||||
</template>
|
||||
@@ -1,8 +1,9 @@
|
||||
import vuetify from "./vuetify";
|
||||
import pinia from "@/stores";
|
||||
import router from "./router.ts";
|
||||
|
||||
import type { App } from "vue";
|
||||
|
||||
export function registerPlugins(app: App) {
|
||||
app.use(vuetify).use(pinia);
|
||||
app.use(vuetify).use(router).use(pinia);
|
||||
}
|
||||
|
||||
37
app/frontend/src/plugins/router.ts
Normal file
37
app/frontend/src/plugins/router.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { createMemoryHistory, createRouter } from "vue-router";
|
||||
import Chat from "@/components/Chat.vue";
|
||||
import { useIRCStore } from "@/stores/irc";
|
||||
const routes = [
|
||||
{
|
||||
path: "/",
|
||||
name: "Chat",
|
||||
component: Chat,
|
||||
children: [
|
||||
{
|
||||
path: "register",
|
||||
name: "Register",
|
||||
component: () => import("@/components/Register.vue"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/login",
|
||||
name: "Login",
|
||||
component: () => import("@/components/Login.vue"),
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createMemoryHistory(),
|
||||
routes,
|
||||
});
|
||||
|
||||
router.beforeEach(async (to, from) => {
|
||||
if (!useIRCStore().connected && to.name !== "Login") {
|
||||
return { name: "Login" };
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
export default router;
|
||||
@@ -3,6 +3,7 @@ import { ref } from "vue";
|
||||
|
||||
export const useAccountStore = defineStore("accountStore", () => {
|
||||
const authenticated = ref(false);
|
||||
const showRegistration = ref(false);
|
||||
const account = ref({
|
||||
nick: "",
|
||||
account: "",
|
||||
@@ -21,5 +22,13 @@ export const useAccountStore = defineStore("accountStore", () => {
|
||||
account.value.nick = v;
|
||||
}
|
||||
|
||||
return { account, authError, authenticated, setAuthenticated, setNick };
|
||||
return {
|
||||
account,
|
||||
authError,
|
||||
authenticated,
|
||||
showRegistration,
|
||||
setAuthenticated,
|
||||
setNick,
|
||||
showRegistration,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,15 +1,50 @@
|
||||
import { defineStore, storeToRefs } from "pinia";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Client } from "irc-framework";
|
||||
import { useBufferStore } from "./bufferStore";
|
||||
import { ref } from "vue";
|
||||
import { useAccountStore } from "./accountStore";
|
||||
|
||||
export type HookFunction = (event: any) => HookStatus;
|
||||
|
||||
export enum HookStatus {
|
||||
HOOK_OK,
|
||||
HOOK_EAT,
|
||||
}
|
||||
|
||||
export const useIRCStore = defineStore("ircStore", () => {
|
||||
const bufferStore = useBufferStore();
|
||||
const accountStore = useAccountStore();
|
||||
const connected = ref(false);
|
||||
const { authError } = storeToRefs(accountStore);
|
||||
|
||||
const hooks = {} as Record<string, HookFunction[]>;
|
||||
|
||||
function registerHook(event: string, f: HookFunction) {
|
||||
if (hooks[event]) hooks[event].push(f);
|
||||
else hooks[event] = [f];
|
||||
}
|
||||
|
||||
function runHook(eventName: string, eventArgs: any): HookStatus {
|
||||
if (!hooks[eventName]) return HookStatus.HOOK_OK;
|
||||
let lastRetVal = HookStatus.HOOK_OK;
|
||||
|
||||
for (const hookFunction of hooks[eventName]) {
|
||||
const retVal = hookFunction(eventArgs);
|
||||
if (retVal === HookStatus.HOOK_EAT) return retVal;
|
||||
lastRetVal = retVal;
|
||||
}
|
||||
|
||||
return lastRetVal;
|
||||
}
|
||||
|
||||
function unregisterHook(eventName: string, f: HookFunction) {
|
||||
if (!hooks[eventName]) return;
|
||||
const idx = hooks[eventName].findIndex((item) => item === f);
|
||||
if (idx === -1) return;
|
||||
hooks[eventName].splice(idx, 1);
|
||||
}
|
||||
|
||||
const selfAvatar = ref("https://placekittens.com/128/128");
|
||||
const bio = ref();
|
||||
|
||||
@@ -85,7 +120,6 @@ export const useIRCStore = defineStore("ircStore", () => {
|
||||
nick: accountStore.account.nick,
|
||||
};
|
||||
|
||||
console.log(connectParams);
|
||||
client.connect(connectParams);
|
||||
}
|
||||
|
||||
@@ -93,11 +127,12 @@ export const useIRCStore = defineStore("ircStore", () => {
|
||||
if (!bufferStore.activeBuffer) {
|
||||
return;
|
||||
}
|
||||
if (bufferStore.activeBuffer.channel)
|
||||
bufferStore.activeBuffer.channel.say(message);
|
||||
else client.say(bufferStore.activeBuffer.name, message);
|
||||
}
|
||||
|
||||
function isMe(target: string) {
|
||||
console.log(client.user.nick);
|
||||
return target === client.user.nick;
|
||||
}
|
||||
|
||||
@@ -129,8 +164,10 @@ export const useIRCStore = defineStore("ircStore", () => {
|
||||
},
|
||||
);
|
||||
|
||||
const router = useRouter();
|
||||
client.on("registered", function () {
|
||||
connected.value = true;
|
||||
router.push({ name: "Chat" });
|
||||
client.list();
|
||||
client.raw("METADATA * SUB avatar");
|
||||
client.raw("METADATA * SUB bio");
|
||||
@@ -207,14 +244,22 @@ export const useIRCStore = defineStore("ircStore", () => {
|
||||
|
||||
client.on("message", function (message: { nick: string; target: string }) {
|
||||
let buffer;
|
||||
|
||||
const retVal = runHook("message", message);
|
||||
if (retVal === HookStatus.HOOK_EAT) return;
|
||||
|
||||
if (message.nick === "HistServ") return;
|
||||
if (isMe(message.target)) {
|
||||
buffer = bufferStore.getBuffer(message.nick);
|
||||
} else {
|
||||
buffer = bufferStore.getBuffer(message.target);
|
||||
}
|
||||
|
||||
if (!buffer) {
|
||||
return;
|
||||
buffer = bufferStore.addBuffer(message.nick, {
|
||||
name: message.nick,
|
||||
channel: null,
|
||||
});
|
||||
}
|
||||
|
||||
buffer.messages.push(message);
|
||||
@@ -227,6 +272,14 @@ export const useIRCStore = defineStore("ircStore", () => {
|
||||
}
|
||||
});
|
||||
|
||||
client.on("notice", function (message) {
|
||||
const retVal = runHook("notice", message);
|
||||
if (retVal === HookStatus.HOOK_EAT) return;
|
||||
if (bufferStore.activeBuffer) {
|
||||
bufferStore.activeBuffer.messages.push({ ...message, kind: "notice" });
|
||||
}
|
||||
});
|
||||
|
||||
client.on("join", ({ nick, channel }: { nick: string; channel: string }) => {
|
||||
if (isMe(nick)) {
|
||||
bufferStore.addBuffer(channel, {
|
||||
@@ -294,5 +347,7 @@ export const useIRCStore = defineStore("ircStore", () => {
|
||||
setBio,
|
||||
bio,
|
||||
connected,
|
||||
registerHook,
|
||||
unregisterHook,
|
||||
};
|
||||
});
|
||||
|
||||
299
app/package-lock.json
generated
299
app/package-lock.json
generated
@@ -1,6 +1,301 @@
|
||||
{
|
||||
"name": "IrChad",
|
||||
"name": "app",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"vue-router": "^4.6.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
|
||||
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz",
|
||||
"integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.28.6"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz",
|
||||
"integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.28.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@vue/compiler-core": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.26.tgz",
|
||||
"integrity": "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@vue/shared": "3.5.26",
|
||||
"entities": "^7.0.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-dom": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz",
|
||||
"integrity": "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-sfc": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz",
|
||||
"integrity": "sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@vue/compiler-core": "3.5.26",
|
||||
"@vue/compiler-dom": "3.5.26",
|
||||
"@vue/compiler-ssr": "3.5.26",
|
||||
"@vue/shared": "3.5.26",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.21",
|
||||
"postcss": "^8.5.6",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-ssr": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz",
|
||||
"integrity": "sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/devtools-api": {
|
||||
"version": "6.6.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
|
||||
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@vue/reactivity": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.26.tgz",
|
||||
"integrity": "sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-core": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.26.tgz",
|
||||
"integrity": "sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-dom": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.26.tgz",
|
||||
"integrity": "sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "3.5.26",
|
||||
"@vue/runtime-core": "3.5.26",
|
||||
"@vue/shared": "3.5.26",
|
||||
"csstype": "^3.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/server-renderer": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.26.tgz",
|
||||
"integrity": "sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-ssr": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz",
|
||||
"integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.0.tgz",
|
||||
"integrity": "sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.21",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.6",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/postcss"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.26.tgz",
|
||||
"integrity": "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.26",
|
||||
"@vue/compiler-sfc": "3.5.26",
|
||||
"@vue/runtime-dom": "3.5.26",
|
||||
"@vue/server-renderer": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vue-router": {
|
||||
"version": "4.6.4",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz",
|
||||
"integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/devtools-api": "^6.6.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/posva"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.5.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
app/package.json
Normal file
5
app/package.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"vue-router": "^4.6.4"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user