feat: initial schemas-app implementation

- Add Nuxt 4 application with Vuetify UI framework
- Implement GraphQL schema registry management interface
- Add Apollo Client integration with Auth0 authentication
- Create organization and API key management
- Add schema and ref browsing capabilities
- Implement organization switcher for multi-org users
- Add delete functionality for organizations and API keys
- Create Kubernetes deployment descriptors
- Add Docker configuration with nginx

Features:
- Dashboard with organization overview
- Schema browsing by ref with supergraph viewing
- Ref management with schema details
- Settings page for organizations and API keys
- User list per organization with provider icons
- Admin-only organization creation
- Delete confirmations with warnings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-22 16:42:35 +01:00
commit 072e1b10f1
41 changed files with 25557 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
import { config } from '@vue/test-utils'
import { vi } from 'vitest'
import * as Vue from 'vue'
// Mock localStorage
const localStorageMock = {
getItem: vi.fn(),
setItem: vi.fn(),
removeItem: vi.fn(),
clear: vi.fn(),
key: vi.fn(),
length: 0,
}
global.localStorage = localStorageMock as unknown as Storage
// Make Vue composables globally available
global.ref = Vue.ref
global.computed = Vue.computed
global.reactive = Vue.reactive
global.watch = Vue.watch
global.watchEffect = Vue.watchEffect
global.defineModel = Vue.defineModel
global.onMounted = Vue.onMounted
global.onUnmounted = Vue.onUnmounted
global.nextTick = Vue.nextTick
// Mock Nuxt composables
global.useRuntimeConfig = vi.fn(() => ({
public: {},
}))
global.useNuxtApp = vi.fn(() => ({
$apollo: {},
}))
global.navigateTo = vi.fn()
global.definePageMeta = vi.fn()
// Mock Vuetify components globally for tests
config.global.stubs = {
VAlert: {
name: 'v-alert',
template: '<div class="v-alert" :type="type" :variant="variant" :color="color"><slot /></div>',
props: ['color', 'type', 'variant'],
},
VTextField: {
template: '<div class="v-text-field"><input :readonly="readonly || disabled" :disabled="disabled" :error="error" :value="modelValue" @input="$emit(\'update:model-value\', $event.target.value)" @blur="$emit(\'blur\')" /></div>',
props: ['modelValue', 'readonly', 'disabled', 'active', 'focused', 'variant', 'error', 'errorMessages', 'label'],
emits: ['update:model-value', 'blur'],
},
VBtn: {
name: 'v-btn',
template: '<button :disabled="disabled" :color="color" :data-testid="$attrs[\'data-testid\']" @click="$emit(\'click\')"><slot /></button>',
props: ['disabled', 'variant', 'icon', 'color', 'flat', 'depressed', 'xLarge'],
emits: ['click'],
},
VDialog: {
name: 'v-dialog',
template: '<div class="v-dialog"><slot name="activator" /><div class="v-dialog__content"><slot /></div></div>',
props: ['modelValue', 'width', 'maxWidth', 'persistent'],
},
VForm: {
name: 'v-form',
template: '<form @submit="$emit(\'submit\', $event)"><slot /></form>',
emits: ['submit'],
},
VCard: {
name: 'v-card',
template: '<div class="v-card" :variant="variant" :rounded="rounded" :loading="loading"><div v-if="title" class="v-card-title">{{ title }}</div><slot /></div>',
props: ['variant', 'rounded', 'loading', 'title'],
},
VCardTitle: {
template: '<div class="v-card-title"><slot /></div>',
},
VCardText: {
name: 'v-card-text',
template: '<div class="v-card-text"><slot /></div>',
},
VCardActions: {
name: 'v-card-actions',
template: '<div class="v-card-actions"><slot /></div>',
},
VSpacer: {
name: 'v-spacer',
template: '<div class="v-spacer"></div>',
},
VIcon: {
name: 'v-icon',
template: '<i class="v-icon" :class="icon" @click="$emit(\'click\')"></i>',
props: ['icon', 'large'],
emits: ['click'],
},
}