Compare commits

..

23 Commits

Author SHA1 Message Date
iamBadgers
b5f0e8afbb minor ui tweaks 2025-07-13 11:14:33 -07:00
iamBadgers
b21e763d65 Initial pass on character lists. 2025-07-06 00:11:25 -07:00
iamBadgers
8745fc3c7e Add in some ui work for listing available characters. 2025-07-05 00:10:59 -07:00
iamBadgers
0707250864 Only idiots throw null... 2025-07-04 00:02:06 -07:00
iamBadgers
25cb93fba0 Progress with some fancy webrpc stuff through traefik 2025-06-20 01:41:15 -07:00
iamBadgers
d480267c64 random-ass changes 2025-06-19 23:34:08 -07:00
iamBadgers
a62fe1aba9 work on the list call 2025-06-16 00:21:03 -07:00
iamBadgers
1f43ff468b move flags to its own module. 2025-06-15 22:09:18 -07:00
iamBadgers
aa4c44840b move flags to its own module. 2025-06-14 17:12:49 -07:00
iamBadgers
882e8cf72a add commander for cli flags 2025-06-14 16:16:40 -07:00
iamBadgers
28a991c7d4 move over to database service cause I forgot I made that 2025-06-14 00:48:33 -07:00
iamBadgers
7230d526e0 Get it to store data from grpc calls. 2025-06-13 21:17:35 -07:00
iamBadgers
1bcaedc293 get mongo running 2025-06-13 00:01:55 -07:00
iamBadgers
39a3783ebd add reflection service to valut 2025-06-12 19:28:42 -07:00
iamBadgers
a4be179faf Finally up and running again. 2025-06-12 00:10:12 -07:00
iamBadgers
dbf550b700 small cleanup 2025-06-11 00:03:39 -07:00
iamBadgers
af408e5246 fix up docker files 2025-06-10 23:53:18 -07:00
iamBadgers
8d9bfa3fe0 Move frontend into front end folder. Add build stuff to proto file. Finaly figured out the Vue bullshit. 2025-06-10 23:31:54 -07:00
iamBadgers
4f126594e5 boilerplate for grpc 2025-06-08 00:31:24 -07:00
iamBadgers
2d81203398 fix up some docker build issues re pathing 2025-06-07 23:55:37 -07:00
iamBadgers
a3ecb70abe Update docker files to build from the folder above to include the proto files. 2025-06-07 23:33:38 -07:00
iamBadgers
a2a51754f7 partial work on initting protos 2025-06-07 22:28:16 -07:00
iamBadgers
7d13bc0c47 cleanup vault packages 2025-06-07 22:20:44 -07:00
59 changed files with 5427 additions and 5728 deletions

5
.dockerignore Normal file
View File

@@ -0,0 +1,5 @@
dist
frontend/node_modules
vault/node_modules
vault/src/proto
frontend/src/proto

4
.gitignore vendored
View File

@@ -7,6 +7,10 @@ __pycache__
dist dist
rush-character-archive/dist rush-character-archive/dist
# generated files
frontend/src/proto
vault/src/proto
# sqlite file # sqlite file
*.db *.db
*.sqbpro *.sqbpro

128
build.log Normal file
View File

@@ -0,0 +1,128 @@
#0 building with "desktop-linux" instance using docker driver
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 322B done
#1 DONE 0.0s
#2 [internal] load metadata for docker.io/library/node:22.16
#2 DONE 0.3s
#3 [internal] load .dockerignore
#3 transferring context: 120B done
#3 DONE 0.0s
#4 [ 1/10] FROM docker.io/library/node:22.16@sha256:71bcbb3b215b3fa84b5b167585675072f4c270855e37a599803f1a58141a0716
#4 resolve docker.io/library/node:22.16@sha256:71bcbb3b215b3fa84b5b167585675072f4c270855e37a599803f1a58141a0716 0.0s done
#4 DONE 0.0s
#5 [ 2/10] WORKDIR /srv/proto
#5 CACHED
#6 [internal] load build context
#6 transferring context: 285.61kB 0.1s done
#6 DONE 0.1s
#7 [ 3/10] COPY proto/ .
#7 DONE 0.8s
#8 [ 4/10] WORKDIR /srv/frontend
#8 DONE 0.1s
#9 [ 5/10] COPY frontend/package.json .
#9 DONE 0.1s
#10 [ 6/10] RUN npm install
#10 10.52
#10 10.52 added 328 packages, and audited 329 packages in 10s
#10 10.52
#10 10.52 90 packages are looking for funding
#10 10.52 run `npm fund` for details
#10 10.52
#10 10.52 found 0 vulnerabilities
#10 10.52 npm notice
#10 10.52 npm notice New major version of npm available! 10.9.2 -> 11.4.1
#10 10.52 npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.4.1
#10 10.52 npm notice To update run: npm install -g npm@11.4.1
#10 10.52 npm notice
#10 DONE 11.1s
#11 [ 7/10] COPY frontend/. .
#11 DONE 0.2s
#12 [ 8/10] RUN npm i -g serve
#12 2.048
#12 2.048 added 88 packages in 2s
#12 2.048
#12 2.048 24 packages are looking for funding
#12 2.048 run `npm fund` for details
#12 DONE 2.1s
#13 [ 9/10] RUN npm run build_protos
#13 0.279
#13 0.279 > frontend@0.0.0 build_protos
#13 0.279 > mkdir -p src/proto & npx protoc -I=../proto/ --ts_out=server_grpc1:./src/proto --proto_path ../proto ../proto/*.proto
#13 0.279
#13 1.394 @protobuf-ts/protoc installed protoc v31.1.
#13 DONE 1.8s
#14 [10/10] RUN npm run build
#14 0.235
#14 0.235 > frontend@0.0.0 build
#14 0.235 > run-p type-check "build-only {@}" --
#14 0.235
#14 0.323
#14 0.323 > frontend@0.0.0 build-only
#14 0.323 > vite build
#14 0.323
#14 0.325
#14 0.325 > frontend@0.0.0 type-check
#14 0.325 > vue-tsc --build
#14 0.325
#14 0.752 vite v6.3.5 building for production...
#14 0.805 transforming...
#14 1.191 ✓ 69 modules transformed.
#14 1.297 rendering chunks...
#14 1.301 computing gzip size...
#14 1.307 dist/index.html 0.43 kB │ gzip: 0.28 kB
#14 1.307 dist/assets/index-TXLObeWa.css 3.71 kB │ gzip: 1.19 kB
#14 1.307 dist/assets/index-0ixp9Wqt.js 105.33 kB │ gzip: 37.78 kB
#14 1.307 ✓ built in 530ms
#14 1.467 src/proto/character.grpc-server.ts(7,28): error TS2307: Cannot find module '@grpc/grpc-js' or its corresponding type declarations.
#14 1.467 src/proto/character.grpc-server.ts(38,30): error TS7006: Parameter 'bytes' implicitly has an 'any' type.
#14 1.467 src/proto/character.grpc-server.ts(39,29): error TS7006: Parameter 'bytes' implicitly has an 'any' type.
#14 1.467 src/proto/character.grpc-server.ts(40,28): error TS7006: Parameter 'value' implicitly has an 'any' type.
#14 1.467 src/proto/character.grpc-server.ts(40,37): error TS2591: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
#14 1.467 src/proto/character.grpc-server.ts(41,27): error TS7006: Parameter 'value' implicitly has an 'any' type.
#14 1.467 src/proto/character.grpc-server.ts(41,36): error TS2591: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
#14 1.467 src/proto/character.grpc-server.ts(48,30): error TS7006: Parameter 'bytes' implicitly has an 'any' type.
#14 1.467 src/proto/character.grpc-server.ts(49,29): error TS7006: Parameter 'bytes' implicitly has an 'any' type.
#14 1.467 src/proto/character.grpc-server.ts(50,28): error TS7006: Parameter 'value' implicitly has an 'any' type.
#14 1.467 src/proto/character.grpc-server.ts(50,37): error TS2591: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
#14 1.467 src/proto/character.grpc-server.ts(51,27): error TS7006: Parameter 'value' implicitly has an 'any' type.
#14 1.467 src/proto/character.grpc-server.ts(51,36): error TS2591: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
#14 1.485 ERROR: "type-check" exited with 2.
#14 ERROR: process "/bin/sh -c npm run build" did not complete successfully: exit code: 1
------
> [10/10] RUN npm run build:
1.467 src/proto/character.grpc-server.ts(40,37): error TS2591: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
1.467 src/proto/character.grpc-server.ts(41,27): error TS7006: Parameter 'value' implicitly has an 'any' type.
1.467 src/proto/character.grpc-server.ts(41,36): error TS2591: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
1.467 src/proto/character.grpc-server.ts(48,30): error TS7006: Parameter 'bytes' implicitly has an 'any' type.
1.467 src/proto/character.grpc-server.ts(49,29): error TS7006: Parameter 'bytes' implicitly has an 'any' type.
1.467 src/proto/character.grpc-server.ts(50,28): error TS7006: Parameter 'value' implicitly has an 'any' type.
1.467 src/proto/character.grpc-server.ts(50,37): error TS2591: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
1.467 src/proto/character.grpc-server.ts(51,27): error TS7006: Parameter 'value' implicitly has an 'any' type.
1.467 src/proto/character.grpc-server.ts(51,36): error TS2591: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
1.485 ERROR: "type-check" exited with 2.
------
Dockerfile:20
--------------------
18 |
19 | RUN npm run build_protos
20 | >>> RUN npm run build
21 |
22 | EXPOSE 8080
--------------------
ERROR: failed to solve: process "/bin/sh -c npm run build" did not complete successfully: exit code: 1
View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/k2rob0qo9fs8fmawdf7vwutz8

View File

@@ -1,32 +1,43 @@
networks:
rush-character-net:
services: services:
rush-character-archive:
build: ./rush-character-archive proxy:
command: npm run dev image: traefik
networks: command: --providers.docker
- rush-character-net
ports: ports:
- 8080:3000 - 80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
frontend:
build:
context: ./
dockerfile: ./frontend/Dockerfile
command: npm run dev
develop: develop:
watch: watch:
- action: sync - action: sync
path: ./rush-character-archive path: ./frontend
target: /srv/rush-character-archive target: /srv/frontend
ignore: ignore:
- node_modules - node_modules
- action: rebuild - action: rebuild
path: ./rush-character-archive/package.json path: ./frontend/package.json
- action: rebuild - action: rebuild
path: ./rush-character-archive/Dockerfile path: ./frontend/Dockerfile
vault: labels:
build: ./vault traefik.http.routers.client.rule: "Host(`localhost`)"
command: npm run dev
networks:
- rush-character-net
ports: ports:
- 8081:8080 - 8080:3000
vault:
build:
context: ./
dockerfile: ./vault/Dockerfile
command: npm run dev
environment:
MONGO_URI: mongodb://rushvault:rushvault@mongo:27017/
depends_on:
- mongo
develop: develop:
watch: watch:
- action: sync - action: sync
@@ -38,6 +49,14 @@ services:
path: ./vault/package.json path: ./vault/package.json
- action: rebuild - action: rebuild
path: ./vault/Dockerfile path: ./vault/Dockerfile
ports:
- 8081:8080
labels:
traefik.http.routers.api.rule: "Host(`localhost`) && PathPrefix(`/api`)"
traefik.http.services.api.loadbalancer.server.scheme: "h2c"
traefik.http.routers.api.middlewares: "api-stripprefix,api-grpcweb"
traefik.http.middlewares.api-stripprefix.stripprefix.prefixes: "/api"
traefik.http.middlewares.api-grpcweb.grpcWeb.allowOrigins: "*"
mongo: mongo:
image: mongo image: mongo
@@ -45,28 +64,19 @@ services:
environment: environment:
MONGO_INITDB_ROOT_USERNAME: rushvault MONGO_INITDB_ROOT_USERNAME: rushvault
MONGO_INITDB_ROOT_PASSWORD: rushvault MONGO_INITDB_ROOT_PASSWORD: rushvault
MONGO_INITDB_DATABASE: DB
mongo-express: mongo-express:
image: mongo-express image: mongo-express
restart: always restart: always
ports: depends_on:
- 8083:8081 - mongo
environment: environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: rushvault ME_CONFIG_MONGODB_ADMINUSERNAME: rushvault
ME_CONFIG_MONGODB_ADMINPASSWORD: rushvault ME_CONFIG_MONGODB_ADMINPASSWORD: rushvault
ME_CONFIG_MONGODB_URL: mongodb://rushvault:rushvault@mongo:27017/ ME_CONFIG_MONGODB_URL: mongodb://rushvault:rushvault@mongo:27017/
ME_CONFIG_BASICAUTH: false ME_CONFIG_BASICAUTH: false
labels:
# db: traefik.http.routers.mexp.rule: "Host(`mexp.localhost`)"
# image: postgres:17-bookworm ports:
# networks: - 8082:8081
# - rush-character-net
# environment:
# POSTGRES_USER: rushvault
# POSTGRES_PASSWORD: rushvault
# POSTGRES_DB: rushvault
# adminer:
# image: adminer
# networks:
# - rush-character-net
# ports:
# - 8082:8080

View File

@@ -2,5 +2,5 @@
"$schema": "https://json.schemastore.org/prettierrc", "$schema": "https://json.schemastore.org/prettierrc",
"semi": false, "semi": false,
"singleQuote": true, "singleQuote": true,
"printWidth": 100 "printWidth": 80
} }

23
frontend/Dockerfile Normal file
View File

@@ -0,0 +1,23 @@
FROM node:22.16
WORKDIR /srv/proto
COPY proto/ .
# RUN npm install
# RUN npm run build
WORKDIR /srv/frontend
COPY frontend/package.json .
RUN npm install
COPY frontend/. .
RUN npm i -g serve
RUN npm run build
EXPOSE 3000
CMD ["serve", "-s", "dist"]

View File

@@ -1,4 +1,4 @@
# rush-character-archive # frontend
This template should help get you started developing with Vue 3 in Vite. This template should help get you started developing with Vue 3 in Vite.

View File

@@ -9,14 +9,14 @@ import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
// More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup // More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup
export default defineConfigWithVueTs( export default defineConfigWithVueTs(
{ // {
name: 'app/files-to-lint', // name: 'app/files-to-lint',
files: ['**/*.{ts,mts,tsx,vue}'], // files: ['**/*.{ts,mts,tsx,vue}'],
}, // },
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']), // globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
pluginVue.configs['flat/essential'], // pluginVue.configs['flat/essential'],
vueTsConfigs.recommended, // vueTsConfigs.recommended,
skipFormatting, // skipFormatting,
) )

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,12 @@
{ {
"name": "rush-character-archive", "name": "frontend",
"version": "0.0.0", "version": "0.0.0",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "run-p type-check \"build-only {@}\" --", "build_protos": "mkdir -p src/proto & npx protoc -I=../proto/ --ts_out ./src/proto --proto_path ../proto ../proto/*.proto",
"build": "run-p build_protos && run-p type-check \"build-only {@}\" --",
"preview": "vite preview", "preview": "vite preview",
"build-only": "vite build", "build-only": "vite build",
"type-check": "vue-tsc --build", "type-check": "vue-tsc --build",
@@ -13,18 +14,25 @@
"format": "prettier --write src/" "format": "prettier --write src/"
}, },
"dependencies": { "dependencies": {
"@vueuse/core": "^13.5.0",
"json-editor-vue": "^0.18.1",
"vue": "^3.5.13", "vue": "^3.5.13",
"vue-router": "^4.5.0" "vuetify": "^3.8.12"
}, },
"devDependencies": { "devDependencies": {
"@protobuf-ts/grpcweb-transport": "^2.11.0",
"@protobuf-ts/plugin": "^2.11.0",
"@tsconfig/node22": "^22.0.1", "@tsconfig/node22": "^22.0.1",
"@types/node": "^22.14.0", "@types/google-protobuf": "^3.15.12",
"@types/node": "^22.15.31",
"@vitejs/plugin-vue": "^5.2.3", "@vitejs/plugin-vue": "^5.2.3",
"@vue/eslint-config-prettier": "^10.2.0", "@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.5.0", "@vue/eslint-config-typescript": "^14.5.0",
"@vue/tsconfig": "^0.7.0", "@vue/tsconfig": "^0.7.0",
"eslint": "^9.22.0", "eslint": "^9.22.0",
"eslint-plugin-vue": "~10.0.0", "eslint-plugin-vue": "~10.0.0",
"google-protobuf": "^3.21.4",
"grpc-web": "^1.5.0",
"jiti": "^2.4.2", "jiti": "^2.4.2",
"npm-run-all2": "^7.0.2", "npm-run-all2": "^7.0.2",
"prettier": "3.5.3", "prettier": "3.5.3",

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

77
frontend/src/App.vue Normal file
View File

@@ -0,0 +1,77 @@
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
import TheWelcome from './components/TheWelcome.vue'
import CharacterEditer from './components/CharacterEditer.vue'
import CharacterSelector from './components/CharacterSelector.vue'
import { Character, ListCharacterRequest } from './proto/character'
import { CharacterManagerClient } from './proto/character.client'
import { GrpcWebFetchTransport } from '@protobuf-ts/grpcweb-transport'
const client = new CharacterManagerClient(
new GrpcWebFetchTransport({
baseUrl: 'http://localhost/api',
format: 'binary',
}),
)
const butts = () => {
console.log('click')
let request = ListCharacterRequest.fromJson({
playerName: 'potato',
characterName: 'spud',
})
return client.listCharacters(request).then((res) => {
console.log(res)
return res
})
}
</script>
<template>
<header>
<img
alt="Vue logo"
class="logo"
src="./assets/logo.svg"
width="125"
height="125"
/>
</header>
<main>
<CharacterSelector></CharacterSelector>
<!-- potato
<button class="button" @click="butts">butts</button>
<CharacterEditer></CharacterEditer> -->
</main>
</template>
<style scoped>
header {
line-height: 1.5;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
}
</style>

View File

Before

Width:  |  Height:  |  Size: 276 B

After

Width:  |  Height:  |  Size: 276 B

View File

@@ -0,0 +1,24 @@
<template>
<div>{{ character }}</div>
<JsonEditorVue v-model="value" v-bind="{}" />
<v-btn>Save Character</v-btn>
</template>
<style></style>
<script setup lang="ts">
import { ref } from 'vue'
import JsonEditorVue from 'json-editor-vue'
import { Character } from '../proto/character'
const value = ref({})
const character: Character = {
playerName: '',
characterName: '',
characterAlias: [],
version: '',
sourceTable: '',
json: '{}',
}
</script>

View File

@@ -0,0 +1,79 @@
<template>
<v-text-field
v-model="characterSearch"
label="Character Name / Alias"
type="input"
clearable
></v-text-field>
<v-text-field
v-model="playerSearch"
label="Player Name"
type="input"
clearable
></v-text-field>
<div v-for="character in characterList">{{ character }}</div>
<v-expansion-panels>
<CharacterSelectorRow
v-for="character in characterList"
:character="character"
/>
</v-expansion-panels>
</template>
<style></style>
<script setup lang="ts">
import { ref, watch, onMounted } from 'vue'
import { Character, ListCharacterRequest } from '../proto/character'
import { CharacterManagerClient } from '../proto/character.client'
import { GrpcWebFetchTransport } from '@protobuf-ts/grpcweb-transport'
import { watchDebounced } from '@vueuse/core'
import CharacterSelectorRow from './CharacterSelectorRow.vue'
const characterSearch = ref('')
const playerSearch = ref('')
const characterList = ref(new Array<Character>())
const client = new CharacterManagerClient(
new GrpcWebFetchTransport({
baseUrl: 'http://localhost/api',
format: 'binary',
}),
)
watchDebounced(
[characterSearch, playerSearch],
(
[newCharacterValue, oldCharacterValue],
[newPlayerValue, oldPlayerValue],
) => {
console.log(newCharacterValue)
console.log(newPlayerValue)
client
.listCharacters({
characterName: characterSearch.value,
playerName: playerSearch.value,
})
.then((res) => {
characterList.value = res.response.characters
})
},
{ debounce: 500 },
)
onMounted(() => {
let request = ListCharacterRequest.fromJson({
playerName: '',
characterName: '',
})
client.listCharacters(request).then((res) => {
characterList.value = res.response.characters
})
})
</script>

View File

@@ -0,0 +1,61 @@
<template>
<v-expansion-panel>
<v-expansion-panel-title>
<div class="d-flex flex-row">
<div class="charactername">{{ characterName }}</div>
<div class="playername">( {{ playerName }} )</div>
</div>
</v-expansion-panel-title>
<v-expansion-panel-text>
<div>Alias: {{ alias }}</div>
<JsonEditorVue v-model="json" v-bind="editorConfig" />
</v-expansion-panel-text>
</v-expansion-panel>
</template>
<style>
.charactername {
font-weight: bold;
margin-right: 10px;
}
</style>
<script setup lang="ts">
import JsonEditorVue from 'json-editor-vue'
import { computed } from 'vue'
import { Character, ListCharacterRequest } from '../proto/character'
const editorConfig = {
mainMenuBar: false,
navigationBar: false,
readOnly: true,
}
const {
character = {
playerName: 'Unkown Player',
characterName: 'Player Character',
characterAlias: ['No Alias'],
json: "",
},
} = defineProps<{ character?: Character }>()
const playerName = computed(() => {
return character.playerName || 'Unnamed Player'
})
const characterName = computed(() => {
return character.characterName || 'Unnamed Character'
})
const alias = computed(() => {
return (character.characterAlias || [])
.map((entry) => '"' + entry + '"')
.join(', ')
})
const json = computed(() => {
return character.json || '{}'
})
</script>

View File

@@ -1,3 +1,4 @@
d
<script setup lang="ts"> <script setup lang="ts">
defineProps<{ defineProps<{
msg: string msg: string
@@ -10,7 +11,7 @@ defineProps<{
<h3> <h3>
Youve successfully created a project with Youve successfully created a project with
<a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> + <a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>. What's next? <a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
</h3> </h3>
</div> </div>
</template> </template>

View File

@@ -17,7 +17,9 @@ const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
<template #heading>Documentation</template> <template #heading>Documentation</template>
Vues Vues
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a> <a href="https://vuejs.org/" target="_blank" rel="noopener"
>official documentation</a
>
provides you with all information you need to get started. provides you with all information you need to get started.
</WelcomeItem> </WelcomeItem>
@@ -28,23 +30,35 @@ const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
<template #heading>Tooling</template> <template #heading>Tooling</template>
This project is served and bundled with This project is served and bundled with
<a href="https://vite.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The <a
recommended IDE setup is href="https://vite.dev/guide/features.html"
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> target="_blank"
rel="noopener"
>Vite</a
>. The recommended IDE setup is
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener"
>VSCode</a
>
+ +
<a href="https://github.com/vuejs/language-tools" target="_blank" rel="noopener" <a
href="https://github.com/vuejs/language-tools"
target="_blank"
rel="noopener"
>Vue - Official</a >Vue - Official</a
>. If you need to test your components and web pages, check out >. If you need to test your components and web pages, check out
<a href="https://vitest.dev/" target="_blank" rel="noopener">Vitest</a> <a href="https://vitest.dev/" target="_blank" rel="noopener">Vitest</a>
and and
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a> <a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a>
/ /
<a href="https://playwright.dev/" target="_blank" rel="noopener">Playwright</a>. <a href="https://playwright.dev/" target="_blank" rel="noopener"
>Playwright</a
>.
<br /> <br />
More instructions are available in More instructions are available in
<a href="javascript:void(0)" @click="openReadmeInEditor"><code>README.md</code></a <a href="javascript:void(0)" @click="openReadmeInEditor"
><code>README.md</code></a
>. >.
</WelcomeItem> </WelcomeItem>
@@ -56,11 +70,21 @@ const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
Get official tools and libraries for your project: Get official tools and libraries for your project:
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>, <a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>, <a href="https://router.vuejs.org/" target="_blank" rel="noopener"
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and >Vue Router</a
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If >,
you need more resources, we suggest paying <a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener"
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a> >Vue Test Utils</a
>, and
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener"
>Vue Dev Tools</a
>. If you need more resources, we suggest paying
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
rel="noopener"
>Awesome Vue</a
>
a visit. a visit.
</WelcomeItem> </WelcomeItem>
@@ -73,10 +97,15 @@ const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
Got stuck? Ask your question on Got stuck? Ask your question on
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a> <a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>
(our official Discord server), or (our official Discord server), or
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener" <a
href="https://stackoverflow.com/questions/tagged/vue.js"
target="_blank"
rel="noopener"
>StackOverflow</a >StackOverflow</a
>. You should also follow the official >. You should also follow the official
<a href="https://bsky.app/profile/vuejs.org" target="_blank" rel="noopener">@vuejs.org</a> <a href="https://bsky.app/profile/vuejs.org" target="_blank" rel="noopener"
>@vuejs.org</a
>
Bluesky account or the Bluesky account or the
<a href="https://x.com/vuejs" target="_blank" rel="noopener">@vuejs</a> <a href="https://x.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
X account for latest news in the Vue world. X account for latest news in the Vue world.
@@ -88,8 +117,10 @@ const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
</template> </template>
<template #heading>Support Vue</template> <template #heading>Support Vue</template>
As an independent project, Vue relies on community backing for its sustainability. You can help As an independent project, Vue relies on community backing for its
us by sustainability. You can help us by
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>. <a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener"
>becoming a sponsor</a
>.
</WelcomeItem> </WelcomeItem>
</template> </template>

View File

@@ -1,5 +1,10 @@
<template> <template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"> <svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
>
<path <path
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z" d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
/> />

View File

@@ -1,5 +1,10 @@
<template> <template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor"> <svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="17"
fill="currentColor"
>
<path <path
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z" d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
/> />

View File

@@ -1,5 +1,10 @@
<template> <template>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor"> <svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="20"
fill="currentColor"
>
<path <path
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z" d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
/> />

View File

@@ -1,5 +1,10 @@
<template> <template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"> <svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
>
<path <path
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z" d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
/> />

13
frontend/src/main.ts Normal file
View File

@@ -0,0 +1,13 @@
import './assets/main.css'
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import { createApp } from 'vue'
import App from './App.vue'
const vuetify = createVuetify({ components, directives })
createApp(App).use(vuetify).mount('#app')

958
package-lock.json generated Normal file
View File

@@ -0,0 +1,958 @@
{
"name": "rush-character-archive",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"json-editor-vue": "^0.18.1",
"vuetify": "^3.8.12"
}
},
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
"license": "Apache-2.0",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
}
},
"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",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
"integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/types": "^7.28.0"
},
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/types": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz",
"integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@codemirror/autocomplete": {
"version": "6.18.6",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz",
"integrity": "sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==",
"license": "MIT",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0"
}
},
"node_modules/@codemirror/commands": {
"version": "6.8.1",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz",
"integrity": "sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==",
"license": "MIT",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.4.0",
"@codemirror/view": "^6.27.0",
"@lezer/common": "^1.1.0"
}
},
"node_modules/@codemirror/lang-json": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz",
"integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==",
"license": "MIT",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@lezer/json": "^1.0.0"
}
},
"node_modules/@codemirror/language": {
"version": "6.11.2",
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.2.tgz",
"integrity": "sha512-p44TsNArL4IVXDTbapUmEkAlvWs2CFQbcfc0ymDsis1kH2wh0gcY96AS29c/vp2d0y2Tquk1EDSaawpzilUiAw==",
"license": "MIT",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.23.0",
"@lezer/common": "^1.1.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0",
"style-mod": "^4.0.0"
}
},
"node_modules/@codemirror/lint": {
"version": "6.8.5",
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.5.tgz",
"integrity": "sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==",
"license": "MIT",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.35.0",
"crelt": "^1.0.5"
}
},
"node_modules/@codemirror/search": {
"version": "6.5.11",
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz",
"integrity": "sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==",
"license": "MIT",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"crelt": "^1.0.5"
}
},
"node_modules/@codemirror/state": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz",
"integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==",
"license": "MIT",
"dependencies": {
"@marijn/find-cluster-break": "^1.0.0"
}
},
"node_modules/@codemirror/view": {
"version": "6.38.0",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.0.tgz",
"integrity": "sha512-yvSchUwHOdupXkd7xJ0ob36jdsSR/I+/C+VbY0ffBiL5NiSTEBDfB1ZGWbbIlDd5xgdUkody+lukAdOxYrOBeg==",
"license": "MIT",
"dependencies": {
"@codemirror/state": "^6.5.0",
"crelt": "^1.0.6",
"style-mod": "^4.1.0",
"w3c-keyname": "^2.2.4"
}
},
"node_modules/@fortawesome/fontawesome-common-types": {
"version": "6.7.2",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
"integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/free-regular-svg-icons": {
"version": "6.7.2",
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.7.2.tgz",
"integrity": "sha512-7Z/ur0gvCMW8G93dXIQOkQqHo2M5HLhYrRVC0//fakJXxcF1VmMPsxnG6Ee8qEylA8b8Q3peQXWMNZ62lYF28g==",
"license": "(CC-BY-4.0 AND MIT)",
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.7.2"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/free-solid-svg-icons": {
"version": "6.7.2",
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz",
"integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==",
"license": "(CC-BY-4.0 AND MIT)",
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.7.2"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.12",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
"integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
"integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.29",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
"integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@jsep-plugin/assignment": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz",
"integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==",
"license": "MIT",
"engines": {
"node": ">= 10.16.0"
},
"peerDependencies": {
"jsep": "^0.4.0||^1.0.0"
}
},
"node_modules/@jsep-plugin/regex": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz",
"integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==",
"license": "MIT",
"engines": {
"node": ">= 10.16.0"
},
"peerDependencies": {
"jsep": "^0.4.0||^1.0.0"
}
},
"node_modules/@jsonquerylang/jsonquery": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@jsonquerylang/jsonquery/-/jsonquery-5.0.4.tgz",
"integrity": "sha512-QdgVkapeGRxUqOOJuh2svDutejKaCizhupEmO4ZKSsaLolD7w5QhgrjmBNuS1wMCM5TyNKifK4i1wBDfNzO9xQ==",
"license": "ISC",
"bin": {
"jsonquery": "bin/cli.js"
}
},
"node_modules/@lezer/common": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
"integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==",
"license": "MIT"
},
"node_modules/@lezer/highlight": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz",
"integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
"license": "MIT",
"dependencies": {
"@lezer/common": "^1.0.0"
}
},
"node_modules/@lezer/json": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz",
"integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==",
"license": "MIT",
"dependencies": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"node_modules/@lezer/lr": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz",
"integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
"license": "MIT",
"dependencies": {
"@lezer/common": "^1.0.0"
}
},
"node_modules/@marijn/find-cluster-break": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
"license": "MIT"
},
"node_modules/@replit/codemirror-indentation-markers": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/@replit/codemirror-indentation-markers/-/codemirror-indentation-markers-6.5.3.tgz",
"integrity": "sha512-hL5Sfvw3C1vgg7GolLe/uxX5T3tmgOA3ZzqlMv47zjU1ON51pzNWiVbS22oh6crYhtVhv8b3gdXwoYp++2ilHw==",
"license": "MIT",
"peerDependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0"
}
},
"node_modules/@sphinxxxx/color-conversion": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@sphinxxxx/color-conversion/-/color-conversion-2.2.2.tgz",
"integrity": "sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw==",
"license": "ISC"
},
"node_modules/@sveltejs/acorn-typescript": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz",
"integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==",
"license": "MIT",
"peerDependencies": {
"acorn": "^8.9.0"
}
},
"node_modules/@types/estree": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"license": "MIT"
},
"node_modules/@vue/compiler-core": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.17.tgz",
"integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/parser": "^7.27.5",
"@vue/shared": "3.5.17",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz",
"integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/compiler-core": "3.5.17",
"@vue/shared": "3.5.17"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz",
"integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/parser": "^7.27.5",
"@vue/compiler-core": "3.5.17",
"@vue/compiler-dom": "3.5.17",
"@vue/compiler-ssr": "3.5.17",
"@vue/shared": "3.5.17",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.17",
"postcss": "^8.5.6",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz",
"integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.17",
"@vue/shared": "3.5.17"
}
},
"node_modules/@vue/reactivity": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.17.tgz",
"integrity": "sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/shared": "3.5.17"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.17.tgz",
"integrity": "sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/reactivity": "3.5.17",
"@vue/shared": "3.5.17"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.17.tgz",
"integrity": "sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/reactivity": "3.5.17",
"@vue/runtime-core": "3.5.17",
"@vue/shared": "3.5.17",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.17.tgz",
"integrity": "sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/compiler-ssr": "3.5.17",
"@vue/shared": "3.5.17"
},
"peerDependencies": {
"vue": "3.5.17"
}
},
"node_modules/@vue/shared": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.17.tgz",
"integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==",
"license": "MIT",
"peer": true
},
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/aria-query": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
"integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/axobject-query": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/codemirror-wrapped-line-indent": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/codemirror-wrapped-line-indent/-/codemirror-wrapped-line-indent-1.0.9.tgz",
"integrity": "sha512-oc976hHLt35u6Ojbhub+IWOxEpapZSqYieLEdGhsgFZ4rtYQtdb5KjxzgjCCyVe3t0yk+a6hmaIOEsjU/tZRxQ==",
"license": "MIT",
"peerDependencies": {
"@codemirror/language": "^6.9.0",
"@codemirror/state": "^6.2.1",
"@codemirror/view": "^6.17.1"
}
},
"node_modules/crelt": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
"license": "MIT"
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"license": "MIT",
"peer": true
},
"node_modules/diff-sequences": {
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
"integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
"license": "MIT",
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"license": "BSD-2-Clause",
"peer": true,
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/esm-env": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
"license": "MIT"
},
"node_modules/esrap": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.0.tgz",
"integrity": "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
}
},
"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",
"peer": true
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
"node_modules/fast-uri": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
"integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "BSD-3-Clause"
},
"node_modules/immutable-json-patch": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/immutable-json-patch/-/immutable-json-patch-6.0.1.tgz",
"integrity": "sha512-BHL/cXMjwFZlTOffiWNdY8ZTvNyYLrutCnWxrcKPHr5FqpAb6vsO6WWSPnVSys3+DruFN6lhHJJPHi8uELQL5g==",
"license": "ISC"
},
"node_modules/is-reference": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
"integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.6"
}
},
"node_modules/jmespath": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz",
"integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==",
"license": "Apache-2.0",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/jsep": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz",
"integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==",
"license": "MIT",
"engines": {
"node": ">= 10.16.0"
}
},
"node_modules/json-editor-vue": {
"version": "0.18.1",
"resolved": "https://registry.npmjs.org/json-editor-vue/-/json-editor-vue-0.18.1.tgz",
"integrity": "sha512-SQCtNngo/ScFjXC7KUOqLOeeLgvl+xwWbxfNelqIOHC6uLilQl7AlWzNJyrDqo+RWnc53nT0OngXki5uTx9SJg==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"vanilla-jsoneditor": "^3.0.0",
"vue-demi": "^0.14.10"
},
"peerDependencies": {
"@vue/composition-api": ">=1",
"vue": "2||3"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"license": "MIT"
},
"node_modules/json-source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/json-source-map/-/json-source-map-0.6.1.tgz",
"integrity": "sha512-1QoztHPsMQqhDq0hlXY5ZqcEdUzxQEIxgFkKl4WUp2pgShObl+9ovi4kRh2TfvAfxAoHOJ9vIMEqk3k4iex7tg==",
"license": "MIT"
},
"node_modules/jsonpath-plus": {
"version": "10.3.0",
"resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz",
"integrity": "sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==",
"license": "MIT",
"dependencies": {
"@jsep-plugin/assignment": "^1.3.0",
"@jsep-plugin/regex": "^1.0.4",
"jsep": "^1.4.0"
},
"bin": {
"jsonpath": "bin/jsonpath-cli.js",
"jsonpath-plus": "bin/jsonpath-cli.js"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/jsonrepair": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.12.0.tgz",
"integrity": "sha512-SWfjz8SuQ0wZjwsxtSJ3Zy8vvLg6aO/kxcp9TWNPGwJKgTZVfhNEQBMk/vPOpYCDFWRxD6QWuI6IHR1t615f0w==",
"license": "ISC",
"bin": {
"jsonrepair": "bin/cli.js"
}
},
"node_modules/locate-character": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
"license": "MIT"
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
"license": "MIT"
},
"node_modules/magic-string": {
"version": "0.30.17",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
"integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"node_modules/memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
"license": "MIT"
},
"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",
"peer": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/natural-compare-lite": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
"license": "MIT"
},
"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",
"peer": true
},
"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",
"peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"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",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/style-mod": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
"license": "MIT"
},
"node_modules/svelte": {
"version": "5.35.2",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.35.2.tgz",
"integrity": "sha512-uW/rRXYrhZ7Dh4UQNZ0t+oVGL1dEM+95GavCO8afAk1IY2cPq9BcZv9C3um5aLIya2y8lIeLPxLII9ASGg9Dzw==",
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.3.0",
"@jridgewell/sourcemap-codec": "^1.5.0",
"@sveltejs/acorn-typescript": "^1.0.5",
"@types/estree": "^1.0.5",
"acorn": "^8.12.1",
"aria-query": "^5.3.1",
"axobject-query": "^4.1.0",
"clsx": "^2.1.1",
"esm-env": "^1.2.1",
"esrap": "^2.1.0",
"is-reference": "^3.0.3",
"locate-character": "^3.0.0",
"magic-string": "^0.30.11",
"zimmerframe": "^1.1.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/vanilla-jsoneditor": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/vanilla-jsoneditor/-/vanilla-jsoneditor-3.6.1.tgz",
"integrity": "sha512-P/rDsaj8c4IKWCPmpxcy13TVANzjAR0qSil78HJEw+aVCghJK6cySzJm/XwJ8Q/vyvfUg1aAq8hJWF/Uui6T0w==",
"license": "ISC",
"dependencies": {
"@codemirror/autocomplete": "^6.18.1",
"@codemirror/commands": "^6.7.1",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/language": "^6.10.3",
"@codemirror/lint": "^6.8.2",
"@codemirror/search": "^6.5.6",
"@codemirror/state": "^6.4.1",
"@codemirror/view": "^6.34.1",
"@fortawesome/free-regular-svg-icons": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@jsonquerylang/jsonquery": "^3.1.1 || ^4.0.0 || ^5.0.0",
"@lezer/highlight": "^1.2.1",
"@replit/codemirror-indentation-markers": "^6.5.3",
"ajv": "^8.17.1",
"codemirror-wrapped-line-indent": "^1.0.8",
"diff-sequences": "^29.6.3",
"immutable-json-patch": "^6.0.1",
"jmespath": "^0.16.0",
"json-source-map": "^0.6.1",
"jsonpath-plus": "^10.3.0",
"jsonrepair": "^3.0.0",
"lodash-es": "^4.17.21",
"memoize-one": "^6.0.0",
"natural-compare-lite": "^1.4.0",
"svelte": "^5.0.0",
"vanilla-picker": "^2.12.3"
}
},
"node_modules/vanilla-picker": {
"version": "2.12.3",
"resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.12.3.tgz",
"integrity": "sha512-qVkT1E7yMbUsB2mmJNFmaXMWE2hF8ffqzMMwe9zdAikd8u2VfnsVY2HQcOUi2F38bgbxzlJBEdS1UUhOXdF9GQ==",
"license": "ISC",
"dependencies": {
"@sphinxxxx/color-conversion": "^2.2.2"
}
},
"node_modules/vue": {
"version": "3.5.17",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.17.tgz",
"integrity": "sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.17",
"@vue/compiler-sfc": "3.5.17",
"@vue/runtime-dom": "3.5.17",
"@vue/server-renderer": "3.5.17",
"@vue/shared": "3.5.17"
},
"peerDependencies": {
"typescript": "*"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/vuetify": {
"version": "3.8.12",
"resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.8.12.tgz",
"integrity": "sha512-XRX/yRel/V5rlas12ovujVCo8RDb/NwICyef/DVYzybqbYz/UGHZd23sN5q1zw0h9jUN8httXI6ytWN7OFugmA==",
"license": "MIT",
"engines": {
"node": "^12.20 || >=14.13"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/johnleider"
},
"peerDependencies": {
"typescript": ">=4.7",
"vite-plugin-vuetify": ">=2.1.0",
"vue": "^3.5.0",
"webpack-plugin-vuetify": ">=3.1.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
},
"vite-plugin-vuetify": {
"optional": true
},
"webpack-plugin-vuetify": {
"optional": true
}
}
},
"node_modules/w3c-keyname": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
"license": "MIT"
},
"node_modules/zimmerframe": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz",
"integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==",
"license": "MIT"
}
}
}

6
package.json Normal file
View File

@@ -0,0 +1,6 @@
{
"dependencies": {
"json-editor-vue": "^0.18.1",
"vuetify": "^3.8.12"
}
}

33
proto/character.proto Normal file
View File

@@ -0,0 +1,33 @@
syntax = "proto3";
service CharacterManager {
rpc createCharacter(CreateCharacterRequest) returns (Character);
rpc getCharacter(GetCharacterRequest) returns (Character);
rpc listCharacters(ListCharacterRequest) returns (ListCharacterResponse);
}
message Empty {}
message Character {
string PlayerName = 1;
string CharacterName = 2;
repeated string CharacterAlias = 3;
string Version = 4;
string SourceTable = 5;
string Json = 6;
}
message CreateCharacterRequest {
Character characterData = 1;
}
message GetCharacterRequest {}
message ListCharacterRequest {
string PlayerName = 1;
string CharacterName = 2;
}
message ListCharacterResponse {
repeated Character characters = 1;
}

1372
proto/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

23
proto/package.json Normal file
View File

@@ -0,0 +1,23 @@
{
"name": "proto",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"build_server": "npx protoc --ts_out=server_grpc1:./ --proto_path ./ ./*.proto",
"build_client": "npx protoc --ts_out:./ --proto_path ./ ./*.proto"
},
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@types/google-protobuf": "^3.15.12",
"grpc_tools_node_protoc_ts": "^5.3.3",
"grpc-tools": "^1.13.0",
"ts-node": "^10.9.2",
"typescript": "^5.8.3"
},
"dependencies": {
"@grpc/grpc-js": "^1.13.4",
"@protobuf-ts/plugin": "^2.11.0"
}
}

View File

@@ -1,17 +0,0 @@
FROM node:22.16
WORKDIR /srv/rush-character-archive
COPY package.json .
RUN npm install
RUN npm i -g serve
COPY . .
RUN npm run build
EXPOSE 8080
CMD ["serve", "-s", "dist"]

View File

@@ -1,85 +0,0 @@
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<header>
<img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />
<div class="wrapper">
<HelloWorld msg="You did it!" />
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
</nav>
</div>
</header>
<RouterView />
</template>
<style scoped>
header {
line-height: 1.5;
max-height: 100vh;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
nav {
width: 100%;
font-size: 12px;
text-align: center;
margin-top: 2rem;
}
nav a.router-link-exact-active {
color: var(--color-text);
}
nav a.router-link-exact-active:hover {
background-color: transparent;
}
nav a {
display: inline-block;
padding: 0 1rem;
border-left: 1px solid var(--color-border);
}
nav a:first-of-type {
border: 0;
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
nav {
text-align: left;
margin-left: -1rem;
font-size: 1rem;
padding: 1rem 0;
margin-top: 1rem;
}
}
</style>

View File

@@ -1,11 +0,0 @@
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')

View File

@@ -1,23 +0,0 @@
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView,
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/AboutView.vue'),
},
],
})
export default router

View File

@@ -1,15 +0,0 @@
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<style>
@media (min-width: 1024px) {
.about {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>

View File

@@ -1,9 +0,0 @@
<script setup lang="ts">
import TheWelcome from '../components/TheWelcome.vue'
</script>
<template>
<main>
<TheWelcome />
</main>
</template>

View File

@@ -1,33 +0,0 @@
module.exports = {
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"overrides": [
{
"env": {
"node": true
},
"files": [
".eslintrc.{js,cjs}"
],
"parserOptions": {
"sourceType": "script"
}
}
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
}
}

3
vault/.prettierignore Normal file
View File

@@ -0,0 +1,3 @@
# Ignore artifacts:
build
coverage

View File

@@ -1,13 +1,18 @@
FROM node:22.16 FROM node:22.16
WORKDIR /srv/proto
COPY proto/ .
WORKDIR /srv/vault WORKDIR /srv/vault
COPY package.json . COPY vault/package.json .
RUN npm install RUN npm install
COPY . . COPY vault/ .
RUN npm run build_protos
RUN npm run build RUN npm run build
EXPOSE 8080 EXPOSE 8080

17
vault/eslint.config.mjs Normal file
View File

@@ -0,0 +1,17 @@
import js from '@eslint/js'
import globals from 'globals'
import tseslint from 'typescript-eslint'
import { defineConfig } from 'eslint/config'
export default defineConfig([
{
files: ['**/*.{js,mjs,cjs,ts,mts,cts}'],
plugins: { js },
extends: ['js/recommended'],
},
{
files: ['**/*.{js,mjs,cjs,ts,mts,cts}'],
languageOptions: { globals: globals.node },
},
tseslint.configs.recommended,
])

6549
vault/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,44 +1,40 @@
{ {
"name": "vault", "name": "vault",
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "backend for rush cahracter archive",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "build_protos": "mkdir -p src/proto && npx protoc -I=../proto/ --ts_out=server_grpc1:./src/proto --proto_path ../proto ../proto/*.proto && cp ../proto/*.proto ./src/proto",
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", "build": "tsc",
"format": "prettier --write src/", "start": "tsc && node dist/app.js",
"dev": "npx ts-node-dev src/app.ts", "dev": "npx ts-node-dev src/app.ts",
"build": "webpack && cp package.json ./dist/package.json" "test": "echo \"Error: no test specified\" && exit 1",
"format": "npx prettier . --write",
"lint": "npx eslint . --ext .ts"
}, },
"keywords": [], "author": "iamBadgers",
"author": "",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@types/express": "^4.17.21", "@eslint/js": "^9.28.0",
"@types/sequelize": "^4.28.20", "@protobuf-ts/plugin": "^2.11.0",
"@types/sqlite3": "^3.1.11", "@types/express": "^5.0.3",
"@typescript-eslint/eslint-plugin": "^7.1.1", "@types/node": "^22.15.30",
"@typescript-eslint/parser": "^7.1.1", "eslint": "^9.28.0",
"crossenv": "^0.0.2-security", "globals": "^16.2.0",
"eslint": "^8.57.0", "prettier": "3.5.3",
"node-polyfill-webpack-plugin": "^4.0.0", "ts-node": "^10.9.2",
"prettier": "^3.2.5", "ts-node-dev": "^2.0.0",
"ts-loader": "^9.5.1", "typescript": "^5.8.3",
"typescript": "^5.4.5", "typescript-eslint": "^8.33.1"
"webpack-cli": "^5.1.4"
}, },
"dependencies": { "dependencies": {
"@types/body-parser": "^1.19.5", "@grpc/grpc-js": "^1.13.4",
"asty-astq": "^1.14.0", "@grpc/proto-loader": "^0.7.15",
"body-parser": "^1.20.2", "@grpc/reflection": "^1.0.4",
"express": "^4.21.2", "@protobuf-ts/protoc": "^2.11.0",
"memcached": "^2.2.2", "commander": "^14.0.0",
"net": "^1.0.2", "express": "^5.1.0",
"pg": "^8.16.0", "google-protobuf": "^3.21.4",
"pg-hstore": "^2.3.4", "mongodb": "^6.17.0"
"sequelize": "^6.37.1",
"sqlite3": "^5.1.7",
"tokenizr": "^1.7.0",
"webpack-node-externals": "^3.0.0"
} }
} }

View File

@@ -1,16 +1,26 @@
import express from 'express' import { Server, ServerCredentials } from '@grpc/grpc-js'
import { buildClient } from './db' import { MongoClient } from 'mongodb'
const app = express() import { CharacterService } from './character_service'
import { DatabaseService } from './database'
import { Flags } from './flags'
const dbClient = buildClient('db', 'rushvault', 'rushvault', 'rushvault') const flags = new Flags()
app.get('/api/person', async (req, res) => { const port = flags.getPort()
res.status(200).send('potato!')
}) const address = `0.0.0.0:${port}`
app.listen(8080, async () => { const databaseService = new DatabaseService(
console.log('starting on 8080') flags.getMongoDbAddress(),
dbClient.connect() flags.getMongoDbName(),
console.log(await dbClient.query('SELECT NOW()')) )
const characterService = new CharacterService(databaseService)
const app = new Server()
characterService.addToServer(app)
app.bindAsync(address, ServerCredentials.createInsecure(), () => {
console.log(`Starting server at ${address}`)
}) })

View File

@@ -0,0 +1,87 @@
import { Server, ServerUnaryCall, sendUnaryData, StatusBuilder } from '@grpc/grpc-js'
import { ReflectionService } from '@grpc/reflection'
import { loadSync } from '@grpc/proto-loader'
import { MongoClient, Collection, Db } from 'mongodb'
import { DatabaseService } from './database'
import {
Character,
GetCharacterRequest,
CreateCharacterRequest,
ListCharacterRequest,
ListCharacterResponse,
} from './proto/character'
import {
characterManagerDefinition,
ICharacterManager,
} from './proto/character.grpc-server'
const testCharacter: Character = {
playerName: 'test player',
characterName: 'test character',
characterAlias: ['test alias'],
version: 'test version',
sourceTable: 'source table',
json: 'test json',
}
export class CharacterService {
reflectionService: ReflectionService
characterManager: ICharacterManager
databaseService: DatabaseService
constructor(databaseService: DatabaseService) {
this.reflectionService = new ReflectionService(
loadSync('./src/proto/character.proto'),
)
this.characterManager = {
createCharacter: this.createCharacterCall.bind(this),
getCharacter: this.getCharacterCall.bind(this),
listCharacters: this.listCharactersCall.bind(this),
}
this.databaseService = databaseService
}
addToServer(server: Server) {
server.addService(characterManagerDefinition, this.characterManager)
this.reflectionService.addToServer(server)
}
async createCharacterCall(
call: ServerUnaryCall<CreateCharacterRequest, Character>,
callback: sendUnaryData<Character>,
) {
let newCharacter = await this.databaseService.insertCharacter(
call.request.characterData,
)
console.log(newCharacter)
callback(null, newCharacter)
}
getCharacterCall(
call: ServerUnaryCall<GetCharacterRequest, Character>,
callback: sendUnaryData<Character>,
) {
callback(null, testCharacter)
}
async listCharactersCall(
call: ServerUnaryCall<ListCharacterRequest, ListCharacterResponse>,
callback: sendUnaryData<ListCharacterResponse>,
) {
let characters = await this.databaseService.listCharacters(
call.request.playerName,
call.request.characterName,
)
callback(null, {
characters,
})
}
}

71
vault/src/database.ts Normal file
View File

@@ -0,0 +1,71 @@
import { MongoClient, Db, Collection } from 'mongodb'
import { Character } from './proto/character'
export class DatabaseService {
private readonly client: MongoClient
private readonly db: Db
private readonly characterCollection: Collection
constructor(databaseAddress: string, databaseName: string) {
this.client = new MongoClient(databaseAddress)
this.db = this.client.db(databaseName)
this.characterCollection = this.db.collection('characters')
}
insertCharacter(character: Character): Promise<Character> {
return this.characterCollection
.insertOne(character)
.then((insertResult) => {
console.log("Adding new character record:", insertResult)
return this.characterCollection.findOne({
_id: insertResult.insertedId,
})
})
.then(record => {
const character = recordToCharacter(record)
console.log(`New character result: \n _id: ${record._id}`, character)
return character
})
}
fetchCharactersForPlayer(playerName: string): Promise<Array<Character>> {
return this.characterCollection
.find({ playerName: playerName })
.toArray()
.then((results) => results.map(recordToCharacter))
}
fetchCharactersForCharacterName(playerName: string): Array<Character> {
return []
}
listCharacters(
playerName: string,
characterName: string,
): Promise<Array<Character>> {
let query = {}
if (playerName != '') query['playerName'] = playerName
if (characterName != '')
query['$or'] = [
{ characterName: characterName },
{ characterAlias: characterName},
]
return this.characterCollection
.find(query)
.toArray()
.then((results) => results.map(recordToCharacter))
}
}
function recordToCharacter(record): Character {
return {
playerName: record.playerName,
characterName: record.characterName,
characterAlias: record.characterAlias,
version: record.version,
sourceTable: record.sourceTable,
json: record.json,
}
}

View File

@@ -1,24 +0,0 @@
import { Client } from 'pg'
export function buildClient(
host: string,
user: string,
password: string,
database: string,
) {
return new Client({ user, password, host, database })
}
// export class VaultDbClient {
// client: Client
// constructor(
// host: string,
// port: number,
// user: string,
// password: string,
// database: string,
// ) {
// this.client = new Client({ user, password, host, port, database })
// }
// }

32
vault/src/flags.ts Normal file
View File

@@ -0,0 +1,32 @@
import { Command } from 'commander'
export class Flags {
private readonly program = new Command()
.option('-p, --port <number>', 'server port number', '8080')
.option(
'--mongoPath <string>',
'mongo db path',
'mongodb://rushvault:rushvault@mongo:27017/',
)
.option(
'--mongoDb <string>',
'name of the databse to store collections',
'rush-vault',
)
constructor() {
this.program.parse()
}
getPort(): number {
return this.program.opts().port
}
getMongoDbAddress(): string {
return this.program.opts().mongoPath
}
getMongoDbName(): string {
return this.program.opts().mongoDb
}
}

View File

@@ -1,30 +0,0 @@
const path = require('path');
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")
const nodeExternals = require('webpack-node-externals');
module.exports = {
mode: 'production',
entry: './src/app.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
}, node: {
__dirname: false
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'app.js',
path: path.resolve(__dirname, './dist'),
},
plugins: [
new NodePolyfillPlugin(),
],
externals: [nodeExternals()],
};