im done for rn gn
This commit is contained in:
commit
79922f09a1
16 changed files with 2283 additions and 0 deletions
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Nuxt dev/build outputs
|
||||
.output
|
||||
.data
|
||||
.nuxt
|
||||
.nitro
|
||||
.cache
|
||||
dist
|
||||
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.fleet
|
||||
.idea
|
||||
|
||||
# Local env files
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
75
README.md
Normal file
75
README.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
# Nuxt Minimal Starter
|
||||
|
||||
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure to install dependencies:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm install
|
||||
|
||||
# pnpm
|
||||
pnpm install
|
||||
|
||||
# yarn
|
||||
yarn install
|
||||
|
||||
# bun
|
||||
bun install
|
||||
```
|
||||
|
||||
## Development Server
|
||||
|
||||
Start the development server on `http://localhost:3000`:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
# pnpm
|
||||
pnpm dev
|
||||
|
||||
# yarn
|
||||
yarn dev
|
||||
|
||||
# bun
|
||||
bun run dev
|
||||
```
|
||||
|
||||
## Production
|
||||
|
||||
Build the application for production:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run build
|
||||
|
||||
# pnpm
|
||||
pnpm build
|
||||
|
||||
# yarn
|
||||
yarn build
|
||||
|
||||
# bun
|
||||
bun run build
|
||||
```
|
||||
|
||||
Locally preview production build:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run preview
|
||||
|
||||
# pnpm
|
||||
pnpm preview
|
||||
|
||||
# yarn
|
||||
yarn preview
|
||||
|
||||
# bun
|
||||
bun run preview
|
||||
```
|
||||
|
||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||
12
app/app.vue
Normal file
12
app/app.vue
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<script setup>
|
||||
useHead({
|
||||
link: [
|
||||
{ rel: 'stylesheet', href: '/css/main.css' }
|
||||
]
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="app-viewport">
|
||||
<NuxtPage />
|
||||
</div>
|
||||
</template>
|
||||
37
app/components/header.vue
Normal file
37
app/components/header.vue
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<script setup>
|
||||
defineProps({
|
||||
userProfile: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
activeTab: {
|
||||
type: String,
|
||||
default: 'welcome'
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['logout', 'navigate'])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<aside class="settings-sidebar">
|
||||
<div class="sidebar-header archivo-black">
|
||||
MOD PORTAL
|
||||
</div>
|
||||
|
||||
<div v-if="userProfile" class="user-badge">
|
||||
<span class="user-name">{{ userProfile.username || userProfile.firstName }}</span>
|
||||
<span class="user-email">{{ userProfile.email }}</span>
|
||||
</div>
|
||||
|
||||
<nav class="sidebar-menu">
|
||||
<button type="button" class="nav-item" :class="{ 'active-nav': activeTab === 'welcome' }"
|
||||
@click="emit('navigate', '/')">
|
||||
<span>Welcome</span>
|
||||
</button>
|
||||
<button type="button" class="nav-item logout-btn" @click="emit('logout')">
|
||||
<span>Sign Out</span>
|
||||
</button>
|
||||
</nav>
|
||||
</aside>
|
||||
</template>
|
||||
85
app/composables/useKeycloak.js
Normal file
85
app/composables/useKeycloak.js
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import { ref } from 'vue'
|
||||
|
||||
const keycloakInstance = ref(null)
|
||||
const isAuthenticated = ref(false)
|
||||
const userProfile = ref(null)
|
||||
const isInitialized = ref(false)
|
||||
|
||||
export const useKeycloak = () => {
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
const initKeycloak = async () => {
|
||||
if (isInitialized.value && keycloakInstance.value?.authenticated) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!import.meta.client) return false
|
||||
|
||||
try {
|
||||
const Keycloak = (await import('keycloak-js')).default
|
||||
const keycloak = new Keycloak({
|
||||
url: config.public.keycloakUrl,
|
||||
realm: config.public.keycloakRealm,
|
||||
clientId: config.public.keycloakClientId
|
||||
})
|
||||
|
||||
keycloakInstance.value = keycloak
|
||||
|
||||
const auth = await keycloak.init({
|
||||
onLoad: 'check-sso',
|
||||
pkceMethod: 'S256',
|
||||
responseMode: 'query',
|
||||
checkLoginIframe: false
|
||||
})
|
||||
|
||||
const loggedIn = Boolean(auth || keycloak.authenticated)
|
||||
isAuthenticated.value = loggedIn
|
||||
isInitialized.value = true
|
||||
|
||||
if (loggedIn) {
|
||||
try {
|
||||
userProfile.value = await keycloak.loadUserProfile()
|
||||
} catch (e) {
|
||||
console.warn('Could not load user profile:', e)
|
||||
}
|
||||
|
||||
if (window.location.search.includes('code=')) {
|
||||
window.history.replaceState({}, document.title, window.location.pathname)
|
||||
}
|
||||
}
|
||||
|
||||
return loggedIn
|
||||
} catch (error) {
|
||||
console.error('Keycloak init failed:', error)
|
||||
isInitialized.value = true
|
||||
isAuthenticated.value = false
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const login = () => {
|
||||
if (keycloakInstance.value) {
|
||||
keycloakInstance.value.login({
|
||||
redirectUri: `${window.location.origin}/`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const logout = () => {
|
||||
if (keycloakInstance.value) {
|
||||
keycloakInstance.value.logout({
|
||||
redirectUri: `${window.location.origin}/oauth`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
keycloakInstance,
|
||||
isAuthenticated,
|
||||
userProfile,
|
||||
isInitialized,
|
||||
initKeycloak,
|
||||
login,
|
||||
logout
|
||||
}
|
||||
}
|
||||
85
app/pages/index.vue
Normal file
85
app/pages/index.vue
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<script setup>
|
||||
import { onMounted } from 'vue'
|
||||
|
||||
const { isAuthenticated, userProfile, isInitialized, initKeycloak, logout } = useKeycloak()
|
||||
|
||||
//stub
|
||||
const recentLogins = ref([
|
||||
{ user: 'admin_user', time: '2 mins ago', ip: '192.168.1.10' }
|
||||
])
|
||||
|
||||
onMounted(async () => {
|
||||
const auth = await initKeycloak()
|
||||
if (!auth) {
|
||||
navigateTo('/oauth')
|
||||
}
|
||||
})
|
||||
|
||||
const handleLogout = () => {
|
||||
logout()
|
||||
}
|
||||
|
||||
const handleNavigate = (path) => {
|
||||
navigateTo(path)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="!isInitialized" class="global-loader-wrapper">
|
||||
<div class="spinner lg"></div>
|
||||
<p style="color: #8b949e; margin-top: 1rem; font-size: 0.95rem;">
|
||||
Connecting to Keycloak...
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-else-if="isAuthenticated" class="settings-container">
|
||||
<Header
|
||||
:user-profile="userProfile"
|
||||
active-tab="welcome"
|
||||
@logout="handleLogout"
|
||||
@navigate="handleNavigate"
|
||||
/>
|
||||
|
||||
<main class="settings-main-content">
|
||||
<section class="settings-panel">
|
||||
<div class="panel-header archivo-black">
|
||||
<span>PORTAL OVERVIEW</span>
|
||||
</div>
|
||||
|
||||
<div class="panel-body grid-layout">
|
||||
<div class="welcome-left-col">
|
||||
<div class="image-wrapper">
|
||||
<img
|
||||
src="/welcome7.png"
|
||||
alt="Welcome to Mod Portal"
|
||||
class="welcome-image"
|
||||
/>
|
||||
</div>
|
||||
<h2 class="welcome-text">
|
||||
Welcome to the <em>new</em> mod portal!
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="logins-right-col">
|
||||
<div class="logins-card">
|
||||
<div class="logins-header archivo-black">
|
||||
RECENT LOGINS
|
||||
</div>
|
||||
<ul class="logins-list">
|
||||
<li v-for="(log, idx) in recentLogins" :key="idx" class="login-item">
|
||||
<div class="login-user">{{ log.user }}</div>
|
||||
<div class="login-details">
|
||||
<span>{{ log.ip }}</span> •
|
||||
<span class="login-time">{{ log.time }}</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
42
app/pages/oauth/index.vue
Normal file
42
app/pages/oauth/index.vue
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
const { isAuthenticated, isInitialized, initKeycloak, login } = useKeycloak()
|
||||
const isLoggingIn = ref(false)
|
||||
|
||||
onMounted(async () => {
|
||||
const auth = await initKeycloak()
|
||||
if (auth) {
|
||||
navigateTo('/')
|
||||
}
|
||||
})
|
||||
|
||||
const handleLogin = () => {
|
||||
isLoggingIn.value = true
|
||||
login()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="login-wrapper">
|
||||
<section class="settings-panel">
|
||||
<div class="panel-header archivo-black">
|
||||
MOD PORTAL
|
||||
</div>
|
||||
<div class="panel-body" style="text-align: center;">
|
||||
<p style="color: #8b949e; font-size: 0.95rem; margin-bottom: 1.5rem;">
|
||||
Hai there :3
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-login-action"
|
||||
:disabled="!isInitialized || isLoggingIn"
|
||||
@click="handleLogin"
|
||||
>
|
||||
<span v-if="isLoggingIn" class="spinner sm btn-spinner"></span>
|
||||
<span>{{ isLoggingIn ? 'Redirecting...' : 'Login with Keycloak' }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
13
nuxt.config.ts
Normal file
13
nuxt.config.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: '2025-07-15',
|
||||
devtools: { enabled: true },
|
||||
ssr: true,
|
||||
runtimeConfig: {
|
||||
public: {
|
||||
keycloakUrl: process.env.NUXT_PUBLIC_KEYCLOAK_URL,
|
||||
keycloakRealm: process.env.NUXT_PUBLIC_KEYCLOAK_REALM,
|
||||
keycloakClientId: process.env.NUXT_PUBLIC_KEYCLOAK_CLIENT_ID
|
||||
}
|
||||
}
|
||||
})
|
||||
19
package.json
Normal file
19
package.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "mod-portal-v2",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"keycloak-js": "^26.2.4",
|
||||
"nuxt": "^4.5.0",
|
||||
"vite-tsconfig-paths": "^6.1.1",
|
||||
"vue": "^3.5.40",
|
||||
"vue-router": "^5.2.0"
|
||||
}
|
||||
}
|
||||
320
public/css/main.css
Normal file
320
public/css/main.css
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
@import url('https://fonts.googleapis.com/css2?family=Archivo+Black&display=swap');
|
||||
|
||||
.archivo-black {
|
||||
font-family: "Archivo Black", sans-serif;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
width: 100vw;
|
||||
background-color: #1d1e1f;
|
||||
color: #c9d1d9;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.app-viewport {
|
||||
padding: 2rem 1rem;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
border: 3px solid rgba(255, 255, 255, 0.15);
|
||||
border-top-color: #00aeef;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.spinner.lg {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-width: 4px;
|
||||
}
|
||||
|
||||
.spinner.sm {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
.btn-spinner {
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
border-top-color: #ffffff;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.global-loader-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 50vh;
|
||||
}
|
||||
|
||||
button, .btn-login-action {
|
||||
padding: 0.6rem 1.2rem;
|
||||
background: #00aeef;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
transition: opacity 0.2s;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
button:hover, .btn-login-action:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
button:disabled, .btn-login-action:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-login-action {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.login-wrapper {
|
||||
max-width: 420px;
|
||||
margin: 4rem auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.settings-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.settings-sidebar {
|
||||
background-color: #1a1a1f;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
height: max-content;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
padding: 0.85rem 1rem;
|
||||
font-size: 1.1rem;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.user-badge {
|
||||
padding: 0.75rem 1rem;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
color: #ffffff;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.user-email {
|
||||
color: #8b949e;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.sidebar-menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.75rem 1rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
||||
color: #8b949e;
|
||||
text-align: left;
|
||||
font-size: 0.95rem;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
color: #f85149;
|
||||
}
|
||||
|
||||
.logout-btn:hover {
|
||||
background: rgba(248, 81, 73, 0.1);
|
||||
}
|
||||
|
||||
.active-nav {
|
||||
background: rgba(0, 174, 239, 0.1);
|
||||
border-left: 3px solid #00aeef;
|
||||
color: #00aeef;
|
||||
font-weight: 600;
|
||||
padding-left: calc(1rem - 3px);
|
||||
}
|
||||
|
||||
.settings-main-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.settings-panel {
|
||||
background-color: #1a1a1f;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.panel-header {
|
||||
padding: 0.85rem 1.25rem;
|
||||
font-size: 1.1rem;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.grid-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.welcome-left-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.image-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.welcome-image {
|
||||
max-width: 100%;
|
||||
max-height: 680px;
|
||||
object-fit: contain;
|
||||
border-radius: 8px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.welcome-text {
|
||||
font-size: 1.5rem;
|
||||
color: #ffffff;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.welcome-text em {
|
||||
color: #00aeef;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.logins-right-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.logins-card {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.logins-header {
|
||||
padding: 0.75rem 1rem;
|
||||
font-size: 0.9rem;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
color: #8b949e;
|
||||
}
|
||||
|
||||
.logins-list {
|
||||
list-style: none;
|
||||
overflow-y: auto;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.login-item {
|
||||
padding: 0.75rem 1rem;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.login-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.login-user {
|
||||
color: #ffffff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.login-details {
|
||||
color: #8b949e;
|
||||
font-size: 0.78rem;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.login-time {
|
||||
color: #00aeef;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.settings-container {
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.settings-sidebar {
|
||||
width: 280px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.grid-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 300px;
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
2
public/robots.txt
Normal file
2
public/robots.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
User-Agent: *
|
||||
Disallow:
|
||||
BIN
public/welcome5-1.png
Normal file
BIN
public/welcome5-1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
BIN
public/welcome7.png
Normal file
BIN
public/welcome7.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
// https://nuxt.com/docs/guide/concepts/typescript
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.server.json"
|
||||
},
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.shared.json"
|
||||
},
|
||||
{
|
||||
"path": "./.nuxt/tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in a new issue