Compare commits
22 Commits
8fe8f1e122
...
main
Author | SHA1 | Date | |
---|---|---|---|
e384635da5 | |||
145de73133 | |||
35806589f0 | |||
7445919003 | |||
3886c7bcbd | |||
075c246710 | |||
555feddabf | |||
83debac064 | |||
24c3463c86 | |||
6f861798ba | |||
7ab90d4af6 | |||
d5f24feb9e | |||
ad5ce609fc | |||
c458b564ce | |||
bcb9569b26 | |||
90be95afda | |||
c864664536 | |||
9762505a24 | |||
9adeaa4483 | |||
43ce135fc6 | |||
4e722e5e60 | |||
265bfac74a |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,6 +11,8 @@
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
.idea/codeStyles
|
||||
.idea/codeStyles/*
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
19
api.go
19
api.go
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/go-chi/render"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"net/http"
|
||||
"os"
|
||||
"somegit.dev/ALHP/ALHP.GO/ent"
|
||||
"somegit.dev/ALHP/ALHP.GO/ent/dbpackage"
|
||||
"somegit.dev/ALHP/ALHP.GO/ent/predicate"
|
||||
@@ -18,6 +19,8 @@ type StatsResponse struct {
|
||||
Skipped int `json:"skipped"`
|
||||
Latest int `json:"latest"`
|
||||
Queued int `json:"queued"`
|
||||
Building int `json:"building"`
|
||||
LastMirrorTimestamp *int64 `json:"last_mirror_timestamp,omitempty"`
|
||||
LTO *struct {
|
||||
Enabled int `json:"enabled"`
|
||||
Disabled int `json:"disabled"`
|
||||
@@ -71,6 +74,8 @@ func GetStats(w http.ResponseWriter, r *http.Request) {
|
||||
resp.Latest = c.Count
|
||||
case dbpackage.StatusQueued:
|
||||
resp.Queued = c.Count
|
||||
case dbpackage.StatusBuilding:
|
||||
resp.Building = c.Count
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +98,20 @@ func GetStats(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
if os.Getenv("ALHP_TIMESTAMP_PATH") != "" {
|
||||
tsFile, err := os.ReadFile(os.Getenv("ALHP_TIMESTAMP_PATH"))
|
||||
if err != nil {
|
||||
log.Warningf("error reading timestamp file: %v", err)
|
||||
} else {
|
||||
ts, err := strconv.ParseInt(string(tsFile), 10, 64)
|
||||
if err != nil {
|
||||
log.Warningf("error parsing timestamp file: %v", err)
|
||||
} else {
|
||||
resp.LastMirrorTimestamp = &ts
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, resp)
|
||||
}
|
||||
|
1
frontend/.gitignore
vendored
1
frontend/.gitignore
vendored
@@ -3,6 +3,7 @@ node_modules
|
||||
/dist
|
||||
|
||||
# local env files
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
|
8
frontend/components.d.ts
vendored
8
frontend/components.d.ts
vendored
@@ -9,10 +9,14 @@ export {}
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
BuildServerStats: typeof import('./src/components/BuildServerStats.vue')['default']
|
||||
BuildStats: typeof import('./src/components/BuildStats.vue')['default']
|
||||
BuildStats: typeof import('./src/components/MainNav/BuildStats.vue')['default']
|
||||
CurrentlyBuilding: typeof import('./src/components/CurrentlyBuilding.vue')['default']
|
||||
MainNav: typeof import('./src/components/MainNav.vue')['default']
|
||||
PackageFilters: typeof import('./src/components/Packages/PackageFilters.vue')['default']
|
||||
Packages: typeof import('./src/components/Packages.vue')['default']
|
||||
QueuedPackagesList: typeof import('./src/components/QueuedPackagesList.vue')['default']
|
||||
PackageTable: typeof import('./src/components/Packages/PackageTable.vue')['default']
|
||||
QueuedPackagesList: typeof import('./src/components/CurrentlyBuilding/QueuedPackagesList.vue')['default']
|
||||
StatItem: typeof import('./src/components/MainNav/BuildStats/StatItem.vue')['default']
|
||||
StatsListSection: typeof import('./src/components/MainNav/BuildStats/StatsListSection.vue')['default']
|
||||
}
|
||||
}
|
||||
|
13
frontend/env.d.ts
vendored
Normal file
13
frontend/env.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_BASE_URL: string
|
||||
readonly VITE_UPDATE_INTERVAL: number
|
||||
readonly VITE_LIMIT: number
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv
|
||||
}
|
||||
|
||||
declare module '@/*'
|
3
frontend/example.env
Normal file
3
frontend/example.env
Normal file
@@ -0,0 +1,3 @@
|
||||
VITE_BASE_URL="https://API.URL"
|
||||
VITE_UPDATE_INTERVAL=5
|
||||
VITE_LIMIT=50
|
@@ -2,6 +2,8 @@
|
||||
"name": "alhp-web",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"generate-api-types": "yarn openapi-typescript ../openapi_alhp.yaml --output src/generated/alhp.ts",
|
||||
"prebuild": "npm run generate-api-types",
|
||||
"dev": "node --no-warnings ./node_modules/.bin/vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview"
|
||||
@@ -10,21 +12,24 @@
|
||||
"@fontsource/roboto": "^5.2.5",
|
||||
"@mdi/font": "7.4.47",
|
||||
"fork-awesome": "^1.2.0",
|
||||
"openapi-fetch": "^0.13.5",
|
||||
"pinia": "^3.0.2",
|
||||
"roboto-fontface": "^0.10.0",
|
||||
"vue": "^3.5.13",
|
||||
"vuetify": "^3.7.18"
|
||||
"vuetify": "^3.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/types": "^7.26.10",
|
||||
"@types/node": "^22.13.11",
|
||||
"@babel/types": "^7.27.0",
|
||||
"@types/node": "^22.14.1",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"openapi-typescript": "^7.6.1",
|
||||
"prettier": "^3.5.3",
|
||||
"sass": "^1.86.0",
|
||||
"typescript": "^5.8.2",
|
||||
"sass": "^1.86.3",
|
||||
"typescript": "^5.8.3",
|
||||
"unplugin-fonts": "^1.3.1",
|
||||
"unplugin-vue-components": "^28.4.1",
|
||||
"vite": "^6.2.2",
|
||||
"vite-plugin-vuetify": "^2.1.0",
|
||||
"unplugin-vue-components": "^28.5.0",
|
||||
"vite": "^6.2.6",
|
||||
"vite-plugin-vuetify": "^2.1.1",
|
||||
"vue-tsc": "^2.2.8"
|
||||
},
|
||||
"packageManager": "yarn@4.7.0"
|
||||
|
@@ -15,6 +15,43 @@
|
||||
<script lang="ts" setup>
|
||||
import MainNav from '@/components/MainNav.vue'
|
||||
import BuildServerStats from '@/components/BuildServerStats.vue'
|
||||
import Packages from '@/components/Packages.vue'
|
||||
import CurrentlyBuilding from '@/components/CurrentlyBuilding.vue'
|
||||
import Packages from '@/components/Packages.vue'
|
||||
import { useStatsStore } from '@/stores/statsStore'
|
||||
import { onBeforeMount, onUnmounted } from 'vue'
|
||||
import { usePackagesStore } from '@/stores'
|
||||
|
||||
const statsStore = useStatsStore()
|
||||
const packagesStore = usePackagesStore()
|
||||
|
||||
let refreshInterval: number | null = null
|
||||
const startAutoRefresh = (intervalMinutes = Number(import.meta.env.VITE_UPDATE_INTERVAL) || 5) => {
|
||||
stopAutoRefresh()
|
||||
refreshInterval = window.setInterval(
|
||||
() => {
|
||||
statsStore.fetchStats()
|
||||
packagesStore.fetchPackages()
|
||||
packagesStore.fetchCurrentlyBuilding()
|
||||
},
|
||||
intervalMinutes * 60 * 1000
|
||||
)
|
||||
}
|
||||
|
||||
const stopAutoRefresh = () => {
|
||||
if (refreshInterval !== null) {
|
||||
clearInterval(refreshInterval)
|
||||
refreshInterval = null
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
statsStore.fetchStats()
|
||||
packagesStore.fetchPackages(true)
|
||||
packagesStore.fetchCurrentlyBuilding()
|
||||
startAutoRefresh()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
stopAutoRefresh()
|
||||
})
|
||||
</script>
|
||||
|
106
frontend/src/api/README.md
Normal file
106
frontend/src/api/README.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# ALHP API Client
|
||||
|
||||
This directory contains a type-safe API client for the ALHP API, generated from the OpenAPI specification.
|
||||
|
||||
## Usage
|
||||
|
||||
### Importing
|
||||
|
||||
```typescript
|
||||
// Import the API client and its functions
|
||||
import { apiClient, getPackages, getStats } from '@/api';
|
||||
|
||||
// Import types
|
||||
import type { components } from '@/api';
|
||||
```
|
||||
|
||||
### Fetching Packages
|
||||
|
||||
```typescript
|
||||
import { getPackages } from '@/api';
|
||||
import type { components } from '@/api';
|
||||
|
||||
// Example: Get packages with filtering
|
||||
async function fetchPackages() {
|
||||
try {
|
||||
const result = await getPackages({
|
||||
status: ['latest', 'building'],
|
||||
pkgbase: 'linux',
|
||||
exact: false,
|
||||
repo: 'core-x86-64-v3',
|
||||
offset: 0,
|
||||
limit: 50
|
||||
});
|
||||
|
||||
// Access the packages
|
||||
const packages: components['schemas']['Package'][] = result.packages || [];
|
||||
const total: number = result.total || 0;
|
||||
|
||||
return { packages, total };
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch packages:', error);
|
||||
return { packages: [], total: 0 };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Fetching Stats
|
||||
|
||||
```typescript
|
||||
import { getStats } from '@/api';
|
||||
import type { components } from '@/api';
|
||||
|
||||
// Example: Get build statistics
|
||||
async function fetchStats() {
|
||||
try {
|
||||
const stats = await getStats();
|
||||
|
||||
// Access the stats
|
||||
const failedCount: number = stats.failed || 0;
|
||||
const ltoEnabled: number = stats.lto?.enabled || 0;
|
||||
|
||||
return stats;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch stats:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Using the Raw API Client
|
||||
|
||||
If you need more control or want to use endpoints not covered by the utility functions, you can use the raw API client:
|
||||
|
||||
```typescript
|
||||
import { apiClient } from '@/api';
|
||||
|
||||
// Example: Custom API call
|
||||
async function customApiCall() {
|
||||
const { data, error } = await apiClient.GET('/packages', {
|
||||
params: {
|
||||
query: {
|
||||
// Your custom parameters
|
||||
status: ['latest'],
|
||||
limit: 10,
|
||||
offset: 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (error) {
|
||||
console.error('API error:', error);
|
||||
return null;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
```
|
||||
|
||||
## Types
|
||||
|
||||
The API client uses types generated from the OpenAPI specification. The main types are:
|
||||
|
||||
- `components['schemas']['Package']`: Type for package data
|
||||
- `components['schemas']['Stats']`: Type for statistics data
|
||||
|
||||
These types provide full TypeScript intellisense and type checking.
|
59
frontend/src/api/client.ts
Normal file
59
frontend/src/api/client.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import createFetch from 'openapi-fetch'
|
||||
import type { paths } from '@/generated/alhp'
|
||||
|
||||
// Create a type-safe API client using the OpenAPI types
|
||||
const apiClient = createFetch<paths>({
|
||||
baseUrl: import.meta.env.VITE_BASE_URL
|
||||
})
|
||||
|
||||
/**
|
||||
* Get packages with optional filtering
|
||||
* @param params Query parameters for filtering packages
|
||||
* @returns Promise with the packages response
|
||||
*/
|
||||
export const getPackages = async (params: {
|
||||
status?: Array<
|
||||
| 'latest'
|
||||
| 'failed'
|
||||
| 'built'
|
||||
| 'skipped'
|
||||
| 'delayed'
|
||||
| 'building'
|
||||
| 'signing'
|
||||
| 'unknown'
|
||||
| 'queued'
|
||||
>
|
||||
pkgbase?: string
|
||||
exact?: boolean
|
||||
repo?: string
|
||||
offset: number
|
||||
limit: number
|
||||
}) => {
|
||||
const { data, error } = await apiClient.GET('/packages', {
|
||||
params: {
|
||||
query: params
|
||||
}
|
||||
})
|
||||
|
||||
if (error) {
|
||||
throw new Error(`Failed to fetch packages: ${(error as any).statusCode}`)
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Get build statistics
|
||||
* @returns Promise with the stats response
|
||||
*/
|
||||
export const getStats = async () => {
|
||||
const { data, error } = await apiClient.GET('/stats')
|
||||
|
||||
if (error) {
|
||||
throw new Error(`Failed to fetch stats: ${(error as any).statusCode || 'unknown error'}`)
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
export default apiClient
|
6
frontend/src/api/index.ts
Normal file
6
frontend/src/api/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
// Export the API client and its functions
|
||||
export { default as apiClient } from './client';
|
||||
export { getPackages, getStats } from './client';
|
||||
|
||||
// Export types from the generated OpenAPI file
|
||||
export type { components } from '../generated/alhp';
|
@@ -2,7 +2,7 @@
|
||||
<v-sheet class="mt-2" color="transparent">
|
||||
<h5 class="text-h5">Buildserver Stats</h5>
|
||||
<iframe
|
||||
:height="width <= 800 ? `${IFRAME_HEIGHT}px` : '420px'"
|
||||
:height="iframeHeight"
|
||||
allowtransparency="true"
|
||||
class="w-100 border-0"
|
||||
src="https://stats.itsh.dev/public-dashboards/0fb04abb0c5e4b7390cf26a98e6dead1"></iframe>
|
||||
@@ -11,40 +11,14 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useDisplay } from 'vuetify'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const { width } = useDisplay()
|
||||
|
||||
/**
|
||||
* Represents the height of a graph in pixels.
|
||||
* This constant is used to define the vertical dimension of the graph
|
||||
* when rendering it in a user interface or graphical representation.
|
||||
*
|
||||
* @constant {number} GRAPH_HEIGHT
|
||||
*/
|
||||
const GRAPH_HEIGHT = 335
|
||||
/**
|
||||
* Represents the total number of graphs to be processed or displayed.
|
||||
*
|
||||
* This variable is used to define the fixed amount of graphs that the system
|
||||
* is intended to handle at a given time. It can be leveraged to set limits
|
||||
* on iterations, arrays, or display logic related to graph management.
|
||||
*
|
||||
* Default value: 4
|
||||
*
|
||||
* Type: number
|
||||
*/
|
||||
const NUMBER_OF_GRAPHS = 4
|
||||
/**
|
||||
* Represents the height of an iframe calculated dynamically based on the number of graphs
|
||||
* and the height of each graph.
|
||||
*
|
||||
* IFRAME_HEIGHT is determined by multiplying the number of graphs (`NUMBER_OF_GRAPHS`)
|
||||
* displayed in the iframe by the height of a single graph (`GRAPH_HEIGHT`).
|
||||
*
|
||||
* This variable is commonly used to ensure the iframe adjusts correctly to accommodate
|
||||
* all graphs without introducing unnecessary scrollbars.
|
||||
*
|
||||
* @constant {number} IFRAME_HEIGHT
|
||||
*/
|
||||
const IFRAME_HEIGHT = NUMBER_OF_GRAPHS * GRAPH_HEIGHT
|
||||
|
||||
const iframeHeight = computed(() =>
|
||||
width.value <= 800 ? `${NUMBER_OF_GRAPHS * GRAPH_HEIGHT}px` : '420px'
|
||||
)
|
||||
</script>
|
||||
|
@@ -1,102 +0,0 @@
|
||||
<template>
|
||||
<v-sheet :style="sheetStyles" class="d-flex" color="transparent">
|
||||
<!-- Dynamically render the "Stats" section -->
|
||||
<v-list :style="listStyles" bg-color="transparent" class="d-flex">
|
||||
<v-list-subheader>Stats:</v-list-subheader>
|
||||
<v-list-item
|
||||
v-for="item in statsList"
|
||||
:key="item.label"
|
||||
:style="{ color: item.color }"
|
||||
:title="item.label">
|
||||
{{ item.value }}
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
<!-- Dynamically render the "LTO" section -->
|
||||
<v-list :style="listStyles" bg-color="transparent" class="d-flex">
|
||||
<v-list-subheader>LTO:</v-list-subheader>
|
||||
<v-list-item
|
||||
v-for="item in ltoList"
|
||||
:key="item.label"
|
||||
:style="{ color: item.color }"
|
||||
:title="item.label">
|
||||
{{ item.value }}
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-sheet>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { type Stats } from '@/types/Stats'
|
||||
|
||||
// Define reusable styles and colors
|
||||
const sheetStyles = { gap: '50px' }
|
||||
const listStyles = { borderRadius: '5px' }
|
||||
const colors = {
|
||||
latest: '#069b35',
|
||||
queued: '#b97808',
|
||||
skipped: '#878787',
|
||||
failed: '#b30303',
|
||||
enabled: '#069b35',
|
||||
disabled: '#b30303',
|
||||
unknown: '#878787'
|
||||
}
|
||||
|
||||
// Reactive stats object
|
||||
const stats = ref<Stats>({
|
||||
latest: 0,
|
||||
queued: 0,
|
||||
skipped: 0,
|
||||
failed: 0,
|
||||
lto: {
|
||||
enabled: 0,
|
||||
disabled: 0,
|
||||
unknown: 0
|
||||
}
|
||||
})
|
||||
|
||||
// Map stats and LTO data for simpler rendering in the template
|
||||
const statsList = ref([
|
||||
{ label: 'latest', value: stats.value.latest, color: colors.latest },
|
||||
{ label: 'queued', value: stats.value.queued, color: colors.queued },
|
||||
{ label: 'skipped', value: stats.value.skipped, color: colors.skipped },
|
||||
{ label: 'failed', value: stats.value.failed, color: colors.failed }
|
||||
])
|
||||
|
||||
const ltoList = ref([
|
||||
{ label: 'enabled', value: stats.value.lto.enabled, color: colors.enabled },
|
||||
{ label: 'disabled', value: stats.value.lto.disabled, color: colors.disabled },
|
||||
{ label: 'unknown', value: stats.value.lto.unknown, color: colors.unknown }
|
||||
])
|
||||
|
||||
// Function to fetch stats data (refactored with async/await)
|
||||
const getStats = async (): Promise<void> => {
|
||||
try {
|
||||
const response = await fetch('https://api.alhp.dev/stats')
|
||||
if (!response.ok) throw new Error(response.statusText)
|
||||
|
||||
const statistics = await response.json()
|
||||
stats.value = statistics
|
||||
|
||||
// Update lists with fresh data
|
||||
statsList.value = [
|
||||
{ label: 'latest', value: stats.value.latest, color: colors.latest },
|
||||
{ label: 'queued', value: stats.value.queued, color: colors.queued },
|
||||
{ label: 'skipped', value: stats.value.skipped, color: colors.skipped },
|
||||
{ label: 'failed', value: stats.value.failed, color: colors.failed }
|
||||
]
|
||||
ltoList.value = [
|
||||
{ label: 'enabled', value: stats.value.lto.enabled, color: colors.enabled },
|
||||
{ label: 'disabled', value: stats.value.lto.disabled, color: colors.disabled },
|
||||
{ label: 'unknown', value: stats.value.lto.unknown, color: colors.unknown }
|
||||
]
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch stats:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch stats on mount
|
||||
onMounted(() => {
|
||||
getStats()
|
||||
})
|
||||
</script>
|
@@ -11,18 +11,32 @@
|
||||
<v-row :class="mobile ? 'mt-1' : ''" class="flex-nowrap ms-1 d-flex align-items-center">
|
||||
<div
|
||||
:class="
|
||||
packageCount.building > 0 ? 'pulsating-circle-amber' : 'pulsating-circle-green'
|
||||
updateFailed
|
||||
? 'pulsating-circle-error'
|
||||
: packageArrays.building.length > 0
|
||||
? 'pulsating-circle-amber'
|
||||
: 'pulsating-circle-green'
|
||||
"
|
||||
class="circle-offset flex-circle" />
|
||||
<span class="ms-2">
|
||||
{{ packageCount.building > 0 ? 'Building' : 'Idle' }}
|
||||
{{
|
||||
updateFailed
|
||||
? 'Could not fetch data.'
|
||||
: packageArrays.building.length > 0
|
||||
? 'Building'
|
||||
: 'Idle'
|
||||
}}
|
||||
</span>
|
||||
</v-row>
|
||||
</v-col>
|
||||
<v-col v-if="packageCount.building > 0" class="v-col-12 v-col-lg-8 mb-3">
|
||||
<v-col v-if="packageArrays.building.length > 0" class="v-col-12 v-col-lg-8 mb-3">
|
||||
<v-progress-linear
|
||||
:max="packageCount.built + packageCount.building + packageCount.queued"
|
||||
:model-value="packageCount.built"
|
||||
:max="
|
||||
packageArrays.built.length +
|
||||
packageArrays.building.length +
|
||||
packageArrays.queued.length
|
||||
"
|
||||
:model-value="packageArrays.built.length"
|
||||
color="light-blue"
|
||||
height="10"
|
||||
rounded
|
||||
@@ -33,21 +47,41 @@
|
||||
class="text-grey v-col-12 v-col-lg-2 mb-3"
|
||||
cols="auto"
|
||||
style="font-size: 13px">
|
||||
<div v-if="!updateFailed" class="d-flex flex-column">
|
||||
<span>
|
||||
Last updated
|
||||
{{ formatTimeAgo(lastUpdatedSeconds) }}
|
||||
<v-tooltip activator="parent" location="start">
|
||||
{{
|
||||
lastUpdatedSeconds > 59
|
||||
? rtf.format(-Math.floor(lastUpdatedSeconds / 60), 'minutes')
|
||||
: rtf.format(-lastUpdatedSeconds, 'seconds')
|
||||
unixTimestampToLocalizedDate(
|
||||
Math.floor((packagesStore.state.lastUpdated || Date.now()) / 1000)
|
||||
)
|
||||
}}
|
||||
</v-tooltip>
|
||||
</span>
|
||||
<span>
|
||||
Last Mirror sync
|
||||
{{ formatTimeAgo(lastMirrorSync) }}
|
||||
<v-tooltip activator="parent" location="start">
|
||||
{{
|
||||
unixTimestampToLocalizedDate(
|
||||
statsStore.state.stats?.last_mirror_timestamp || Math.floor(Date.now() / 1000)
|
||||
)
|
||||
}}
|
||||
</v-tooltip>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<template v-else>Please try again later.</template>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-title>
|
||||
<v-card-text
|
||||
v-if="packageCount.building > 0 || packageCount.queued > 0"
|
||||
v-if="packageArrays.building.length > 0 || packageArrays.queued.length > 0"
|
||||
class="d-flex flex-column">
|
||||
<v-list width="100%">
|
||||
<v-list v-if="packageArrays.building.length > 0" class="mb-4" width="100%">
|
||||
<v-list-subheader>Building</v-list-subheader>
|
||||
<v-list-item v-for="(pkg, index) in packages.building" :key="index">
|
||||
<v-list-item v-for="(pkg, index) in packageArrays.building" :key="index">
|
||||
<template v-slot:prepend>
|
||||
<div class="pulsating-circle-amber me-4" />
|
||||
</template>
|
||||
@@ -58,124 +92,87 @@
|
||||
<v-list-item-subtitle>{{ pkg.arch_version }}</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
<v-sheet class="ps-4 mt-4" color="transparent" rounded width="100%">
|
||||
<v-sheet class="ps-4" color="transparent" rounded width="100%">
|
||||
<h4 class="mb-2 font-weight-light text-grey">Queued</h4>
|
||||
<QueuedPackagesList :packages="packages.queued" />
|
||||
<queued-packages-list :packages="packageArrays.queued" />
|
||||
</v-sheet>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import type { Packages } from '@/types/Packages'
|
||||
import { Package } from '@/types/Package'
|
||||
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import QueuedPackagesList from './QueuedPackagesList.vue'
|
||||
import QueuedPackagesList from '@/components/CurrentlyBuilding/QueuedPackagesList.vue'
|
||||
import { usePackagesStore, useStatsStore } from '@/stores'
|
||||
|
||||
const BASE_URL = 'https://api.alhp.dev/packages'
|
||||
const UPDATE_INTERVAL_MINUTES = 5
|
||||
const statsStore = useStatsStore()
|
||||
const packagesStore = usePackagesStore()
|
||||
|
||||
const { mobile } = useDisplay()
|
||||
const lastUpdatedTime = ref(0)
|
||||
const lastUpdatedSeconds = ref(0)
|
||||
const rtf = new Intl.RelativeTimeFormat('en', {
|
||||
localeMatcher: 'best fit',
|
||||
numeric: 'always',
|
||||
style: 'long'
|
||||
})
|
||||
|
||||
const packageCount = ref({
|
||||
total: 0,
|
||||
building: 0,
|
||||
built: 0,
|
||||
queued: 0
|
||||
const now = ref(Math.floor(Date.now() / 1000))
|
||||
|
||||
const updateFailed = computed(
|
||||
() => !!packagesStore.state.errorCurrentlyBuilding || !!statsStore.state.error
|
||||
)
|
||||
const lastUpdatedSeconds = computed(
|
||||
() => now.value - Math.floor((packagesStore.state.lastUpdated || Date.now()) / 1000)
|
||||
)
|
||||
const lastMirrorSync = computed(
|
||||
() => now.value - (statsStore.state.stats?.last_mirror_timestamp || Math.floor(Date.now() / 1000))
|
||||
)
|
||||
|
||||
const packageArrays = reactive({
|
||||
building: computed(
|
||||
() =>
|
||||
packagesStore.state.currentlyBuildingPackages.filter((pkg) => pkg.status === 'building') || []
|
||||
),
|
||||
queued: computed(
|
||||
() =>
|
||||
packagesStore.state.currentlyBuildingPackages.filter((pkg) => pkg.status === 'queued') || []
|
||||
),
|
||||
built: computed(
|
||||
() =>
|
||||
packagesStore.state.currentlyBuildingPackages.filter((pkg) => pkg.status === 'built') || []
|
||||
)
|
||||
})
|
||||
|
||||
const packages = ref<{
|
||||
built: Array<Package>
|
||||
building: Array<Package>
|
||||
queued: Array<Package>
|
||||
}>({
|
||||
built: [],
|
||||
building: [],
|
||||
queued: []
|
||||
})
|
||||
let updateTimer: number | undefined
|
||||
const startLastUpdatedTimer = () => {
|
||||
updateTimer = window.setInterval(() => {
|
||||
now.value = Math.floor(Date.now() / 1000)
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
const fetchPackages = async (endpoint: string, status?: string) => {
|
||||
let url = `${BASE_URL}?limit=0&offset=0`
|
||||
if (status) {
|
||||
url += `&status=${status}`
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(url, { method: 'GET' })
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
const json: Packages = await response.json()
|
||||
return json
|
||||
} catch (error) {
|
||||
console.error('Error fetching packages:', error)
|
||||
return null
|
||||
const formatTimeAgo = (seconds: number): string => {
|
||||
if (seconds >= 3600) {
|
||||
return rtf.format(-Math.floor(seconds / 3600), 'hours')
|
||||
} else if (seconds >= 60) {
|
||||
return rtf.format(-Math.floor(seconds / 60), 'minutes')
|
||||
} else {
|
||||
return rtf.format(-seconds, 'seconds')
|
||||
}
|
||||
}
|
||||
|
||||
const getTotalPackages = async () => {
|
||||
const json = await fetchPackages(`${BASE_URL}?limit=1&offset=0`)
|
||||
if (json) {
|
||||
packageCount.value.total = json.total
|
||||
}
|
||||
}
|
||||
|
||||
const getBuiltPackages = async () => {
|
||||
const json = await fetchPackages(`${BASE_URL}?limit=0&offset=0`, 'built')
|
||||
if (json) {
|
||||
packageCount.value.built = json.total
|
||||
packages.value.built = json.packages
|
||||
}
|
||||
}
|
||||
|
||||
const getBuildingPackages = async () => {
|
||||
const json = await fetchPackages(`${BASE_URL}?limit=0&offset=0`, 'building')
|
||||
if (json) {
|
||||
packageCount.value.building = json.total
|
||||
packages.value.building = json.packages
|
||||
}
|
||||
}
|
||||
|
||||
const getQueuedPackages = async () => {
|
||||
const json = await fetchPackages(`${BASE_URL}?limit=0&offset=0`, 'queued')
|
||||
if (json) {
|
||||
packageCount.value.queued = json.total
|
||||
packages.value.queued = json.packages
|
||||
}
|
||||
function unixTimestampToLocalizedDate(timestamp: number): string {
|
||||
const date = new Date(timestamp * 1000) // convert to milliseconds
|
||||
return date.toLocaleString(navigator.language)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getTotalPackages()
|
||||
getBuiltPackages()
|
||||
getBuildingPackages()
|
||||
getQueuedPackages()
|
||||
startLastUpdatedTimer()
|
||||
})
|
||||
|
||||
lastUpdatedTime.value = Date.now()
|
||||
lastUpdatedSeconds.value = Math.floor((Date.now() - lastUpdatedTime.value) / 1000)
|
||||
|
||||
setInterval(() => {
|
||||
lastUpdatedSeconds.value = Math.floor((Date.now() - lastUpdatedTime.value) / 1000)
|
||||
}, 1000)
|
||||
|
||||
setInterval(
|
||||
() => {
|
||||
getTotalPackages()
|
||||
getBuiltPackages()
|
||||
getBuildingPackages()
|
||||
getQueuedPackages()
|
||||
lastUpdatedTime.value = Date.now()
|
||||
lastUpdatedSeconds.value = Math.floor((Date.now() - lastUpdatedTime.value) / 1000)
|
||||
},
|
||||
UPDATE_INTERVAL_MINUTES * 60 * 1000
|
||||
)
|
||||
onUnmounted(() => {
|
||||
if (updateTimer) {
|
||||
clearInterval(updateTimer)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -222,16 +219,37 @@ onMounted(() => {
|
||||
animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
|
||||
}
|
||||
|
||||
.pulsating-circle-error {
|
||||
background-color: rgba(225, 64, 6, 0.94);
|
||||
border-radius: 50%;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.pulsating-circle-error:before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
box-sizing: border-box;
|
||||
margin-left: -50%;
|
||||
margin-top: -50%;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(225, 64, 6, 0.94);
|
||||
-webkit-animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
|
||||
animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
|
||||
}
|
||||
|
||||
.circle-offset {
|
||||
transform: translateY(10px); /* Preserves vertical shift as needed */
|
||||
}
|
||||
|
||||
.flex-circle {
|
||||
flex-shrink: 0; /* Prevents shrinking */
|
||||
flex-grow: 0; /* Prevents growing */
|
||||
width: 12px; /* Ensures consistent dimensions */
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%; /* Maintains circular appearance */
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@-webkit-keyframes pulse-ring {
|
||||
|
@@ -39,11 +39,11 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineProps } from 'vue'
|
||||
import type { Package } from '@/types/Package'
|
||||
import { components } from '@/api'
|
||||
|
||||
defineProps({
|
||||
packages: {
|
||||
type: Array<Package>,
|
||||
type: Array<components['schemas']['Package']>,
|
||||
required: true,
|
||||
default: () => []
|
||||
}
|
@@ -1,38 +1,102 @@
|
||||
<template>
|
||||
<v-app-bar color="#191c2a" style="background: #0d1538">
|
||||
<v-container :class="width < 1440 ? 'ms-3' : 'mx-auto'" fluid style="max-width: 1440px">
|
||||
<v-row>
|
||||
<v-app-bar-title style="align-self: center">
|
||||
<span style="font-size: 20px">
|
||||
ALHP Status
|
||||
<a class="ms-2 gitea-link" href="https://somegit.dev/ALHP/ALHP.GO" target="_blank">
|
||||
<i class="fa fa-gitea"></i>
|
||||
</a>
|
||||
<v-app-bar :color="appBarColors.background" aria-label="Main Navigation" role="navigation">
|
||||
<v-container :class="containerClasses" :style="{ maxWidth: maxContainerWidth }" fluid>
|
||||
<v-row align="center">
|
||||
<v-app-bar-title class="app-title">
|
||||
<span aria-label="Home" class="home-link" role="button" tabindex="0">
|
||||
{{ appTitle }}
|
||||
</span>
|
||||
<a
|
||||
:href="repoUrl"
|
||||
aria-label="ALHP GitHub Repository"
|
||||
class="ms-2 gitea-link"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank">
|
||||
<i aria-hidden="true" class="fa fa-gitea"></i>
|
||||
</a>
|
||||
</v-app-bar-title>
|
||||
|
||||
<build-stats v-if="!mobile" />
|
||||
<v-spacer v-if="isDesktop"></v-spacer>
|
||||
|
||||
<build-stats v-if="isDesktop || isTablet" :show-lto="isDesktop" />
|
||||
|
||||
<!-- Mobile menu button could be added here -->
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-app-bar>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import BuildStats from '@/components/BuildStats.vue'
|
||||
import BuildStats from '@/components/MainNav/BuildStats.vue'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const { mobile, width } = useDisplay()
|
||||
const isTablet = computed(() => mobile && width.value >= 650 && width.value < 960)
|
||||
const isDesktop = computed(() => !mobile.value && !isTablet.value)
|
||||
|
||||
interface AppBarColors {
|
||||
background: string
|
||||
accent: string
|
||||
}
|
||||
|
||||
const appTitle = 'ALHP Status'
|
||||
const repoUrl = 'https://somegit.dev/ALHP/ALHP.GO'
|
||||
const maxContainerWidth = '1440px'
|
||||
const appBarColors: AppBarColors = {
|
||||
background: '#0d1538',
|
||||
accent: '#609926'
|
||||
}
|
||||
|
||||
const containerClasses = computed(() => ({
|
||||
'ms-3': width.value < 1440,
|
||||
'mx-auto': width.value >= 1440
|
||||
}))
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.app-title {
|
||||
align-self: center;
|
||||
font-size: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.home-link {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.home-link:hover,
|
||||
.home-link:focus {
|
||||
opacity: 0.9;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.gitea-link {
|
||||
color: white;
|
||||
font-size: 25px;
|
||||
text-decoration: none; /* Optional: To prevent underlining */
|
||||
transition: color 0.2s; /* Smooth color transition */
|
||||
text-decoration: none;
|
||||
transition: color 0.2s;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gitea-link:hover {
|
||||
color: #609926;
|
||||
.gitea-link:hover,
|
||||
.gitea-link:focus {
|
||||
color: v-bind('appBarColors.accent');
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.app-title {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.gitea-link {
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
104
frontend/src/components/MainNav/BuildStats.vue
Normal file
104
frontend/src/components/MainNav/BuildStats.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<v-sheet
|
||||
v-if="!statsStore.state.loading && !statsStore.state.error"
|
||||
:style="sheetStyles"
|
||||
class="d-flex"
|
||||
color="transparent">
|
||||
<StatsListSection title="Stats">
|
||||
<StatItem
|
||||
v-for="(stat, key) in generalStats"
|
||||
:key="key"
|
||||
:color="stat.color"
|
||||
:count="stat.count"
|
||||
:title="key" />
|
||||
</StatsListSection>
|
||||
|
||||
<StatsListSection v-if="showLto" title="LTO">
|
||||
<StatItem
|
||||
v-for="(stat, key) in ltoStats"
|
||||
:key="key"
|
||||
:color="stat.color"
|
||||
:count="stat.count"
|
||||
:title="key" />
|
||||
</StatsListSection>
|
||||
</v-sheet>
|
||||
<v-sheet
|
||||
v-else-if="statsStore.state.loading"
|
||||
:style="sheetStyles"
|
||||
class="d-flex align-center"
|
||||
color="transparent">
|
||||
<v-progress-circular class="mr-2" color="white" indeterminate size="20"></v-progress-circular>
|
||||
<span class="text-caption">Loading stats...</span>
|
||||
</v-sheet>
|
||||
<v-sheet
|
||||
v-else-if="statsStore.state.error"
|
||||
:style="sheetStyles"
|
||||
class="d-flex align-center"
|
||||
color="transparent">
|
||||
<span class="text-caption text-error">Error loading stats</span>
|
||||
</v-sheet>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import { useStatsStore } from '@/stores/statsStore'
|
||||
import StatsListSection from '@/components/MainNav/BuildStats/StatsListSection.vue'
|
||||
import StatItem from '@/components/MainNav/BuildStats/StatItem.vue'
|
||||
|
||||
interface Props {
|
||||
showLto?: boolean
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
showLto: true
|
||||
})
|
||||
|
||||
const COLORS = {
|
||||
SUCCESS: '#069b35',
|
||||
WARNING: '#b97808',
|
||||
ERROR: '#b30303',
|
||||
NEUTRAL: '#878787'
|
||||
}
|
||||
|
||||
const sheetStyles = { gap: '50px' }
|
||||
|
||||
const statsStore = useStatsStore()
|
||||
|
||||
const generalStats = computed(() => ({
|
||||
latest: {
|
||||
count: statsStore.state.stats?.latest || 0,
|
||||
color: COLORS.SUCCESS
|
||||
},
|
||||
queued: {
|
||||
count: statsStore.state.stats?.queued || 0,
|
||||
color: COLORS.WARNING
|
||||
},
|
||||
building: {
|
||||
count: statsStore.state.stats?.building || 0,
|
||||
color: COLORS.WARNING
|
||||
},
|
||||
skipped: {
|
||||
count: statsStore.state.stats?.skipped || 0,
|
||||
color: COLORS.NEUTRAL
|
||||
},
|
||||
failed: {
|
||||
count: statsStore.state.stats?.failed || 0,
|
||||
color: COLORS.ERROR
|
||||
}
|
||||
}))
|
||||
|
||||
const ltoStats = computed(() => ({
|
||||
enabled: {
|
||||
count: statsStore.state.stats?.lto?.enabled || 0,
|
||||
color: COLORS.SUCCESS
|
||||
},
|
||||
disabled: {
|
||||
count: statsStore.state.stats?.lto?.disabled || 0,
|
||||
color: COLORS.ERROR
|
||||
},
|
||||
unknown: {
|
||||
count: statsStore.state.stats?.lto?.unknown || 0,
|
||||
color: COLORS.NEUTRAL
|
||||
}
|
||||
}))
|
||||
</script>
|
13
frontend/src/components/MainNav/BuildStats/StatItem.vue
Normal file
13
frontend/src/components/MainNav/BuildStats/StatItem.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<v-list-item :style="{ color }" :title="title">
|
||||
{{ count }}
|
||||
</v-list-item>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
title: string
|
||||
count: number
|
||||
color: string
|
||||
}>()
|
||||
</script>
|
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<v-list bg-color="transparent" class="stats-list d-flex">
|
||||
<v-list-subheader>{{ title }}:</v-list-subheader>
|
||||
<slot></slot>
|
||||
</v-list>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
title: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.stats-list {
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
@@ -1,398 +1,15 @@
|
||||
<template>
|
||||
<v-sheet :color="TRANSPARENT_COLOR" class="mt-6" width="100%">
|
||||
<h5 class="text-h5 mb-4">Packages</h5>
|
||||
<v-row :style="mobile ? '' : `height: ${ROW_HEIGHT}px`" width="100%">
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-2">
|
||||
<v-text-field
|
||||
v-model="inputPkgBase"
|
||||
clearable
|
||||
color="primary"
|
||||
placeholder="Search Pkgbase"
|
||||
variant="outlined"></v-text-field>
|
||||
</v-col>
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-2 mt-n6 mt-sm-0">
|
||||
<v-select
|
||||
v-model="selectedRepo"
|
||||
:items="selectRepoItems"
|
||||
clearable
|
||||
color="primary"
|
||||
item-title="title"
|
||||
item-value="value"
|
||||
placeholder="Any Repo"
|
||||
return-object
|
||||
single-line
|
||||
variant="outlined"></v-select>
|
||||
</v-col>
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-3 mt-n6 mt-sm-0">
|
||||
<v-select
|
||||
v-model="selectedStatuses"
|
||||
:items="selectStatusItems"
|
||||
chips
|
||||
closable-chips
|
||||
color="primary"
|
||||
density="default"
|
||||
item-title="title"
|
||||
item-value="value"
|
||||
multiple
|
||||
placeholder="Any Status"
|
||||
return-object
|
||||
variant="outlined"></v-select>
|
||||
</v-col>
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-2 mt-n6 mt-sm-0">
|
||||
<v-switch v-model="enableExact" color="primary" label="Exact search"></v-switch>
|
||||
</v-col>
|
||||
<v-col :class="mobile ? 'mt-n6' : ''" :cols="mobile ? 12 : 'auto'" class="ms-auto">
|
||||
<v-pagination
|
||||
v-model="page"
|
||||
:length="pagesMax"
|
||||
:total-visible="mobile ? undefined : 3"
|
||||
active-color="primary"
|
||||
density="comfortable"
|
||||
start="1"
|
||||
variant="text"></v-pagination>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-table class="mt-2 mt-sm-6" style="width: 100%; background: transparent; font-size: 1rem">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Repository</th>
|
||||
<th scope="col">Pkgbase</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col">Reason</th>
|
||||
<th scope="col">
|
||||
LTO
|
||||
<v-tooltip activator="parent" location="bottom">
|
||||
Link time optimization;
|
||||
<br />
|
||||
Does not guarantee that package is actually built with LTO
|
||||
</v-tooltip>
|
||||
</th>
|
||||
<th scope="col">
|
||||
DS
|
||||
<v-tooltip activator="parent" location="bottom">
|
||||
Debug-symbols available via debuginfod
|
||||
</v-tooltip>
|
||||
</th>
|
||||
<th scope="col">Archlinux Version</th>
|
||||
<th scope="col">ALHP Version</th>
|
||||
<th class="text-end" scope="col" style="width: 30px">Info</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="main-tbody">
|
||||
<tr v-if="noPackagesFound">
|
||||
No Packages found
|
||||
</tr>
|
||||
<template v-else>
|
||||
<tr
|
||||
v-for="(pkg, index) in packages"
|
||||
:key="index"
|
||||
:style="`background-color: ${getStatusColor(pkg.status)};`">
|
||||
<td class="font-weight-bold text-no-wrap">
|
||||
{{ repoName(pkg.repo) }}
|
||||
<v-chip
|
||||
:color="getVersionColor(repoVersion(pkg.repo))"
|
||||
class="ms-2"
|
||||
density="comfortable"
|
||||
label
|
||||
variant="flat">
|
||||
{{ repoVersion(pkg.repo) }}
|
||||
</v-chip>
|
||||
</td>
|
||||
<td class="text-no-wrap">{{ pkg.pkgbase }}</td>
|
||||
<td>{{ pkg.status.toLocaleUpperCase() }}</td>
|
||||
<td>{{ pkg.skip_reason || '' }}</td>
|
||||
<td><i :class="getLto(pkg.lto).class" :title="getLto(pkg.lto).title"></i></td>
|
||||
<td>
|
||||
<i
|
||||
:class="getDs(pkg.debug_symbols).class"
|
||||
:title="getDs(pkg.debug_symbols).title"></i>
|
||||
</td>
|
||||
<td>{{ pkg.arch_version }}</td>
|
||||
<td>{{ pkg.repo_version }}</td>
|
||||
<td class="d-flex align-center" style="gap: 3px">
|
||||
<a
|
||||
v-if="pkg.status === 'failed'"
|
||||
:href="`https://alhp.dev/logs/${pkg.repo.slice(pkg.repo.indexOf('-') + 1)}/${pkg.pkgbase}.log`"
|
||||
class="text-decoration-none"
|
||||
style="
|
||||
color: darkgrey;
|
||||
transform: translateY(-3px) translateX(-22px);
|
||||
max-width: 15px;
|
||||
"
|
||||
target="_blank">
|
||||
<i class="fa fa-file-text fa-lg"></i>
|
||||
</a>
|
||||
<span v-else style="width: 15px"></span>
|
||||
<a
|
||||
:href="`https://archlinux.org/packages/?q=${pkg.pkgbase}`"
|
||||
class="text-decoration-none font-weight-bold"
|
||||
style="
|
||||
color: darkgrey;
|
||||
font-size: 18px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 15px;
|
||||
transform: translateX(-15px);
|
||||
"
|
||||
target="_blank"
|
||||
title="ArchWeb">
|
||||
AW
|
||||
</a>
|
||||
<span
|
||||
v-if="pkg.build_date && pkg.peak_mem"
|
||||
class="fa fa-info-circle fa-lg"
|
||||
style="color: darkgrey; transform: translateY(-1px); max-width: 15px !important">
|
||||
<v-tooltip activator="parent" location="start">
|
||||
{{ `Built on ${pkg.build_date}` }}
|
||||
<br />
|
||||
{{ `Peak-Memory: ${pkg.peak_mem}` }}
|
||||
</v-tooltip>
|
||||
</span>
|
||||
<span v-else style="max-width: 15px !important"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</v-table>
|
||||
|
||||
<PackageFilters />
|
||||
|
||||
<PackageTable />
|
||||
</v-sheet>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from 'vue'
|
||||
import { type Package } from '@/types/Package'
|
||||
import { type Packages } from '@/types/Packages'
|
||||
import { useDisplay } from 'vuetify'
|
||||
|
||||
// Constants
|
||||
const OFFSET = 50
|
||||
const ROW_HEIGHT = 60
|
||||
const TRANSPARENT_COLOR = 'transparent'
|
||||
|
||||
// Refs
|
||||
const page = ref(0)
|
||||
const pagesMax = ref(1)
|
||||
const packages = ref<Array<Package>>([])
|
||||
const noPackagesFound = ref(false)
|
||||
const init = ref(false)
|
||||
const inputPkgBase = ref('')
|
||||
const selectedRepo = ref<{ title: string; value: string } | undefined>(undefined)
|
||||
const selectedStatuses = ref<Array<{ title: string; value: string }>>([])
|
||||
const enableExact = ref(false)
|
||||
|
||||
// Display
|
||||
const { mobile } = useDisplay()
|
||||
|
||||
// Select Items
|
||||
const selectRepoItems = [
|
||||
{ title: 'core-x86-64-v2', value: 'core-x86-64-v2' },
|
||||
{ title: 'extra-x86-64-v2', value: 'extra-x86-64-v2' },
|
||||
{ title: 'multilib-x86-64-v2', value: 'multilib-x86-64-v2' },
|
||||
{ title: 'core-x86-64-v3', value: 'core-x86-64-v3' },
|
||||
{ title: 'extra-x86-64-v3', value: 'extra-x86-64-v3' },
|
||||
{ title: 'multilib-x86-64-v3', value: 'multilib-x86-64-v3' },
|
||||
{ title: 'core-x86-64-v4', value: 'core-x86-64-v4' },
|
||||
{ title: 'extra-x86-64-v4', value: 'extra-x86-64-v4' },
|
||||
{ title: 'multilib-x86-64-v4', value: 'multilib-x86-64-v4' }
|
||||
]
|
||||
|
||||
const selectStatusItems = [
|
||||
{ title: 'Latest', value: 'latest' },
|
||||
{ title: 'Built', value: 'built' },
|
||||
{ title: 'Failed', value: 'failed' },
|
||||
{ title: 'Skipped', value: 'skipped' },
|
||||
{ title: 'Delayed', value: 'delayed' },
|
||||
{ title: 'Queued', value: 'queued' },
|
||||
{ title: 'Building', value: 'building' },
|
||||
{ title: 'Signing', value: 'signing' },
|
||||
{ title: 'Unknown', value: 'unknown' }
|
||||
]
|
||||
|
||||
// Computed properties
|
||||
const repoName = (repo: string) => repo.split('-')[0]
|
||||
const repoVersion = (repo: string) => repo.split('-')[repo.split('-').length - 1]
|
||||
|
||||
// Helper function for getting the color associated with a version
|
||||
const getVersionColor = (version: string) => {
|
||||
switch (version) {
|
||||
case 'v2':
|
||||
return '#3498db'
|
||||
case 'v3':
|
||||
return '#f39c12'
|
||||
case 'v4':
|
||||
return '#2ecc71'
|
||||
default:
|
||||
return 'grey'
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function for getting the status color
|
||||
const getStatusColor = (status: Package['status']) => {
|
||||
switch (status) {
|
||||
case 'skipped':
|
||||
return '#373737'
|
||||
case 'queued':
|
||||
return '#5d2f03'
|
||||
case 'latest':
|
||||
return ''
|
||||
case 'failed':
|
||||
return '#4f140f'
|
||||
case 'signing':
|
||||
return '#093372'
|
||||
case 'building':
|
||||
return '#084f46'
|
||||
case 'unknown':
|
||||
return '#191919'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
const getLto = (lto: Package['lto']) => {
|
||||
switch (lto) {
|
||||
case 'enabled':
|
||||
return {
|
||||
title: 'built with LTO',
|
||||
class: 'fa fa-check fa-lg text-success'
|
||||
}
|
||||
case 'unknown':
|
||||
return {
|
||||
title: 'not built with LTO yet',
|
||||
class: 'fa fa-hourglass-o fa-lg text-grey'
|
||||
}
|
||||
case 'disabled':
|
||||
return {
|
||||
title: 'LTO explicitly disabled',
|
||||
class: 'fa fa-times fa-lg text-red'
|
||||
}
|
||||
case 'auto_disabled':
|
||||
return {
|
||||
title: 'LTO automatically disabled',
|
||||
class: 'fa fa-times-circle-o fa-lg text-amber'
|
||||
}
|
||||
default:
|
||||
return { title: '', class: '' }
|
||||
}
|
||||
}
|
||||
|
||||
const getDs = (ds: Package['debug_symbols']) => {
|
||||
switch (ds) {
|
||||
case 'available':
|
||||
return {
|
||||
title: 'Debug symbols available',
|
||||
class: 'fa fa-check fa-lg text-success'
|
||||
}
|
||||
case 'unknown':
|
||||
return {
|
||||
title: 'Not built yet',
|
||||
class: 'fa fa-hourglass-o fa-lg text-grey'
|
||||
}
|
||||
case 'not_available':
|
||||
return {
|
||||
title: 'Not built with debug symbols',
|
||||
class: 'fa fa-times fa-lg text-red'
|
||||
}
|
||||
default:
|
||||
return { title: '', class: '' }
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function for updating URL params dynamically
|
||||
const updateUrlParams = () => {
|
||||
const params = new URLSearchParams()
|
||||
if (page.value > 0) {
|
||||
params.set('offset', (page.value * OFFSET).toString())
|
||||
}
|
||||
if (inputPkgBase.value) {
|
||||
params.set('pkgbase', inputPkgBase.value.toLowerCase())
|
||||
}
|
||||
if (selectedRepo.value) {
|
||||
params.set('repo', selectedRepo.value.value)
|
||||
}
|
||||
if (selectedStatuses.value.length > 0) {
|
||||
selectedStatuses.value.forEach((status) => {
|
||||
params.append('status', status.value)
|
||||
})
|
||||
}
|
||||
if (enableExact.value) {
|
||||
params.set('exact', '')
|
||||
}
|
||||
window.history.pushState(null, '', `${window.location.pathname}?${params}`)
|
||||
}
|
||||
|
||||
const searchPackages = () => {
|
||||
const offset = OFFSET * page.value
|
||||
noPackagesFound.value = false
|
||||
const params = new URLSearchParams()
|
||||
if (page.value > 0) {
|
||||
params.set('offset', offset.toString())
|
||||
}
|
||||
if (inputPkgBase.value) {
|
||||
params.set('pkgbase', inputPkgBase.value.toLowerCase())
|
||||
}
|
||||
if (selectedRepo.value) {
|
||||
params.set('repo', selectedRepo.value.value)
|
||||
}
|
||||
if (selectedStatuses.value.length > 0) {
|
||||
selectedStatuses.value.forEach((status) => {
|
||||
params.append('status', status.value)
|
||||
})
|
||||
}
|
||||
if (enableExact.value) {
|
||||
params.set('exact', '')
|
||||
}
|
||||
params.set('limit', OFFSET.toString())
|
||||
params.set('offset', offset.toString())
|
||||
fetch('https://api.alhp.dev/packages?' + params, {
|
||||
method: 'GET'
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) return response.json()
|
||||
if (response.status === 404) {
|
||||
noPackagesFound.value = true
|
||||
pagesMax.value = 1
|
||||
} else {
|
||||
throw new Error(response.statusText)
|
||||
}
|
||||
})
|
||||
.then((json: Packages) => {
|
||||
if (!json) return
|
||||
pagesMax.value = json.total / OFFSET + 1
|
||||
packages.value = json.packages
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error)
|
||||
})
|
||||
}
|
||||
// Properly set the initial values from URL params
|
||||
onMounted(() => {
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
page.value = urlParams.has('offset')
|
||||
? Math.floor(parseInt(urlParams.get('offset') || '0') / OFFSET)
|
||||
: 0
|
||||
inputPkgBase.value = urlParams.get('pkgbase') || ''
|
||||
const repoValue = urlParams.get('repo')
|
||||
if (repoValue) {
|
||||
selectedRepo.value = { title: repoValue, value: repoValue }
|
||||
} else {
|
||||
selectedRepo.value = undefined
|
||||
}
|
||||
const statuses = urlParams.getAll('status')
|
||||
selectedStatuses.value = statuses.map((status) => ({
|
||||
title: status.toUpperCase(),
|
||||
value: status
|
||||
}))
|
||||
enableExact.value = urlParams.has('exact')
|
||||
searchPackages()
|
||||
})
|
||||
|
||||
// Watchers
|
||||
watch(
|
||||
[page, inputPkgBase, selectedRepo, selectedStatuses, enableExact],
|
||||
() => {
|
||||
if (init.value) return
|
||||
updateUrlParams()
|
||||
searchPackages()
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
import { TRANSPARENT_COLOR } from '@/config/constants'
|
||||
import PackageFilters from '@/components/Packages/PackageFilters.vue'
|
||||
import PackageTable from '@/components/Packages/PackageTable.vue'
|
||||
</script>
|
||||
|
140
frontend/src/components/Packages/PackageFilters.vue
Normal file
140
frontend/src/components/Packages/PackageFilters.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<v-row :style="mobile ? '' : `height: ${ROW_HEIGHT}px`" width="100%">
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-2">
|
||||
<v-text-field
|
||||
v-model="pkgbase"
|
||||
clearable
|
||||
color="primary"
|
||||
placeholder="Search Pkgbase"
|
||||
variant="outlined"></v-text-field>
|
||||
</v-col>
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-2 mt-n6 mt-sm-0">
|
||||
<v-select
|
||||
v-model="repo"
|
||||
:items="REPO_ITEMS"
|
||||
clearable
|
||||
color="primary"
|
||||
placeholder="Any Repo"
|
||||
variant="outlined"></v-select>
|
||||
</v-col>
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-3 mt-n6 mt-sm-0">
|
||||
<v-select
|
||||
v-model="status"
|
||||
:items="STATUS_ITEMS"
|
||||
chips
|
||||
closable-chips
|
||||
color="primary"
|
||||
density="default"
|
||||
item-title="title"
|
||||
item-value="value"
|
||||
multiple
|
||||
placeholder="Any Status"
|
||||
return-object
|
||||
variant="outlined"></v-select>
|
||||
</v-col>
|
||||
<v-col class="v-col-12 v-col-sm-2 v-col-lg-2 mt-n6 mt-sm-0">
|
||||
<v-switch v-model="exact" color="primary" label="Exact search"></v-switch>
|
||||
</v-col>
|
||||
<v-col :class="mobile ? 'mt-n6' : ''" :cols="mobile ? 12 : 'auto'" class="ms-auto">
|
||||
<v-pagination
|
||||
v-model="page"
|
||||
:length="totalPages"
|
||||
:total-visible="mobile ? undefined : 3"
|
||||
active-color="primary"
|
||||
density="comfortable"
|
||||
start="1"
|
||||
variant="text"></v-pagination>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useDisplay } from 'vuetify'
|
||||
import { REPO_ITEMS, ROW_HEIGHT, STATUS_ITEMS } from '@/config/constants'
|
||||
import { usePackagesStore } from '@/stores'
|
||||
import { computed, onMounted, ref, watch } from 'vue'
|
||||
import { components } from '@/api'
|
||||
|
||||
const { mobile } = useDisplay()
|
||||
const packagesStore = usePackagesStore()
|
||||
|
||||
const page = ref<number>(1)
|
||||
const pkgbase = ref<string>()
|
||||
const repo = ref<string>()
|
||||
const status = ref<{ title: string; value: string }[]>([])
|
||||
const exact = ref<boolean>()
|
||||
|
||||
const totalPages = computed(() => Math.ceil(packagesStore.state.total / packagesStore.state.limit))
|
||||
|
||||
const updateFilter = (pageVal?: number) => {
|
||||
if (packagesStore.state.loading) return
|
||||
|
||||
if (pageVal) {
|
||||
page.value = pageVal
|
||||
} else {
|
||||
page.value = 1
|
||||
}
|
||||
|
||||
packagesStore.setFilters(
|
||||
{
|
||||
exact: exact.value,
|
||||
status: status.value.map(
|
||||
(state) => state.value as components['schemas']['Package']['status']
|
||||
),
|
||||
pkgbase: pkgbase.value !== null ? pkgbase.value : undefined,
|
||||
repo: repo.value
|
||||
},
|
||||
page.value
|
||||
)
|
||||
}
|
||||
|
||||
const initFilters = () => {
|
||||
page.value = packagesStore.state.offset / packagesStore.state.limit + 1
|
||||
pkgbase.value = packagesStore.state.filters.pkgbase
|
||||
repo.value = packagesStore.state.filters.repo
|
||||
exact.value = packagesStore.state.filters.exact
|
||||
if (packagesStore.state.filters.status) {
|
||||
for (const state of packagesStore.state.filters.status) {
|
||||
if (state) {
|
||||
status.value.push({ title: state.toUpperCase(), value: state.toLowerCase() })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => page.value,
|
||||
(pageVal) => {
|
||||
packagesStore.goToPage(pageVal)
|
||||
}
|
||||
)
|
||||
|
||||
// Watcher for pkgbase with debounce
|
||||
let pkgbaseTimeout: ReturnType<typeof setTimeout> | null = null
|
||||
watch(
|
||||
() => pkgbase.value,
|
||||
() => {
|
||||
if (pkgbaseTimeout) clearTimeout(pkgbaseTimeout)
|
||||
pkgbaseTimeout = setTimeout(() => {
|
||||
updateFilter()
|
||||
}, 300)
|
||||
}
|
||||
)
|
||||
|
||||
// Watcher for other filters (repo, status, exact) without debounce
|
||||
watch(
|
||||
[() => repo.value, () => status.value?.map((state) => state.value), () => exact.value],
|
||||
() => {
|
||||
// Cancel pending pkgbase debounce if any
|
||||
if (pkgbaseTimeout) {
|
||||
clearTimeout(pkgbaseTimeout)
|
||||
pkgbaseTimeout = null
|
||||
}
|
||||
updateFilter()
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
initFilters()
|
||||
})
|
||||
</script>
|
112
frontend/src/components/Packages/PackageTable.vue
Normal file
112
frontend/src/components/Packages/PackageTable.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<v-table class="mt-2 mt-sm-6" style="width: 100%; background: transparent; font-size: 1rem">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Repository</th>
|
||||
<th scope="col">Pkgbase</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col">Reason</th>
|
||||
<th scope="col">
|
||||
LTO
|
||||
<v-tooltip activator="parent" location="bottom">
|
||||
Link time optimization;
|
||||
<br />
|
||||
Does not guarantee that package is actually built with LTO
|
||||
</v-tooltip>
|
||||
</th>
|
||||
<th scope="col">
|
||||
DS
|
||||
<v-tooltip activator="parent" location="bottom">
|
||||
Debug-symbols available via debuginfod
|
||||
</v-tooltip>
|
||||
</th>
|
||||
<th scope="col">Archlinux Version</th>
|
||||
<th scope="col">ALHP Version</th>
|
||||
<th class="text-end" scope="col" style="width: 30px">Info</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="main-tbody">
|
||||
<tr v-if="packagesStore.state.packages.length === 0">
|
||||
No Packages found
|
||||
</tr>
|
||||
<template v-else>
|
||||
<tr
|
||||
v-for="(pkg, index) in packagesStore.state.packages"
|
||||
:key="index"
|
||||
:style="`background-color: ${getStatusColor(pkg.status)};`">
|
||||
<td class="font-weight-bold text-no-wrap">
|
||||
<v-chip
|
||||
:color="getVersionColor(repoVersion(pkg.repo || ''))"
|
||||
class="me-2"
|
||||
density="comfortable"
|
||||
label
|
||||
variant="flat">
|
||||
{{ repoVersion(pkg.repo || '') }}
|
||||
</v-chip>
|
||||
{{ repoName(pkg.repo || '') }}
|
||||
</td>
|
||||
<td class="text-no-wrap">{{ pkg.pkgbase }}</td>
|
||||
<td>{{ (pkg.status || '').toLocaleUpperCase() }}</td>
|
||||
<td>{{ pkg.skip_reason || '' }}</td>
|
||||
<td><i :class="getLto(pkg.lto).class" :title="getLto(pkg.lto).title"></i></td>
|
||||
<td>
|
||||
<i :class="getDs(pkg.debug_symbols).class" :title="getDs(pkg.debug_symbols).title"></i>
|
||||
</td>
|
||||
<td>{{ pkg.arch_version }}</td>
|
||||
<td>{{ pkg.repo_version }}</td>
|
||||
<td class="d-flex align-center" style="gap: 3px">
|
||||
<a
|
||||
v-if="pkg.status === 'failed'"
|
||||
:href="`https://alhp.dev/logs/${(pkg.repo || '').slice((pkg.repo || '').indexOf('-') + 1)}/${pkg.pkgbase}.log`"
|
||||
class="text-decoration-none"
|
||||
style="
|
||||
color: darkgrey;
|
||||
transform: translateY(-3px) translateX(-22px);
|
||||
max-width: 15px;
|
||||
"
|
||||
target="_blank">
|
||||
<i class="fa fa-file-text fa-lg"></i>
|
||||
</a>
|
||||
<span v-else style="width: 15px"></span>
|
||||
<a
|
||||
:href="`https://archlinux.org/packages/?q=${pkg.pkgbase}`"
|
||||
class="text-decoration-none font-weight-bold"
|
||||
style="
|
||||
color: darkgrey;
|
||||
font-size: 18px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 15px;
|
||||
transform: translateX(-15px);
|
||||
"
|
||||
target="_blank"
|
||||
title="ArchWeb">
|
||||
AW
|
||||
</a>
|
||||
<span
|
||||
v-if="pkg.build_date && pkg.peak_mem"
|
||||
class="fa fa-info-circle fa-lg"
|
||||
style="color: darkgrey; transform: translateY(-1px); max-width: 15px !important">
|
||||
<v-tooltip activator="parent" location="start">
|
||||
{{ `Built on ${pkg.build_date}` }}
|
||||
<br />
|
||||
{{ `Peak-Memory: ${pkg.peak_mem}` }}
|
||||
</v-tooltip>
|
||||
</span>
|
||||
<span v-else style="max-width: 15px !important"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { usePackageDisplay } from '@/composables/Packages/usePackageDisplay'
|
||||
import { usePackagesStore } from '@/stores'
|
||||
|
||||
const { repoName, repoVersion, getVersionColor, getStatusColor, getLto, getDs } =
|
||||
usePackageDisplay()
|
||||
|
||||
const packagesStore = usePackagesStore()
|
||||
</script>
|
98
frontend/src/composables/Packages/usePackageDisplay.ts
Normal file
98
frontend/src/composables/Packages/usePackageDisplay.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { components } from '@/api'
|
||||
|
||||
export function usePackageDisplay() {
|
||||
const repoName = (repo: string) => repo.split('-')[0]
|
||||
const repoVersion = (repo: string) => repo.split('-')[repo.split('-').length - 1]
|
||||
|
||||
const getVersionColor = (version: string) => {
|
||||
switch (version) {
|
||||
case 'v2':
|
||||
return '#3498db'
|
||||
case 'v3':
|
||||
return '#f39c12'
|
||||
case 'v4':
|
||||
return '#2ecc71'
|
||||
default:
|
||||
return 'grey'
|
||||
}
|
||||
}
|
||||
|
||||
const getStatusColor = (status: components['schemas']['Package']['status']) => {
|
||||
switch (status) {
|
||||
case 'skipped':
|
||||
return '#373737'
|
||||
case 'queued':
|
||||
return '#5d2f03'
|
||||
case 'latest':
|
||||
return ''
|
||||
case 'failed':
|
||||
return '#4f140f'
|
||||
case 'signing':
|
||||
return '#093372'
|
||||
case 'building':
|
||||
return '#084f46'
|
||||
case 'unknown':
|
||||
return '#191919'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
const getLto = (lto: components['schemas']['Package']['lto']) => {
|
||||
switch (lto) {
|
||||
case 'enabled':
|
||||
return {
|
||||
title: 'built with LTO',
|
||||
class: 'fa fa-check fa-lg text-success'
|
||||
}
|
||||
case 'unknown':
|
||||
return {
|
||||
title: 'not built with LTO yet',
|
||||
class: 'fa fa-hourglass-o fa-lg text-grey'
|
||||
}
|
||||
case 'disabled':
|
||||
return {
|
||||
title: 'LTO explicitly disabled',
|
||||
class: 'fa fa-times fa-lg text-red'
|
||||
}
|
||||
case 'auto_disabled':
|
||||
return {
|
||||
title: 'LTO automatically disabled',
|
||||
class: 'fa fa-times-circle-o fa-lg text-amber'
|
||||
}
|
||||
default:
|
||||
return { title: '', class: '' }
|
||||
}
|
||||
}
|
||||
|
||||
const getDs = (ds: components['schemas']['Package']['debug_symbols']) => {
|
||||
switch (ds) {
|
||||
case 'available':
|
||||
return {
|
||||
title: 'Debug symbols available',
|
||||
class: 'fa fa-check fa-lg text-success'
|
||||
}
|
||||
case 'unknown':
|
||||
return {
|
||||
title: 'Not built yet',
|
||||
class: 'fa fa-hourglass-o fa-lg text-grey'
|
||||
}
|
||||
case 'not_available':
|
||||
return {
|
||||
title: 'Not built with debug symbols',
|
||||
class: 'fa fa-times fa-lg text-red'
|
||||
}
|
||||
default:
|
||||
return { title: '', class: '' }
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
repoName,
|
||||
repoVersion,
|
||||
getVersionColor,
|
||||
getStatusColor,
|
||||
getLto,
|
||||
getDs
|
||||
}
|
||||
}
|
28
frontend/src/config/constants.ts
Normal file
28
frontend/src/config/constants.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// UI Constants
|
||||
export const TRANSPARENT_COLOR = 'transparent'
|
||||
export const ROW_HEIGHT = 60
|
||||
|
||||
// Select Items Constants
|
||||
export const REPO_ITEMS = [
|
||||
'core-x86-64-v2',
|
||||
'core-x86-64-v3',
|
||||
'core-x86-64-v4',
|
||||
'extra-x86-64-v2',
|
||||
'extra-x86-64-v3',
|
||||
'extra-x86-64-v4',
|
||||
'multilib-x86-64-v2',
|
||||
'multilib-x86-64-v3',
|
||||
'multilib-x86-64-v4'
|
||||
]
|
||||
|
||||
export const STATUS_ITEMS = [
|
||||
{ title: 'Latest', value: 'latest' },
|
||||
{ title: 'Built', value: 'built' },
|
||||
{ title: 'Failed', value: 'failed' },
|
||||
{ title: 'Skipped', value: 'skipped' },
|
||||
{ title: 'Delayed', value: 'delayed' },
|
||||
{ title: 'Queued', value: 'queued' },
|
||||
{ title: 'Building', value: 'building' },
|
||||
{ title: 'Signing', value: 'signing' },
|
||||
{ title: 'Unknown', value: 'unknown' }
|
||||
]
|
273
frontend/src/generated/alhp.ts
Normal file
273
frontend/src/generated/alhp.ts
Normal file
@@ -0,0 +1,273 @@
|
||||
/**
|
||||
* This file was auto-generated by openapi-typescript.
|
||||
* Do not make direct changes to the file.
|
||||
*/
|
||||
|
||||
export interface paths {
|
||||
"/packages": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/**
|
||||
* Retrieve package information
|
||||
* @description Fetch packages from the ALHP system. You can filter results using query parameters.
|
||||
*/
|
||||
get: operations["getPackages"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/stats": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/** Retrieve general build statistics */
|
||||
get: operations["getStats"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
}
|
||||
export type webhooks = Record<string, never>;
|
||||
export interface components {
|
||||
schemas: {
|
||||
Package: {
|
||||
/**
|
||||
* @description The base name of the package
|
||||
* @example linux-zen
|
||||
*/
|
||||
pkgbase?: string;
|
||||
/**
|
||||
* @description Repository from which the package originates
|
||||
* @example extra-x86-64-v4
|
||||
*/
|
||||
repo?: string;
|
||||
/**
|
||||
* @description List of package names split from the base package
|
||||
* @example [
|
||||
* "linux-zen",
|
||||
* "linux-zen-headers",
|
||||
* "linux-zen-docs"
|
||||
* ]
|
||||
*/
|
||||
split_packages?: string[];
|
||||
/**
|
||||
* @description Current build or repository status of the package
|
||||
* @example latest
|
||||
* @enum {string}
|
||||
*/
|
||||
status?: "latest" | "failed" | "built" | "skipped" | "delayed" | "building" | "signing" | "unknown" | "queued";
|
||||
/**
|
||||
* @description Reason for skipping the package build (if any)
|
||||
* @example blacklisted
|
||||
*/
|
||||
skip_reason?: string;
|
||||
/**
|
||||
* @description Link Time Optimization (LTO) status for the package
|
||||
* @example enabled
|
||||
* @enum {string}
|
||||
*/
|
||||
lto?: "enabled" | "unknown" | "disabled" | "auto_disabled";
|
||||
/**
|
||||
* @description Availability of debug symbols in the package
|
||||
* @example available
|
||||
* @enum {string}
|
||||
*/
|
||||
debug_symbols?: "available" | "unknown" | "not_available";
|
||||
/**
|
||||
* @description Version available in the official Arch Linux repositories
|
||||
* @example 1.3.4-2
|
||||
*/
|
||||
arch_version?: string;
|
||||
/**
|
||||
* @description Version available in ALHP repositories (may be empty if not built)
|
||||
* @example 1.3.4-2.1
|
||||
*/
|
||||
repo_version?: string;
|
||||
/**
|
||||
* @description Date and time when the package was built (RFC1123 format)
|
||||
* @example Fri, 15 Dec 2023 03:43:11 UTC
|
||||
*/
|
||||
build_date?: string;
|
||||
/**
|
||||
* @description Peak memory usage during the build process (human-readable format)
|
||||
* @example 5 GB
|
||||
*/
|
||||
peak_mem?: string;
|
||||
};
|
||||
/** @description Aggregated statistics across all packages */
|
||||
Stats: {
|
||||
/**
|
||||
* Format: int64
|
||||
* @description Number of packages that failed to build
|
||||
* @example 17
|
||||
*/
|
||||
failed?: number;
|
||||
/**
|
||||
* Format: int64
|
||||
* @description Number of packages that were skipped
|
||||
* @example 29
|
||||
*/
|
||||
skipped?: number;
|
||||
/**
|
||||
* Format: int64
|
||||
* @description Number of packages that are up-to-date
|
||||
* @example 743
|
||||
*/
|
||||
latest?: number;
|
||||
/**
|
||||
* Format: int64
|
||||
* @description Number of packages currently in the build queue
|
||||
* @example 5
|
||||
*/
|
||||
queued?: number;
|
||||
/**
|
||||
* Format: int64
|
||||
* @description Number of packages currently building
|
||||
* @example 11
|
||||
*/
|
||||
building?: number;
|
||||
/**
|
||||
* Format: int64
|
||||
* @description Latest mirror timestamp to detect outdated mirrors (Unix timestamp)
|
||||
* @example 1702612991
|
||||
*/
|
||||
last_mirror_timestamp?: number;
|
||||
/** @description LTO status summary across all packages */
|
||||
lto?: {
|
||||
/**
|
||||
* Format: int64
|
||||
* @description Number of packages with LTO enabled
|
||||
* @example 532
|
||||
*/
|
||||
enabled?: number;
|
||||
/**
|
||||
* Format: int64
|
||||
* @description Number of packages with LTO explicitly disabled
|
||||
* @example 203
|
||||
*/
|
||||
disabled?: number;
|
||||
/**
|
||||
* Format: int64
|
||||
* @description Number of packages with unknown LTO status
|
||||
* @example 11
|
||||
*/
|
||||
unknown?: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
responses: never;
|
||||
parameters: never;
|
||||
requestBodies: never;
|
||||
headers: never;
|
||||
pathItems: never;
|
||||
}
|
||||
export type $defs = Record<string, never>;
|
||||
export interface operations {
|
||||
getPackages: {
|
||||
parameters: {
|
||||
query: {
|
||||
/** @description Filter by package status. Accepts multiple values via repeated parameters. */
|
||||
status?: ("latest" | "failed" | "built" | "skipped" | "delayed" | "building" | "signing" | "unknown" | "queued")[];
|
||||
/** @description Filter by the base package name (`pkgbase`). This is often the main identifier of a package group. */
|
||||
pkgbase?: string;
|
||||
/** @description If present, matches the `pkgbase` exactly. If not provided, allows partial matches. */
|
||||
exact?: boolean;
|
||||
/** @description Filter by repository name. */
|
||||
repo?: string;
|
||||
/** @description Number of results to skip (for pagination). */
|
||||
offset: number;
|
||||
/** @description Maximum number of results to return. */
|
||||
limit: number;
|
||||
};
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Package data retrieved successfully */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": {
|
||||
packages?: components["schemas"]["Package"][];
|
||||
/**
|
||||
* Format: int64
|
||||
* @description Total number of matching packages
|
||||
* @example 1423
|
||||
*/
|
||||
total?: number;
|
||||
/**
|
||||
* Format: int64
|
||||
* @example 0
|
||||
*/
|
||||
offset?: number;
|
||||
/**
|
||||
* Format: int64
|
||||
* @example 25
|
||||
*/
|
||||
limit?: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
/** @description No packages found matching the specified filters */
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
/** @description Internal server error occurred */
|
||||
500: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
getStats: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description General statistics retrieved successfully */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["Stats"];
|
||||
};
|
||||
};
|
||||
/** @description Internal server error occurred */
|
||||
500: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@@ -1,22 +1,13 @@
|
||||
/**
|
||||
* main.ts
|
||||
*
|
||||
* Bootstraps Vuetify and other plugins then mounts the App`
|
||||
*/
|
||||
|
||||
// Plugins
|
||||
import {registerPlugins} from '@/plugins'
|
||||
|
||||
// Components
|
||||
import { registerPlugins } from '@/plugins'
|
||||
import App from './App.vue'
|
||||
|
||||
// Composables
|
||||
import {createApp} from 'vue'
|
||||
|
||||
// Styles
|
||||
import { createApp } from 'vue'
|
||||
import '@/assets/styles/base.scss'
|
||||
import { createPinia } from 'pinia'
|
||||
|
||||
const pinia = createPinia()
|
||||
|
||||
const app = createApp(App)
|
||||
app.use(pinia)
|
||||
|
||||
registerPlugins(app)
|
||||
|
||||
|
3
frontend/src/stores/index.ts
Normal file
3
frontend/src/stores/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// Export all stores
|
||||
export { useStatsStore } from './statsStore'
|
||||
export { usePackagesStore } from './packagesStore'
|
229
frontend/src/stores/packagesStore.ts
Normal file
229
frontend/src/stores/packagesStore.ts
Normal file
@@ -0,0 +1,229 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { reactive } from 'vue'
|
||||
import { components, getPackages } from '@/api'
|
||||
|
||||
interface PackageFilters {
|
||||
status?: components['schemas']['Package']['status'][]
|
||||
pkgbase?: components['schemas']['Package']['pkgbase']
|
||||
exact?: boolean
|
||||
repo?: components['schemas']['Package']['repo']
|
||||
}
|
||||
|
||||
export const usePackagesStore = defineStore('packages', () => {
|
||||
const state = reactive({
|
||||
packages: [] as components['schemas']['Package'][],
|
||||
currentlyBuildingPackages: [] as components['schemas']['Package'][],
|
||||
total: 0,
|
||||
offset: 0,
|
||||
limit: Number(import.meta.env.VITE_LIMIT) || 50,
|
||||
loading: false,
|
||||
loadingCurrentlyBuilding: false,
|
||||
error: null as string | null,
|
||||
errorCurrentlyBuilding: null as string | null,
|
||||
lastUpdated: Date.now(),
|
||||
filters: {
|
||||
status: undefined,
|
||||
pkgbase: undefined,
|
||||
exact: undefined,
|
||||
repo: undefined
|
||||
} as PackageFilters
|
||||
})
|
||||
|
||||
// Actions
|
||||
const fetchPackages = (init = false) => {
|
||||
state.loading = true
|
||||
state.error = null
|
||||
state.packages = []
|
||||
state.total = 0
|
||||
|
||||
if (init) {
|
||||
initFromUrl()
|
||||
}
|
||||
|
||||
const filter: PackageFilters = {}
|
||||
if (state.filters.status && state.filters.status.length > 0) {
|
||||
filter.status = state.filters.status
|
||||
}
|
||||
if (state.filters.pkgbase) {
|
||||
filter.pkgbase = state.filters.pkgbase
|
||||
}
|
||||
if (state.filters.exact === true) {
|
||||
filter.exact = state.filters.exact
|
||||
}
|
||||
if (state.filters.repo) {
|
||||
filter.repo = state.filters.repo
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
getPackages({
|
||||
limit: state.limit,
|
||||
offset: state.offset,
|
||||
...filter
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response) throw new Error('No response from API')
|
||||
state.packages = response.packages || []
|
||||
state.total = response.total || 0
|
||||
state.offset = response.offset || 0
|
||||
state.limit = response.limit || state.limit
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.statusCode === 404) {
|
||||
state.packages = []
|
||||
state.total = 0
|
||||
state.offset = 0
|
||||
state.limit = Number(import.meta.env.VITE_LIMIT) || 50
|
||||
} else {
|
||||
state.error = err instanceof Error ? err.message : 'Failed to fetch packages'
|
||||
console.error('Error fetching packages:', err)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
state.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
const fetchCurrentlyBuilding = () => {
|
||||
state.loadingCurrentlyBuilding = true
|
||||
state.errorCurrentlyBuilding = null
|
||||
state.currentlyBuildingPackages = []
|
||||
|
||||
getPackages({
|
||||
limit: 0,
|
||||
offset: 0,
|
||||
status: ['queued', 'building', 'built']
|
||||
})
|
||||
.then((response) => {
|
||||
state.currentlyBuildingPackages = response?.packages || []
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.statusCode === 404) {
|
||||
state.currentlyBuildingPackages = []
|
||||
} else {
|
||||
state.errorCurrentlyBuilding =
|
||||
err instanceof Error ? err.message : 'Failed to fetch currently building packages'
|
||||
console.error('Error fetching queued packages:', err)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
state.loadingCurrentlyBuilding = false
|
||||
state.lastUpdated = Date.now()
|
||||
})
|
||||
}
|
||||
|
||||
const goToPage = (page: number) => {
|
||||
state.offset = (page - 1) * state.limit
|
||||
|
||||
updateUrlParams()
|
||||
fetchPackages()
|
||||
}
|
||||
|
||||
const setFilters = (newFilters: PackageFilters, page?: number) => {
|
||||
state.filters = JSON.parse(JSON.stringify(newFilters))
|
||||
if (state.filters.exact === false) {
|
||||
state.filters.exact = undefined
|
||||
}
|
||||
if (page) {
|
||||
state.offset = (page - 1) * state.limit
|
||||
}
|
||||
|
||||
updateUrlParams()
|
||||
fetchPackages()
|
||||
}
|
||||
|
||||
const resetFilters = () => {
|
||||
state.filters = {
|
||||
status: undefined,
|
||||
pkgbase: undefined,
|
||||
exact: undefined,
|
||||
repo: undefined
|
||||
}
|
||||
state.offset = 0
|
||||
state.limit = Number(import.meta.env.VITE_LIMIT) || 50
|
||||
|
||||
updateUrlParams()
|
||||
fetchPackages()
|
||||
}
|
||||
|
||||
const updateUrlParams = () => {
|
||||
const params = new URLSearchParams()
|
||||
|
||||
let page = state.offset / state.limit + 1
|
||||
// Only add a page parameter if it's not the first page
|
||||
if (page > 1) {
|
||||
params.set('page', page.toString())
|
||||
}
|
||||
|
||||
if (state.filters.status && state.filters.status.length > 0) {
|
||||
state.filters.status.forEach((status: components['schemas']['Package']['status']) => {
|
||||
if (status) {
|
||||
params.append('status', status)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (state.filters.pkgbase) {
|
||||
params.set('pkgbase', state.filters.pkgbase.toLowerCase())
|
||||
}
|
||||
|
||||
if (state.filters.repo) {
|
||||
params.set('repo', state.filters.repo)
|
||||
}
|
||||
|
||||
if (state.filters.exact === true) {
|
||||
params.set('exact', '')
|
||||
} else {
|
||||
params.delete('exact')
|
||||
}
|
||||
|
||||
const paramsString = params.toString()
|
||||
if (paramsString) {
|
||||
window.history.pushState(null, '', `${window.location.pathname}?${paramsString}`)
|
||||
} else {
|
||||
window.history.pushState(null, '', window.location.pathname)
|
||||
}
|
||||
}
|
||||
|
||||
const initFromUrl = () => {
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
|
||||
if (urlParams.has('page')) {
|
||||
const pageParam = urlParams.get('page') || '1'
|
||||
const parsedPage = parseInt(pageParam, 10)
|
||||
const page = !isNaN(parsedPage) && parsedPage > 0 ? parsedPage : 1
|
||||
state.offset = (page - 1) * state.limit
|
||||
}
|
||||
|
||||
if (urlParams.has('status')) {
|
||||
const status = urlParams.getAll('status')
|
||||
state.filters.status = status as components['schemas']['Package']['status'][]
|
||||
}
|
||||
|
||||
if (urlParams.has('pkgbase')) {
|
||||
const pkgbase = urlParams.get('pkgbase')
|
||||
if (pkgbase === null) return
|
||||
state.filters.pkgbase = pkgbase as components['schemas']['Package']['pkgbase']
|
||||
}
|
||||
|
||||
if (urlParams.has('repo')) {
|
||||
const repo = urlParams.get('repo')
|
||||
if (repo === null) return
|
||||
state.filters.repo = repo as components['schemas']['Package']['repo']
|
||||
}
|
||||
|
||||
if (urlParams.has('exact')) {
|
||||
state.filters.exact = true
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
|
||||
// Actions
|
||||
fetchPackages,
|
||||
fetchCurrentlyBuilding,
|
||||
goToPage,
|
||||
setFilters,
|
||||
resetFilters
|
||||
}
|
||||
})
|
37
frontend/src/stores/statsStore.ts
Normal file
37
frontend/src/stores/statsStore.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { reactive } from 'vue'
|
||||
import { components, getStats } from '@/api'
|
||||
|
||||
export const useStatsStore = defineStore('stats', () => {
|
||||
const state = reactive({
|
||||
stats: {} as components['schemas']['Stats'] | undefined | null,
|
||||
loading: false,
|
||||
error: null as string | null,
|
||||
lastUpdated: Date.now()
|
||||
})
|
||||
|
||||
// Actions
|
||||
const fetchStats = () => {
|
||||
state.loading = true
|
||||
state.error = null
|
||||
|
||||
getStats()
|
||||
.then((response) => {
|
||||
state.stats = response
|
||||
})
|
||||
.catch((err) => {
|
||||
state.error = err instanceof Error ? err.message : 'Failed to fetch packages'
|
||||
console.error('Error fetching packages:', err)
|
||||
})
|
||||
.finally(() => {
|
||||
state.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
|
||||
// Actions
|
||||
fetchStats
|
||||
}
|
||||
})
|
@@ -1,22 +0,0 @@
|
||||
export interface Package {
|
||||
pkgbase: string
|
||||
repo: string
|
||||
split_packages: Array<string>
|
||||
status:
|
||||
| 'latest'
|
||||
| 'failed'
|
||||
| 'built'
|
||||
| 'skipped'
|
||||
| 'delayed'
|
||||
| 'building'
|
||||
| 'signing'
|
||||
| 'unknown'
|
||||
| 'queued'
|
||||
skip_reason: string
|
||||
lto: 'enabled' | 'unknown' | 'disabled' | 'auto_disabled'
|
||||
debug_symbols: 'available' | 'unknown' | 'not_available'
|
||||
arch_version: string
|
||||
repo_version: string
|
||||
build_date: string
|
||||
peak_mem: any
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
import { type Package } from '@/types/Package'
|
||||
|
||||
export interface Packages {
|
||||
packages: Array<Package>
|
||||
total: number
|
||||
offset: number
|
||||
limit: number
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
import { type Stats_Lto } from '@/types/Stats_Lto'
|
||||
|
||||
export interface Stats {
|
||||
latest: number
|
||||
queued: number
|
||||
skipped: number
|
||||
failed: number
|
||||
lto: Stats_Lto
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
export interface Stats_Lto {
|
||||
enabled: number
|
||||
disabled: number
|
||||
unknown: number
|
||||
}
|
@@ -5,6 +5,17 @@ __metadata:
|
||||
version: 8
|
||||
cacheKey: 10c0
|
||||
|
||||
"@babel/code-frame@npm:^7.26.2":
|
||||
version: 7.26.2
|
||||
resolution: "@babel/code-frame@npm:7.26.2"
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier": "npm:^7.25.9"
|
||||
js-tokens: "npm:^4.0.0"
|
||||
picocolors: "npm:^1.0.0"
|
||||
checksum: 10c0/7d79621a6849183c415486af99b1a20b84737e8c11cd55b6544f688c51ce1fd710e6d869c3dd21232023da272a79b91efb3e83b5bc2dc65c1187c5fcd1b72ea8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-string-parser@npm:^7.25.9":
|
||||
version: 7.25.9
|
||||
resolution: "@babel/helper-string-parser@npm:7.25.9"
|
||||
@@ -40,6 +51,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/types@npm:^7.27.0":
|
||||
version: 7.27.0
|
||||
resolution: "@babel/types@npm:7.27.0"
|
||||
dependencies:
|
||||
"@babel/helper-string-parser": "npm:^7.25.9"
|
||||
"@babel/helper-validator-identifier": "npm:^7.25.9"
|
||||
checksum: 10c0/6f1592eabe243c89a608717b07b72969be9d9d2fce1dee21426238757ea1fa60fdfc09b29de9e48d8104311afc6e6fb1702565a9cc1e09bc1e76f2b2ddb0f6e1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/aix-ppc64@npm:0.25.1":
|
||||
version: 0.25.1
|
||||
resolution: "@esbuild/aix-ppc64@npm:0.25.1"
|
||||
@@ -450,6 +471,42 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@redocly/ajv@npm:^8.11.2":
|
||||
version: 8.11.2
|
||||
resolution: "@redocly/ajv@npm:8.11.2"
|
||||
dependencies:
|
||||
fast-deep-equal: "npm:^3.1.1"
|
||||
json-schema-traverse: "npm:^1.0.0"
|
||||
require-from-string: "npm:^2.0.2"
|
||||
uri-js-replace: "npm:^1.0.1"
|
||||
checksum: 10c0/249ca2e237f7b1248ee1018ba1ad3a739cb9f16e5f7fe821875948806980d65246c79ef7d5e7bd8db773c120e2cd5ce15aa47883893608e1965ca4d45c5572f4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@redocly/config@npm:^0.22.0":
|
||||
version: 0.22.2
|
||||
resolution: "@redocly/config@npm:0.22.2"
|
||||
checksum: 10c0/625e947e7939e2d59bd83f516af5a581411167e3fc83adf7322bddf9bc69038fc601ed4ee8abae44d298ed367a16a1a09e7cdbe8b5dde172b4ce53c88d8717f4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@redocly/openapi-core@npm:^1.28.0":
|
||||
version: 1.34.2
|
||||
resolution: "@redocly/openapi-core@npm:1.34.2"
|
||||
dependencies:
|
||||
"@redocly/ajv": "npm:^8.11.2"
|
||||
"@redocly/config": "npm:^0.22.0"
|
||||
colorette: "npm:^1.2.0"
|
||||
https-proxy-agent: "npm:^7.0.5"
|
||||
js-levenshtein: "npm:^1.1.6"
|
||||
js-yaml: "npm:^4.1.0"
|
||||
minimatch: "npm:^5.0.1"
|
||||
pluralize: "npm:^8.0.0"
|
||||
yaml-ast-parser: "npm:0.0.43"
|
||||
checksum: 10c0/252710cdc7fd182f37c2fedaa27cbd8ea5f882e3340515bf572372adc35e5cdc0bfc0aae2ce51defa91d1fd9a2f9d82454104b0c9ab22895f941196f50830b33
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@rollup/rollup-android-arm-eabi@npm:4.36.0":
|
||||
version: 4.36.0
|
||||
resolution: "@rollup/rollup-android-arm-eabi@npm:4.36.0"
|
||||
@@ -590,12 +647,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:^22.13.11":
|
||||
version: 22.13.11
|
||||
resolution: "@types/node@npm:22.13.11"
|
||||
"@types/node@npm:^22.14.1":
|
||||
version: 22.14.1
|
||||
resolution: "@types/node@npm:22.14.1"
|
||||
dependencies:
|
||||
undici-types: "npm:~6.20.0"
|
||||
checksum: 10c0/f6ee33d36372242535c38640fe7550a6640d8a775ec19b55bfc11775b521cba072d892ca92a912332ce01b317293d645c1bf767f3f882ec719f2404a3d2a5b96
|
||||
undici-types: "npm:~6.21.0"
|
||||
checksum: 10c0/d49c4d00403b1c2348cf0701b505fd636d80aabe18102105998dc62fdd36dcaf911e73c7a868c48c21c1022b825c67b475b65b1222d84b704d8244d152bb7f86
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -696,6 +753,39 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vue/devtools-api@npm:^7.7.2":
|
||||
version: 7.7.2
|
||||
resolution: "@vue/devtools-api@npm:7.7.2"
|
||||
dependencies:
|
||||
"@vue/devtools-kit": "npm:^7.7.2"
|
||||
checksum: 10c0/418d3c868143a91518bc846965f7c8a955f072b8526d0f739f4d7dc00b13a0f56b214d876bfff338dc841762b526a1a4c11b5e8b0ab6dd7f3250a694ec8dfbe3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vue/devtools-kit@npm:^7.7.2":
|
||||
version: 7.7.2
|
||||
resolution: "@vue/devtools-kit@npm:7.7.2"
|
||||
dependencies:
|
||||
"@vue/devtools-shared": "npm:^7.7.2"
|
||||
birpc: "npm:^0.2.19"
|
||||
hookable: "npm:^5.5.3"
|
||||
mitt: "npm:^3.0.1"
|
||||
perfect-debounce: "npm:^1.0.0"
|
||||
speakingurl: "npm:^14.0.1"
|
||||
superjson: "npm:^2.2.1"
|
||||
checksum: 10c0/e052ba756558040855304b6ee13ba39131a44c89a9f78ab262c79f8a0e6b58fa379e1efa306a9a50675cac3e48baeb3f86b1560f64edf48cbc0695165d0b2be6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vue/devtools-shared@npm:^7.7.2":
|
||||
version: 7.7.2
|
||||
resolution: "@vue/devtools-shared@npm:7.7.2"
|
||||
dependencies:
|
||||
rfdc: "npm:^1.4.1"
|
||||
checksum: 10c0/6399135da41a91f48c3db7c59cedb01ad331af7784ef0877c15c669ad5a5d1cce68f73d50d81f85a31a90b0d6323ff807ebe5b1fb041d1e86932f2c983a0cdad
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@vue/language-core@npm:2.2.8":
|
||||
version: 2.2.8
|
||||
resolution: "@vue/language-core@npm:2.2.8"
|
||||
@@ -804,6 +894,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"agent-base@npm:^7.1.2":
|
||||
version: 7.1.3
|
||||
resolution: "agent-base@npm:7.1.3"
|
||||
checksum: 10c0/6192b580c5b1d8fb399b9c62bf8343d76654c2dd62afcb9a52b2cf44a8b6ace1e3b704d3fe3547d91555c857d3df02603341ff2cb961b9cfe2b12f9f3c38ee11
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"aggregate-error@npm:^3.0.0":
|
||||
version: 3.1.0
|
||||
resolution: "aggregate-error@npm:3.1.0"
|
||||
@@ -818,23 +915,26 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "alhp-web@workspace:."
|
||||
dependencies:
|
||||
"@babel/types": "npm:^7.26.10"
|
||||
"@babel/types": "npm:^7.27.0"
|
||||
"@fontsource/roboto": "npm:^5.2.5"
|
||||
"@mdi/font": "npm:7.4.47"
|
||||
"@types/node": "npm:^22.13.11"
|
||||
"@types/node": "npm:^22.14.1"
|
||||
"@vitejs/plugin-vue": "npm:^5.2.3"
|
||||
fork-awesome: "npm:^1.2.0"
|
||||
openapi-fetch: "npm:^0.13.5"
|
||||
openapi-typescript: "npm:^7.6.1"
|
||||
pinia: "npm:^3.0.2"
|
||||
prettier: "npm:^3.5.3"
|
||||
roboto-fontface: "npm:^0.10.0"
|
||||
sass: "npm:^1.86.0"
|
||||
typescript: "npm:^5.8.2"
|
||||
sass: "npm:^1.86.3"
|
||||
typescript: "npm:^5.8.3"
|
||||
unplugin-fonts: "npm:^1.3.1"
|
||||
unplugin-vue-components: "npm:^28.4.1"
|
||||
vite: "npm:^6.2.2"
|
||||
vite-plugin-vuetify: "npm:^2.1.0"
|
||||
unplugin-vue-components: "npm:^28.5.0"
|
||||
vite: "npm:^6.2.6"
|
||||
vite-plugin-vuetify: "npm:^2.1.1"
|
||||
vue: "npm:^3.5.13"
|
||||
vue-tsc: "npm:^2.2.8"
|
||||
vuetify: "npm:^3.7.18"
|
||||
vuetify: "npm:^3.8.1"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@@ -845,6 +945,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ansi-colors@npm:^4.1.3":
|
||||
version: 4.1.3
|
||||
resolution: "ansi-colors@npm:4.1.3"
|
||||
checksum: 10c0/ec87a2f59902f74e61eada7f6e6fe20094a628dab765cfdbd03c3477599368768cffccdb5d3bb19a1b6c99126783a143b1fee31aab729b31ffe5836c7e5e28b9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ansi-regex@npm:^5.0.1":
|
||||
version: 5.0.1
|
||||
resolution: "ansi-regex@npm:5.0.1"
|
||||
@@ -885,6 +992,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"argparse@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "argparse@npm:2.0.1"
|
||||
checksum: 10c0/c5640c2d89045371c7cedd6a70212a04e360fd34d6edeae32f6952c63949e3525ea77dbec0289d8213a99bbaeab5abfa860b5c12cf88a2e6cf8106e90dd27a7e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"balanced-match@npm:^1.0.0":
|
||||
version: 1.0.2
|
||||
resolution: "balanced-match@npm:1.0.2"
|
||||
@@ -899,6 +1013,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"birpc@npm:^0.2.19":
|
||||
version: 0.2.19
|
||||
resolution: "birpc@npm:0.2.19"
|
||||
checksum: 10c0/be3c6a4044e3041a5d8eb4c4d50b57b46158dc8149ada718ead20544e50b68b72b34c9d8bf0457d23d5f18e5a66d206b8bef5ff22c1018e1e39d373187eed455
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"brace-expansion@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "brace-expansion@npm:2.0.1"
|
||||
@@ -946,6 +1067,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"change-case@npm:^5.4.4":
|
||||
version: 5.4.4
|
||||
resolution: "change-case@npm:5.4.4"
|
||||
checksum: 10c0/2a9c2b9c9ad6ab2491105aaf506db1a9acaf543a18967798dcce20926c6a173aa63266cb6189f3086e3c14bf7ae1f8ea4f96ecc466fcd582310efa00372f3734
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"chokidar@npm:^3.6.0":
|
||||
version: 3.6.0
|
||||
resolution: "chokidar@npm:3.6.0"
|
||||
@@ -1004,6 +1132,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"colorette@npm:^1.2.0":
|
||||
version: 1.4.0
|
||||
resolution: "colorette@npm:1.4.0"
|
||||
checksum: 10c0/4955c8f7daafca8ae7081d672e4bd89d553bd5782b5846d5a7e05effe93c2f15f7e9c0cb46f341b59f579a39fcf436241ff79594899d75d5f3460c03d607fe9e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"confbox@npm:^0.1.8":
|
||||
version: 0.1.8
|
||||
resolution: "confbox@npm:0.1.8"
|
||||
@@ -1018,6 +1153,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"copy-anything@npm:^3.0.2":
|
||||
version: 3.0.5
|
||||
resolution: "copy-anything@npm:3.0.5"
|
||||
dependencies:
|
||||
is-what: "npm:^4.1.8"
|
||||
checksum: 10c0/01eadd500c7e1db71d32d95a3bfaaedcb839ef891c741f6305ab0461398056133de08f2d1bf4c392b364e7bdb7ce498513896e137a7a183ac2516b065c28a4fe
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cross-spawn@npm:^7.0.0":
|
||||
version: 7.0.3
|
||||
resolution: "cross-spawn@npm:7.0.3"
|
||||
@@ -1246,6 +1390,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-deep-equal@npm:^3.1.1":
|
||||
version: 3.1.3
|
||||
resolution: "fast-deep-equal@npm:3.1.3"
|
||||
checksum: 10c0/40dedc862eb8992c54579c66d914635afbec43350afbbe991235fdcb4e3a8d5af1b23ae7e79bef7d4882d0ecee06c3197488026998fb19f72dc95acff1d1b1d0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-glob@npm:^3.3.2":
|
||||
version: 3.3.2
|
||||
resolution: "fast-glob@npm:3.3.2"
|
||||
@@ -1393,6 +1544,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hookable@npm:^5.5.3":
|
||||
version: 5.5.3
|
||||
resolution: "hookable@npm:5.5.3"
|
||||
checksum: 10c0/275f4cc84d27f8d48c5a5cd5685b6c0fea9291be9deea5bff0cfa72856ed566abde1dcd8cb1da0f9a70b4da3d7ec0d60dc3554c4edbba647058cc38816eced3d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"http-cache-semantics@npm:^4.1.1":
|
||||
version: 4.1.1
|
||||
resolution: "http-cache-semantics@npm:4.1.1"
|
||||
@@ -1420,6 +1578,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"https-proxy-agent@npm:^7.0.5":
|
||||
version: 7.0.6
|
||||
resolution: "https-proxy-agent@npm:7.0.6"
|
||||
dependencies:
|
||||
agent-base: "npm:^7.1.2"
|
||||
debug: "npm:4"
|
||||
checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"iconv-lite@npm:^0.6.2":
|
||||
version: 0.6.3
|
||||
resolution: "iconv-lite@npm:0.6.3"
|
||||
@@ -1450,6 +1618,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"index-to-position@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "index-to-position@npm:1.1.0"
|
||||
checksum: 10c0/77ef140f0218df0486a08cff204de4d382e8c43892039aaa441ac5b87f0c8d8a72af633c8a1c49f1b1ec4177bd809e4e045958a9aebe65545f203342b95886b3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ip-address@npm:^9.0.5":
|
||||
version: 9.0.5
|
||||
resolution: "ip-address@npm:9.0.5"
|
||||
@@ -1506,6 +1681,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"is-what@npm:^4.1.8":
|
||||
version: 4.1.16
|
||||
resolution: "is-what@npm:4.1.16"
|
||||
checksum: 10c0/611f1947776826dcf85b57cfb7bd3b3ea6f4b94a9c2f551d4a53f653cf0cb9d1e6518846648256d46ee6c91d114b6d09d2ac8a07306f7430c5900f87466aae5b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"isexe@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "isexe@npm:2.0.0"
|
||||
@@ -1533,6 +1715,31 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"js-levenshtein@npm:^1.1.6":
|
||||
version: 1.1.6
|
||||
resolution: "js-levenshtein@npm:1.1.6"
|
||||
checksum: 10c0/14045735325ea1fd87f434a74b11d8a14380f090f154747e613529c7cff68b5ee607f5230fa40665d5fb6125a3791f4c223f73b9feca754f989b059f5c05864f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"js-tokens@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "js-tokens@npm:4.0.0"
|
||||
checksum: 10c0/e248708d377aa058eacf2037b07ded847790e6de892bbad3dac0abba2e759cb9f121b00099a65195616badcb6eca8d14d975cb3e89eb1cfda644756402c8aeed
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"js-yaml@npm:^4.1.0":
|
||||
version: 4.1.0
|
||||
resolution: "js-yaml@npm:4.1.0"
|
||||
dependencies:
|
||||
argparse: "npm:^2.0.1"
|
||||
bin:
|
||||
js-yaml: bin/js-yaml.js
|
||||
checksum: 10c0/184a24b4eaacfce40ad9074c64fd42ac83cf74d8c8cd137718d456ced75051229e5061b8633c3366b8aada17945a7a356b337828c19da92b51ae62126575018f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jsbn@npm:1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "jsbn@npm:1.1.0"
|
||||
@@ -1540,7 +1747,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"local-pkg@npm:^1.0.0":
|
||||
"json-schema-traverse@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "json-schema-traverse@npm:1.0.0"
|
||||
checksum: 10c0/71e30015d7f3d6dc1c316d6298047c8ef98a06d31ad064919976583eb61e1018a60a0067338f0f79cabc00d84af3fcc489bd48ce8a46ea165d9541ba17fb30c6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"local-pkg@npm:^1.1.1":
|
||||
version: 1.1.1
|
||||
resolution: "local-pkg@npm:1.1.1"
|
||||
dependencies:
|
||||
@@ -1614,6 +1828,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minimatch@npm:^5.0.1":
|
||||
version: 5.1.6
|
||||
resolution: "minimatch@npm:5.1.6"
|
||||
dependencies:
|
||||
brace-expansion: "npm:^2.0.1"
|
||||
checksum: 10c0/3defdfd230914f22a8da203747c42ee3c405c39d4d37ffda284dac5e45b7e1f6c49aa8be606509002898e73091ff2a3bbfc59c2c6c71d4660609f63aa92f98e3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minimatch@npm:^9.0.3":
|
||||
version: 9.0.3
|
||||
resolution: "minimatch@npm:9.0.3"
|
||||
@@ -1716,6 +1939,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"mitt@npm:^3.0.1":
|
||||
version: 3.0.1
|
||||
resolution: "mitt@npm:3.0.1"
|
||||
checksum: 10c0/3ab4fdecf3be8c5255536faa07064d05caa3dd332bd318ff02e04621f7b3069ca1de9106cfe8e7ced675abfc2bec2ce4c4ef321c4a1bb1fb29df8ae090741913
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"mkdirp@npm:^1.0.3":
|
||||
version: 1.0.4
|
||||
resolution: "mkdirp@npm:1.0.4"
|
||||
@@ -1821,6 +2051,40 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"openapi-fetch@npm:^0.13.5":
|
||||
version: 0.13.5
|
||||
resolution: "openapi-fetch@npm:0.13.5"
|
||||
dependencies:
|
||||
openapi-typescript-helpers: "npm:^0.0.15"
|
||||
checksum: 10c0/57736d9d4310d7bc7fa5e4e37e80d28893a7fefee88ee6e0327600de893e0638479445bf0c9f5bd7b1a2429f409425d3945d6e942b23b37b8081630ac52244fb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"openapi-typescript-helpers@npm:^0.0.15":
|
||||
version: 0.0.15
|
||||
resolution: "openapi-typescript-helpers@npm:0.0.15"
|
||||
checksum: 10c0/5eb68d487b787e3e31266470b1a310726549dd45a1079655ab18066ab291b0b3c343fdf629991013706a2329b86964f8798d56ef0272b94b931fe6c19abd7a88
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"openapi-typescript@npm:^7.6.1":
|
||||
version: 7.6.1
|
||||
resolution: "openapi-typescript@npm:7.6.1"
|
||||
dependencies:
|
||||
"@redocly/openapi-core": "npm:^1.28.0"
|
||||
ansi-colors: "npm:^4.1.3"
|
||||
change-case: "npm:^5.4.4"
|
||||
parse-json: "npm:^8.1.0"
|
||||
supports-color: "npm:^9.4.0"
|
||||
yargs-parser: "npm:^21.1.1"
|
||||
peerDependencies:
|
||||
typescript: ^5.x
|
||||
bin:
|
||||
openapi-typescript: bin/cli.js
|
||||
checksum: 10c0/3591be796ac5eb1fe051b765c29e7cc5fcf9bb59e83eb43e13b4c98f25957d78523a5c8922eb52f1785b3fab6f5e269bc02892d72350ac7274d41192a36673c9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"p-map@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "p-map@npm:4.0.0"
|
||||
@@ -1837,6 +2101,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"parse-json@npm:^8.1.0":
|
||||
version: 8.3.0
|
||||
resolution: "parse-json@npm:8.3.0"
|
||||
dependencies:
|
||||
"@babel/code-frame": "npm:^7.26.2"
|
||||
index-to-position: "npm:^1.1.0"
|
||||
type-fest: "npm:^4.39.1"
|
||||
checksum: 10c0/0eb5a50f88b8428c8f7a9cf021636c16664f0c62190323652d39e7bdf62953e7c50f9957e55e17dc2d74fc05c89c11f5553f381dbc686735b537ea9b101c7153
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"path-browserify@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "path-browserify@npm:1.0.1"
|
||||
@@ -1868,7 +2143,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"picocolors@npm:^1.1.1":
|
||||
"perfect-debounce@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "perfect-debounce@npm:1.0.0"
|
||||
checksum: 10c0/e2baac416cae046ef1b270812cf9ccfb0f91c04ea36ac7f5b00bc84cb7f41bdbba087c0ab21b4e02a7ef3a1f1f6db399f137cecec46868bd7d8d88c2a9ee431f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"picocolors@npm:^1.0.0, picocolors@npm:^1.1.1":
|
||||
version: 1.1.1
|
||||
resolution: "picocolors@npm:1.1.1"
|
||||
checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58
|
||||
@@ -1889,6 +2171,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pinia@npm:^3.0.2":
|
||||
version: 3.0.2
|
||||
resolution: "pinia@npm:3.0.2"
|
||||
dependencies:
|
||||
"@vue/devtools-api": "npm:^7.7.2"
|
||||
peerDependencies:
|
||||
typescript: ">=4.4.4"
|
||||
vue: ^2.7.0 || ^3.5.11
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 10c0/4c21412ddb32c48c1d9fb9fb47a2cd40bc4af9198e65392423ab97f6a9da31d0b880bc59b008967058643a988cb574025f885a1d0e4faf47bec25521933bb27f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pkg-types@npm:^1.3.0":
|
||||
version: 1.3.1
|
||||
resolution: "pkg-types@npm:1.3.1"
|
||||
@@ -1911,6 +2208,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pluralize@npm:^8.0.0":
|
||||
version: 8.0.0
|
||||
resolution: "pluralize@npm:8.0.0"
|
||||
checksum: 10c0/2044cfc34b2e8c88b73379ea4a36fc577db04f651c2909041b054c981cd863dd5373ebd030123ab058d194ae615d3a97cfdac653991e499d10caf592e8b3dc33
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"postcss@npm:^8.4.48, postcss@npm:^8.5.3":
|
||||
version: 8.5.3
|
||||
resolution: "postcss@npm:8.5.3"
|
||||
@@ -1985,6 +2289,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"require-from-string@npm:^2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "require-from-string@npm:2.0.2"
|
||||
checksum: 10c0/aaa267e0c5b022fc5fd4eef49d8285086b15f2a1c54b28240fdf03599cbd9c26049fee3eab894f2e1f6ca65e513b030a7c264201e3f005601e80c49fb2937ce2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"retry@npm:^0.12.0":
|
||||
version: 0.12.0
|
||||
resolution: "retry@npm:0.12.0"
|
||||
@@ -1999,6 +2310,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rfdc@npm:^1.4.1":
|
||||
version: 1.4.1
|
||||
resolution: "rfdc@npm:1.4.1"
|
||||
checksum: 10c0/4614e4292356cafade0b6031527eea9bc90f2372a22c012313be1dcc69a3b90c7338158b414539be863fa95bfcb2ddcd0587be696841af4e6679d85e62c060c7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"roboto-fontface@npm:^0.10.0":
|
||||
version: 0.10.0
|
||||
resolution: "roboto-fontface@npm:0.10.0"
|
||||
@@ -2094,9 +2412,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sass@npm:^1.86.0":
|
||||
version: 1.86.0
|
||||
resolution: "sass@npm:1.86.0"
|
||||
"sass@npm:^1.86.3":
|
||||
version: 1.86.3
|
||||
resolution: "sass@npm:1.86.3"
|
||||
dependencies:
|
||||
"@parcel/watcher": "npm:^2.4.1"
|
||||
chokidar: "npm:^4.0.0"
|
||||
@@ -2107,7 +2425,7 @@ __metadata:
|
||||
optional: true
|
||||
bin:
|
||||
sass: sass.js
|
||||
checksum: 10c0/921caea1fd8a450d4a986e5570ce13c4ca7b2a57da390811add3d2087ad8f46f53b34652ddcb237d8bdaad49c560b8d6eee130c733c787d058bc5a71a914c139
|
||||
checksum: 10c0/ba819a0828f732adf7a94cd8ca017bce92bc299ffb878836ed1da80a30612bfbbf56a5e42d6dff3ad80d919c2025afb42948fc7b54a7bc61a9a2d58e1e0c558a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2192,6 +2510,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"speakingurl@npm:^14.0.1":
|
||||
version: 14.0.1
|
||||
resolution: "speakingurl@npm:14.0.1"
|
||||
checksum: 10c0/1de1d1b938a7c4d9e79593ff7a26d312ec04a7c3234ca40b7f9b8106daf74ea9d2110a077f5db97ecf3762b83069e3ccbf9694431b51d4fcfd863f0b3333c342
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sprintf-js@npm:^1.1.3":
|
||||
version: 1.1.3
|
||||
resolution: "sprintf-js@npm:1.1.3"
|
||||
@@ -2248,6 +2573,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"superjson@npm:^2.2.1":
|
||||
version: 2.2.2
|
||||
resolution: "superjson@npm:2.2.2"
|
||||
dependencies:
|
||||
copy-anything: "npm:^3.0.2"
|
||||
checksum: 10c0/aa49ebe6653e963020bc6a1ed416d267dfda84cfcc3cbd3beffd75b72e44eb9df7327215f3e3e77528f6e19ad8895b16a4964fdcd56d1799d14350db8c92afbc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"supports-color@npm:^9.4.0":
|
||||
version: 9.4.0
|
||||
resolution: "supports-color@npm:9.4.0"
|
||||
checksum: 10c0/6c24e6b2b64c6a60e5248490cfa50de5924da32cf09ae357ad8ebbf305cc5d2717ba705a9d4cb397d80bbf39417e8fdc8d7a0ce18bd0041bf7b5b456229164e4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tar@npm:^6.1.11, tar@npm:^6.1.2":
|
||||
version: 6.2.1
|
||||
resolution: "tar@npm:6.2.1"
|
||||
@@ -2281,23 +2622,30 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@npm:^5.8.2":
|
||||
version: 5.8.2
|
||||
resolution: "typescript@npm:5.8.2"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 10c0/5c4f6fbf1c6389b6928fe7b8fcd5dc73bb2d58cd4e3883f1d774ed5bd83b151cbac6b7ecf11723de56d4676daeba8713894b1e9af56174f2f9780ae7848ec3c6
|
||||
"type-fest@npm:^4.39.1":
|
||||
version: 4.39.1
|
||||
resolution: "type-fest@npm:4.39.1"
|
||||
checksum: 10c0/f5bf302eb2e2f70658be1757aa578f4a09da3f65699b0b12b7ae5502ccea76e5124521a6e6b69540f442c3dc924c394202a2ab58718d0582725c7ac23c072594
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A^5.8.2#optional!builtin<compat/typescript>":
|
||||
version: 5.8.2
|
||||
resolution: "typescript@patch:typescript@npm%3A5.8.2#optional!builtin<compat/typescript>::version=5.8.2&hash=5786d5"
|
||||
"typescript@npm:^5.8.3":
|
||||
version: 5.8.3
|
||||
resolution: "typescript@npm:5.8.3"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 10c0/5448a08e595cc558ab321e49d4cac64fb43d1fa106584f6ff9a8d8e592111b373a995a1d5c7f3046211c8a37201eb6d0f1566f15cdb7a62a5e3be01d087848e2
|
||||
checksum: 10c0/5f8bb01196e542e64d44db3d16ee0e4063ce4f3e3966df6005f2588e86d91c03e1fb131c2581baf0fb65ee79669eea6e161cd448178986587e9f6844446dbb48
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A^5.8.3#optional!builtin<compat/typescript>":
|
||||
version: 5.8.3
|
||||
resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin<compat/typescript>::version=5.8.3&hash=5786d5"
|
||||
bin:
|
||||
tsc: bin/tsc
|
||||
tsserver: bin/tsserver
|
||||
checksum: 10c0/39117e346ff8ebd87ae1510b3a77d5d92dae5a89bde588c747d25da5c146603a99c8ee588c7ef80faaf123d89ed46f6dbd918d534d641083177d5fac38b8a1cb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2308,10 +2656,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"undici-types@npm:~6.20.0":
|
||||
version: 6.20.0
|
||||
resolution: "undici-types@npm:6.20.0"
|
||||
checksum: 10c0/68e659a98898d6a836a9a59e6adf14a5d799707f5ea629433e025ac90d239f75e408e2e5ff086afc3cace26f8b26ee52155293564593fbb4a2f666af57fc59bf
|
||||
"undici-types@npm:~6.21.0":
|
||||
version: 6.21.0
|
||||
resolution: "undici-types@npm:6.21.0"
|
||||
checksum: 10c0/c01ed51829b10aa72fc3ce64b747f8e74ae9b60eafa19a7b46ef624403508a54c526ffab06a14a26b3120d055e1104d7abe7c9017e83ced038ea5cf52f8d5e04
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2359,17 +2707,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unplugin-vue-components@npm:^28.4.1":
|
||||
version: 28.4.1
|
||||
resolution: "unplugin-vue-components@npm:28.4.1"
|
||||
"unplugin-vue-components@npm:^28.5.0":
|
||||
version: 28.5.0
|
||||
resolution: "unplugin-vue-components@npm:28.5.0"
|
||||
dependencies:
|
||||
chokidar: "npm:^3.6.0"
|
||||
debug: "npm:^4.4.0"
|
||||
local-pkg: "npm:^1.0.0"
|
||||
local-pkg: "npm:^1.1.1"
|
||||
magic-string: "npm:^0.30.17"
|
||||
mlly: "npm:^1.7.4"
|
||||
tinyglobby: "npm:^0.2.12"
|
||||
unplugin: "npm:^2.2.0"
|
||||
unplugin: "npm:^2.3.2"
|
||||
unplugin-utils: "npm:^0.2.4"
|
||||
peerDependencies:
|
||||
"@babel/parser": ^7.15.8
|
||||
@@ -2380,7 +2728,7 @@ __metadata:
|
||||
optional: true
|
||||
"@nuxt/kit":
|
||||
optional: true
|
||||
checksum: 10c0/f05448285e6d049b8aeadf5747cf7cda23105bfe8691326217abf3a5aa924768279f1c26f37ed0cd98c00f97ea7ce1cd5d5ed2916fb09f2b817f25563ece825a
|
||||
checksum: 10c0/4a2419cee6a8d19e0dd121fa56afef29c981434ee4f632e972e46aec52f161608c85b0806737308c597ca6d19b07d62f654f4070bd4302c1691a1c865acb9248
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2394,13 +2742,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unplugin@npm:^2.2.0":
|
||||
version: 2.2.2
|
||||
resolution: "unplugin@npm:2.2.2"
|
||||
"unplugin@npm:^2.3.2":
|
||||
version: 2.3.2
|
||||
resolution: "unplugin@npm:2.3.2"
|
||||
dependencies:
|
||||
acorn: "npm:^8.14.1"
|
||||
picomatch: "npm:^4.0.2"
|
||||
webpack-virtual-modules: "npm:^0.6.2"
|
||||
checksum: 10c0/76ba320f0c5d18c31c6efab0bcf1f487e900193da7d9a63d50ccb87ea3c50bc9952111caee4ec5017bdcb53445dce275b994c6aeca6b92567db283ec5d9fc01b
|
||||
checksum: 10c0/157a50072601b9bfbf3ab27a76a04685fb0af0c1a579d958787ffcb28a4d64e09acf42f0176e8767ccd940f27ee52d97a7f6aa6ce2e1e0dbe666ec26519750ef
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2411,9 +2760,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vite-plugin-vuetify@npm:^2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "vite-plugin-vuetify@npm:2.1.0"
|
||||
"uri-js-replace@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "uri-js-replace@npm:1.0.1"
|
||||
checksum: 10c0/0be6c972c84c316e29667628ce7b4ce4de7fc77cec9a514f70c4a3336eea8d1d783c71c9988ac5da333f0f6a85a04a7ae05a3c4aa43af6cd07b7a4d85c8d9f11
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vite-plugin-vuetify@npm:^2.1.1":
|
||||
version: 2.1.1
|
||||
resolution: "vite-plugin-vuetify@npm:2.1.1"
|
||||
dependencies:
|
||||
"@vuetify/loader-shared": "npm:^2.1.0"
|
||||
debug: "npm:^4.3.3"
|
||||
@@ -2422,13 +2778,13 @@ __metadata:
|
||||
vite: ">=5"
|
||||
vue: ^3.0.0
|
||||
vuetify: ^3.0.0
|
||||
checksum: 10c0/c9b6b3ee4b75ffc9b1f124f8f635d372f3258bd6f2abb48db42a80a4efe54127c9e325ad12eb92278ddbd629dfd1111810ec2bd6b1fb076f0724b789f33054e7
|
||||
checksum: 10c0/629893488ae23ffd9e9a32fccf2d6ff4d5a00826329ec90e9765a17d182a9200ffe11430bd418227119e8ef3ed21eaec1bab0635a77fdcb4b64aac10f38adcb0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vite@npm:^6.2.2":
|
||||
version: 6.2.2
|
||||
resolution: "vite@npm:6.2.2"
|
||||
"vite@npm:^6.2.6":
|
||||
version: 6.2.6
|
||||
resolution: "vite@npm:6.2.6"
|
||||
dependencies:
|
||||
esbuild: "npm:^0.25.0"
|
||||
fsevents: "npm:~2.3.3"
|
||||
@@ -2474,7 +2830,7 @@ __metadata:
|
||||
optional: true
|
||||
bin:
|
||||
vite: bin/vite.js
|
||||
checksum: 10c0/52f5b1c10cfe5e3b6382c6de1811ebbf76df9b5a8bab3d65169446c6b54a5f1528f775b1548009a6d8aad11def20fba046bb3e9abb10c0c2c9ccd78118623bb8
|
||||
checksum: 10c0/68a2ed3e61bdd654c59b817b4f3203065241c66d1739faa707499130f3007bc3a666c7a8320a4198e275e62b5e4d34d9b78a6533f69e321d366e76f5093b2071
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2517,14 +2873,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vuetify@npm:^3.7.18":
|
||||
version: 3.7.18
|
||||
resolution: "vuetify@npm:3.7.18"
|
||||
"vuetify@npm:^3.8.1":
|
||||
version: 3.8.1
|
||||
resolution: "vuetify@npm:3.8.1"
|
||||
peerDependencies:
|
||||
typescript: ">=4.7"
|
||||
vite-plugin-vuetify: ">=1.0.0"
|
||||
vue: ^3.3.0
|
||||
webpack-plugin-vuetify: ">=2.0.0"
|
||||
vite-plugin-vuetify: ">=2.1.0"
|
||||
vue: ^3.5.0
|
||||
webpack-plugin-vuetify: ">=3.1.0"
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
@@ -2532,7 +2888,7 @@ __metadata:
|
||||
optional: true
|
||||
webpack-plugin-vuetify:
|
||||
optional: true
|
||||
checksum: 10c0/98686640dc11bb59e12fdb214e0fc8b2a4ecd2f8286448fddb6abecd858a0fd5db5927d443e9b3be7ff92303ae1c8bc01bf4712278a9b6e4f4d72358a36e0a0e
|
||||
checksum: 10c0/b6fd1a96325b16a1f88acd1ef9d385118c09f25793bc7eddc3da2fe57e84a17d200d77dc14a2e0bc1b67fb6f301ce15b760185d2faafeaf61c584a92df6b0b45
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2593,3 +2949,17 @@ __metadata:
|
||||
checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yaml-ast-parser@npm:0.0.43":
|
||||
version: 0.0.43
|
||||
resolution: "yaml-ast-parser@npm:0.0.43"
|
||||
checksum: 10c0/4d2f1e761067b2c6abdd882279a406f879258787af470a6d4a659cb79cb2ab056b870b25f1f80f46ed556e8b499d611d247806376f53edf3412f72c0a8ea2e98
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yargs-parser@npm:^21.1.1":
|
||||
version: 21.1.1
|
||||
resolution: "yargs-parser@npm:21.1.1"
|
||||
checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
10
go.mod
10
go.mod
@@ -39,10 +39,10 @@ require (
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/zclconf/go-cty v1.16.2 // indirect
|
||||
github.com/zclconf/go-cty-yaml v1.1.0 // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/crypto v0.37.0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
golang.org/x/tools v0.31.0 // indirect
|
||||
golang.org/x/sync v0.13.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/tools v0.32.0 // indirect
|
||||
)
|
||||
|
20
go.sum
20
go.sum
@@ -191,8 +191,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
@@ -212,8 +212,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -232,8 +232,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -249,8 +249,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
@@ -262,8 +262,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@@ -224,6 +224,16 @@ components:
|
||||
format: int64
|
||||
description: Number of packages currently in the build queue
|
||||
example: 5
|
||||
building:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Number of packages currently building
|
||||
example: 11
|
||||
last_mirror_timestamp:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Latest mirror timestamp to detect outdated mirrors (Unix timestamp)
|
||||
example: 1702612991
|
||||
lto:
|
||||
type: object
|
||||
description: LTO status summary across all packages
|
||||
|
Reference in New Issue
Block a user