Compare commits

...

23 Commits

Author SHA1 Message Date
Amir Raminfar 701f16fcc2 chore: release v5.2.0 2023-10-31 12:33:12 -07:00
Amir Raminfar 49d53ce255 chore(docs): updates gh pages to have simple auth 2023-10-31 12:30:39 -07:00
Amir Raminfar e57d038221 fix: changes mime type for fetching between to application/x-jsonl. see #2458 (#2461) 2023-10-31 11:22:27 -07:00
Amir Raminfar c74384d012 fix: fixes blank name for proxy mode 2023-10-31 11:15:50 -07:00
Amir Raminfar 5a068133bf fix: fixes forward proxy bug not working (#2460) 2023-10-30 22:42:40 +00:00
Amir Raminfar e85a4aefa2 feat: adds support for user.yml from disk (#2455) 2023-10-30 12:20:00 -07:00
Amir Raminfar b0e43333d2 chore: release v5.1.2 2023-10-30 08:20:25 -07:00
renovate[bot] d2c71e2dc9 fix(deps): update dependency vue-i18n to ^9.6.2 (#2459)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-30 03:56:24 +00:00
renovate[bot] 7fdaa3e4f0 chore(deps): update actions/setup-node action to v4 (#2457)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-29 18:50:14 -07:00
renovate[bot] 0344e2adb4 chore(deps): update actions/checkout action to v4 (#2456)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-29 18:49:54 -07:00
Amir Raminfar 7431c3455f chore(docs): enables gh pages 2023-10-27 13:00:51 -07:00
Amir Raminfar 1fe46e605a feat: syncs settings to disk for authenticated users (#2445) 2023-10-27 12:53:42 -07:00
renovate[bot] e4d1a18d37 fix(deps): update all non-major dependencies (#2453)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-27 19:44:15 +00:00
Amir Raminfar a0a2b7175c chore: release v5.1.1 2023-10-27 11:22:01 -07:00
Amir Raminfar b88fc3c5d1 feat: makes hour time format always 2 digits (#2452) 2023-10-27 09:46:04 -07:00
Amir Raminfar a8bc1dd4c2 chore: reverts netlify changes 2023-10-26 13:45:09 -07:00
Amir Raminfar 29fcb53fac chore: uses removes store 2023-10-26 13:34:38 -07:00
Amir Raminfar 4dfd57612d chore: rollback pnpm changes 2023-10-26 11:28:43 -07:00
Amir Raminfar 51b9ad5f00 chore: tries to clear pnpm store prune again 2023-10-26 10:29:21 -07:00
Amir Raminfar f4b53fd09d chore: tries to clear pnpm store prune 2023-10-26 10:28:49 -07:00
renovate[bot] 5d5628530b fix(deps): update dependency fuse.js to v7 (#2447)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-26 09:47:36 -07:00
Amir Raminfar 4d0904bb2c chore: cleans pnpm 2023-10-26 09:41:27 -07:00
renovate[bot] 13ebc06812 fix(deps): update all non-major dependencies (#2446)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-25 22:09:14 +00:00
36 changed files with 1550 additions and 1130 deletions
+62
View File
@@ -0,0 +1,62 @@
# Sample workflow for building and deploying a VitePress site to GitHub Pages
#
name: Deploy VitePress site to Pages
on:
push:
branches: [master]
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: pages
cancel-in-progress: false
jobs:
# Build job
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # Not needed if lastUpdated is not enabled
- uses: pnpm/action-setup@v2
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: latest
cache: pnpm # or pnpm / yarn
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Install dependencies
run: pnpm install
- name: Build with VitePress
run: |
pnpm docs:build
touch docs/.vitepress/dist/.nojekyll
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
with:
path: docs/.vitepress/dist
# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
needs: build
runs-on: ubuntu-latest
name: Deploy
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
+1
View File
@@ -1,4 +1,5 @@
certs
data
dist
node_modules
.cache
+46 -43
View File
@@ -12,14 +12,14 @@ declare global {
const $ref: typeof import('vue/macros')['$ref']
const $shallowRef: typeof import('vue/macros')['$shallowRef']
const $toRef: typeof import('vue/macros')['$toRef']
const DEFAULT_SETTINGS: typeof import('./composables/settings')['DEFAULT_SETTINGS']
const DEFAULT_SETTINGS: typeof import('./stores/settings')['DEFAULT_SETTINGS']
const EffectScope: typeof import('vue')['EffectScope']
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
const arrayEquals: typeof import('./utils/index')['arrayEquals']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const automaticRedirect: typeof import('./composables/settings')['automaticRedirect']
const collapseNav: typeof import('./composables/settings')['collapseNav']
const automaticRedirect: typeof import('./stores/settings')['automaticRedirect']
const collapseNav: typeof import('./stores/settings')['collapseNav']
const computed: typeof import('vue')['computed']
const computedAsync: typeof import('@vueuse/core')['computedAsync']
const computedEager: typeof import('@vueuse/core')['computedEager']
@@ -58,7 +58,7 @@ declare global {
const getDeep: typeof import('./utils/index')['getDeep']
const globalShowPopup: typeof import('./composables/popup')['globalShowPopup']
const h: typeof import('vue')['h']
const hourStyle: typeof import('./composables/settings')['hourStyle']
const hourStyle: typeof import('./stores/settings')['hourStyle']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const injectLocal: typeof import('@vueuse/core')['injectLocal']
@@ -69,7 +69,7 @@ declare global {
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const lightTheme: typeof import('./composables/settings')['lightTheme']
const lightTheme: typeof import('./stores/settings')['lightTheme']
const logicAnd: typeof import('@vueuse/math')['logicAnd']
const logicNot: typeof import('@vueuse/math')['logicNot']
const logicOr: typeof import('@vueuse/math')['logicOr']
@@ -80,7 +80,7 @@ declare global {
const mapStores: typeof import('pinia')['mapStores']
const mapWritableState: typeof import('pinia')['mapWritableState']
const markRaw: typeof import('vue')['markRaw']
const menuWidth: typeof import('./composables/settings')['menuWidth']
const menuWidth: typeof import('./stores/settings')['menuWidth']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
@@ -123,21 +123,21 @@ declare global {
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const search: typeof import('./composables/settings')['search']
const search: typeof import('./stores/settings')['search']
const sessionHost: typeof import('./composables/storage')['sessionHost']
const setActivePinia: typeof import('pinia')['setActivePinia']
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
const setTitle: typeof import('./composables/title')['setTitle']
const settings: typeof import('./composables/settings')['settings']
const settings: typeof import('./stores/settings')['settings']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const showAllContainers: typeof import('./composables/settings')['showAllContainers']
const showStd: typeof import('./composables/settings')['showStd']
const showTimestamp: typeof import('./composables/settings')['showTimestamp']
const size: typeof import('./composables/settings')['size']
const smallerScrollbars: typeof import('./composables/settings')['smallerScrollbars']
const softWrap: typeof import('./composables/settings')['softWrap']
const showAllContainers: typeof import('./stores/settings')['showAllContainers']
const showStd: typeof import('./stores/settings')['showStd']
const showTimestamp: typeof import('./stores/settings')['showTimestamp']
const size: typeof import('./stores/settings')['size']
const smallerScrollbars: typeof import('./stores/settings')['smallerScrollbars']
const softWrap: typeof import('./stores/settings')['softWrap']
const storeToRefs: typeof import('pinia')['storeToRefs']
const stripVersion: typeof import('./utils/index')['stripVersion']
const syncRef: typeof import('@vueuse/core')['syncRef']
@@ -358,11 +358,12 @@ declare global {
const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
const withBase: typeof import('./stores/config')['withBase']
}
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, InjectionKey, PropType, Ref, VNode } from 'vue'
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
}
// for vue template auto import
import { UnwrapRef } from 'vue'
@@ -375,14 +376,14 @@ declare module 'vue' {
readonly $ref: UnwrapRef<typeof import('vue/macros')['$ref']>
readonly $shallowRef: UnwrapRef<typeof import('vue/macros')['$shallowRef']>
readonly $toRef: UnwrapRef<typeof import('vue/macros')['$toRef']>
readonly DEFAULT_SETTINGS: UnwrapRef<typeof import('./composables/settings')['DEFAULT_SETTINGS']>
readonly DEFAULT_SETTINGS: UnwrapRef<typeof import('./stores/settings')['DEFAULT_SETTINGS']>
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
readonly arrayEquals: UnwrapRef<typeof import('./utils/index')['arrayEquals']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
readonly automaticRedirect: UnwrapRef<typeof import('./composables/settings')['automaticRedirect']>
readonly collapseNav: UnwrapRef<typeof import('./composables/settings')['collapseNav']>
readonly automaticRedirect: UnwrapRef<typeof import('./stores/settings')['automaticRedirect']>
readonly collapseNav: UnwrapRef<typeof import('./stores/settings')['collapseNav']>
readonly computed: UnwrapRef<typeof import('vue')['computed']>
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']>
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']>
@@ -419,7 +420,7 @@ declare module 'vue' {
readonly getDeep: UnwrapRef<typeof import('./utils/index')['getDeep']>
readonly globalShowPopup: UnwrapRef<typeof import('./composables/popup')['globalShowPopup']>
readonly h: UnwrapRef<typeof import('vue')['h']>
readonly hourStyle: UnwrapRef<typeof import('./composables/settings')['hourStyle']>
readonly hourStyle: UnwrapRef<typeof import('./stores/settings')['hourStyle']>
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
readonly inject: UnwrapRef<typeof import('vue')['inject']>
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
@@ -430,7 +431,7 @@ declare module 'vue' {
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
readonly lightTheme: UnwrapRef<typeof import('./composables/settings')['lightTheme']>
readonly lightTheme: UnwrapRef<typeof import('./stores/settings')['lightTheme']>
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
readonly mapActions: UnwrapRef<typeof import('pinia')['mapActions']>
readonly mapGetters: UnwrapRef<typeof import('pinia')['mapGetters']>
@@ -438,7 +439,7 @@ declare module 'vue' {
readonly mapStores: UnwrapRef<typeof import('pinia')['mapStores']>
readonly mapWritableState: UnwrapRef<typeof import('pinia')['mapWritableState']>
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
readonly menuWidth: UnwrapRef<typeof import('./composables/settings')['menuWidth']>
readonly menuWidth: UnwrapRef<typeof import('./stores/settings')['menuWidth']>
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
@@ -481,21 +482,21 @@ declare module 'vue' {
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
readonly search: UnwrapRef<typeof import('./composables/settings')['search']>
readonly search: UnwrapRef<typeof import('./stores/settings')['search']>
readonly sessionHost: UnwrapRef<typeof import('./composables/storage')['sessionHost']>
readonly setActivePinia: UnwrapRef<typeof import('pinia')['setActivePinia']>
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
readonly setTitle: UnwrapRef<typeof import('./composables/title')['setTitle']>
readonly settings: UnwrapRef<typeof import('./composables/settings')['settings']>
readonly settings: UnwrapRef<typeof import('./stores/settings')['settings']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
readonly showAllContainers: UnwrapRef<typeof import('./composables/settings')['showAllContainers']>
readonly showStd: UnwrapRef<typeof import('./composables/settings')['showStd']>
readonly showTimestamp: UnwrapRef<typeof import('./composables/settings')['showTimestamp']>
readonly size: UnwrapRef<typeof import('./composables/settings')['size']>
readonly smallerScrollbars: UnwrapRef<typeof import('./composables/settings')['smallerScrollbars']>
readonly softWrap: UnwrapRef<typeof import('./composables/settings')['softWrap']>
readonly showAllContainers: UnwrapRef<typeof import('./stores/settings')['showAllContainers']>
readonly showStd: UnwrapRef<typeof import('./stores/settings')['showStd']>
readonly showTimestamp: UnwrapRef<typeof import('./stores/settings')['showTimestamp']>
readonly size: UnwrapRef<typeof import('./stores/settings')['size']>
readonly smallerScrollbars: UnwrapRef<typeof import('./stores/settings')['smallerScrollbars']>
readonly softWrap: UnwrapRef<typeof import('./stores/settings')['softWrap']>
readonly storeToRefs: UnwrapRef<typeof import('pinia')['storeToRefs']>
readonly stripVersion: UnwrapRef<typeof import('./utils/index')['stripVersion']>
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
@@ -703,6 +704,7 @@ declare module 'vue' {
readonly watchTriggerable: UnwrapRef<typeof import('@vueuse/core')['watchTriggerable']>
readonly watchWithFilter: UnwrapRef<typeof import('@vueuse/core')['watchWithFilter']>
readonly whenever: UnwrapRef<typeof import('@vueuse/core')['whenever']>
readonly withBase: UnwrapRef<typeof import('./stores/config')['withBase']>
}
}
declare module '@vue/runtime-core' {
@@ -714,14 +716,14 @@ declare module '@vue/runtime-core' {
readonly $ref: UnwrapRef<typeof import('vue/macros')['$ref']>
readonly $shallowRef: UnwrapRef<typeof import('vue/macros')['$shallowRef']>
readonly $toRef: UnwrapRef<typeof import('vue/macros')['$toRef']>
readonly DEFAULT_SETTINGS: UnwrapRef<typeof import('./composables/settings')['DEFAULT_SETTINGS']>
readonly DEFAULT_SETTINGS: UnwrapRef<typeof import('./stores/settings')['DEFAULT_SETTINGS']>
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
readonly arrayEquals: UnwrapRef<typeof import('./utils/index')['arrayEquals']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
readonly automaticRedirect: UnwrapRef<typeof import('./composables/settings')['automaticRedirect']>
readonly collapseNav: UnwrapRef<typeof import('./composables/settings')['collapseNav']>
readonly automaticRedirect: UnwrapRef<typeof import('./stores/settings')['automaticRedirect']>
readonly collapseNav: UnwrapRef<typeof import('./stores/settings')['collapseNav']>
readonly computed: UnwrapRef<typeof import('vue')['computed']>
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']>
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']>
@@ -758,7 +760,7 @@ declare module '@vue/runtime-core' {
readonly getDeep: UnwrapRef<typeof import('./utils/index')['getDeep']>
readonly globalShowPopup: UnwrapRef<typeof import('./composables/popup')['globalShowPopup']>
readonly h: UnwrapRef<typeof import('vue')['h']>
readonly hourStyle: UnwrapRef<typeof import('./composables/settings')['hourStyle']>
readonly hourStyle: UnwrapRef<typeof import('./stores/settings')['hourStyle']>
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
readonly inject: UnwrapRef<typeof import('vue')['inject']>
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
@@ -769,7 +771,7 @@ declare module '@vue/runtime-core' {
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
readonly lightTheme: UnwrapRef<typeof import('./composables/settings')['lightTheme']>
readonly lightTheme: UnwrapRef<typeof import('./stores/settings')['lightTheme']>
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
readonly mapActions: UnwrapRef<typeof import('pinia')['mapActions']>
readonly mapGetters: UnwrapRef<typeof import('pinia')['mapGetters']>
@@ -777,7 +779,7 @@ declare module '@vue/runtime-core' {
readonly mapStores: UnwrapRef<typeof import('pinia')['mapStores']>
readonly mapWritableState: UnwrapRef<typeof import('pinia')['mapWritableState']>
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
readonly menuWidth: UnwrapRef<typeof import('./composables/settings')['menuWidth']>
readonly menuWidth: UnwrapRef<typeof import('./stores/settings')['menuWidth']>
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
@@ -820,21 +822,21 @@ declare module '@vue/runtime-core' {
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
readonly search: UnwrapRef<typeof import('./composables/settings')['search']>
readonly search: UnwrapRef<typeof import('./stores/settings')['search']>
readonly sessionHost: UnwrapRef<typeof import('./composables/storage')['sessionHost']>
readonly setActivePinia: UnwrapRef<typeof import('pinia')['setActivePinia']>
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
readonly setTitle: UnwrapRef<typeof import('./composables/title')['setTitle']>
readonly settings: UnwrapRef<typeof import('./composables/settings')['settings']>
readonly settings: UnwrapRef<typeof import('./stores/settings')['settings']>
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
readonly showAllContainers: UnwrapRef<typeof import('./composables/settings')['showAllContainers']>
readonly showStd: UnwrapRef<typeof import('./composables/settings')['showStd']>
readonly showTimestamp: UnwrapRef<typeof import('./composables/settings')['showTimestamp']>
readonly size: UnwrapRef<typeof import('./composables/settings')['size']>
readonly smallerScrollbars: UnwrapRef<typeof import('./composables/settings')['smallerScrollbars']>
readonly softWrap: UnwrapRef<typeof import('./composables/settings')['softWrap']>
readonly showAllContainers: UnwrapRef<typeof import('./stores/settings')['showAllContainers']>
readonly showStd: UnwrapRef<typeof import('./stores/settings')['showStd']>
readonly showTimestamp: UnwrapRef<typeof import('./stores/settings')['showTimestamp']>
readonly size: UnwrapRef<typeof import('./stores/settings')['size']>
readonly smallerScrollbars: UnwrapRef<typeof import('./stores/settings')['smallerScrollbars']>
readonly softWrap: UnwrapRef<typeof import('./stores/settings')['softWrap']>
readonly storeToRefs: UnwrapRef<typeof import('pinia')['storeToRefs']>
readonly stripVersion: UnwrapRef<typeof import('./utils/index')['stripVersion']>
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
@@ -1042,5 +1044,6 @@ declare module '@vue/runtime-core' {
readonly watchTriggerable: UnwrapRef<typeof import('@vueuse/core')['watchTriggerable']>
readonly watchWithFilter: UnwrapRef<typeof import('@vueuse/core')['watchWithFilter']>
readonly whenever: UnwrapRef<typeof import('@vueuse/core')['whenever']>
readonly withBase: UnwrapRef<typeof import('./stores/config')['withBase']>
}
}
@@ -4,7 +4,7 @@ import { createTestingPinia } from "@pinia/testing";
import EventSource, { sources } from "eventsourcemock";
import LogEventSource from "./LogEventSource.vue";
import LogViewer from "./LogViewer.vue";
import { settings } from "@/composables/settings";
import { settings } from "@/stores/settings";
import { useSearchFilter } from "@/composables/search";
import { vi, describe, expect, beforeEach, test, afterEach } from "vitest";
import { computed, nextTick } from "vue";
@@ -14,6 +14,7 @@ import { containerContext } from "@/composables/containerContext";
vi.mock("@/stores/config", () => ({
__esModule: true,
default: { base: "", hosts: [{ name: "localhost", id: "localhost" }] },
withBase: (path: string) => path,
}));
/**
+1 -1
View File
@@ -14,7 +14,7 @@ const dateFormatter = new Intl.DateTimeFormat(undefined, { day: "2-digit", month
const use12Hour = $computed(() => ({ auto: undefined, "12": true, "24": false })[hourStyle.value]);
const timeFormatter = $computed(
() =>
new Intl.DateTimeFormat(undefined, { hour: "numeric", minute: "2-digit", second: "2-digit", hour12: use12Hour }),
new Intl.DateTimeFormat(undefined, { hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: use12Hour }),
);
const dateStr = $computed(() => dateFormatter.format(props.date));
+2 -2
View File
@@ -85,7 +85,7 @@ export function useLogStream() {
console.debug(`Connecting to ${containerId} with params`, params);
es = new EventSource(
`${config.base}/api/logs/stream/${container.value.host}/${containerId}?${new URLSearchParams(params).toString()}`,
withBase(`/api/logs/stream/${container.value.host}/${containerId}?${new URLSearchParams(params).toString()}`),
);
es.addEventListener("container-stopped", () => {
close();
@@ -118,7 +118,7 @@ export function useLogStream() {
const logs = await (
await fetch(
`${config.base}/api/logs/${container.value.host}/${containerId}?${new URLSearchParams(params).toString()}`,
withBase(`/api/logs/${container.value.host}/${containerId}?${new URLSearchParams(params).toString()}`),
)
).text();
if (logs) {
+1 -1
View File
@@ -65,7 +65,7 @@
<script lang="ts" setup>
// @ts-ignore - splitpanes types are not available
import { Splitpanes, Pane } from "splitpanes";
import { collapseNav } from "@/composables/settings";
import { collapseNav } from "@/stores/settings";
const { authorizationNeeded } = config;
const containerStore = useContainerStore();
+1 -2
View File
@@ -2,13 +2,12 @@ import { type App } from "vue";
import { createRouter, createWebHistory } from "vue-router";
import pages from "~pages";
import { setupLayouts } from "virtual:generated-layouts";
import config from "@/stores/config";
export const install = (app: App) => {
const routes = setupLayouts(pages);
const router = createRouter({
history: createWebHistory(`${config.base}/`),
history: createWebHistory(withBase("/")),
routes,
});
+14 -3
View File
@@ -1,9 +1,12 @@
<template>
<div class="flex flex-col gap-16 px-4 pt-8 md:px-8">
<section v-if="config.user">
<div class="flex items-center gap-4">
<div class="ml-auto">
{{ config.user?.email }}
<div class="flex items-center justify-end gap-4">
<div v-if="config.authProvider === 'simple'">
<button @click.prevent="logout()" class="link-primary">{{ $t("button.logout") }}</button>
</div>
<div>
{{ config.user.name ? config.user.name : config.user.email }}
</div>
<img class="h-10 w-10 rounded-full p-1 ring-2 ring-base-content/50" :src="config.user.avatar" />
</div>
@@ -73,6 +76,14 @@ watchEffect(() => {
setTitle(t("title.dashboard", { count: runningContainers.length }));
}
});
async function logout() {
await fetch(withBase("/api/token"), {
method: "DELETE",
});
location.reload();
}
</script>
<style lang="postcss" scoped>
:deep(tr td) {
+4 -3
View File
@@ -49,14 +49,15 @@ let password = $ref("");
let form: HTMLFormElement | undefined = $ref();
async function onLogin() {
const response = await fetch(`${config.base}/api/validateCredentials`, {
const url = config.authProvider === "simple" ? "/api/token" : "/api/validateCredentials";
const response = await fetch(withBase(url), {
body: new FormData(form),
method: "post",
method: "POST",
});
if (response.status == 200) {
error = false;
window.location.href = `${config.base}/`;
window.location.href = withBase("/");
} else {
error = true;
}
+1 -1
View File
@@ -100,7 +100,7 @@ import {
size,
softWrap,
automaticRedirect,
} from "@/composables/settings";
} from "@/stores/settings";
const { t } = useI18n();
+7 -1
View File
@@ -1,3 +1,5 @@
import { type Settings } from "@/stores/settings";
const text = document.querySelector("script#config__json")?.textContent || "{}";
interface Config {
@@ -8,12 +10,14 @@ interface Config {
maxLogs: number;
hostname: string;
hosts: { name: string; id: string }[];
authProvider: "simple" | "none" | "forward-proxy";
user?: {
username: string;
email: string;
name: string;
avatar: string;
};
serverSettings?: Settings;
}
const pageConfig = JSON.parse(text);
@@ -25,4 +29,6 @@ const config: Config = {
config.version = config.version.replace(/^v/, "");
export default config;
export default Object.freeze(config);
export const withBase = (path: string) => `${config.base}${path}`;
+1 -1
View File
@@ -34,7 +34,7 @@ export const useContainerStore = defineStore("container", () => {
function connect() {
es?.close();
ready.value = false;
es = new EventSource(`${config.base}/api/events/stream`);
es = new EventSource(withBase("/api/events/stream"));
es.addEventListener("error", (e) => {
if (es?.readyState === EventSource.CLOSED) {
showToast(
@@ -1,7 +1,7 @@
import { toRefs } from "@vueuse/core";
const DOZZLE_SETTINGS_KEY = "DOZZLE_SETTINGS";
export const DEFAULT_SETTINGS: {
export type Settings = {
search: boolean;
size: "small" | "medium" | "large";
menuWidth: number;
@@ -14,7 +14,8 @@ export const DEFAULT_SETTINGS: {
softWrap: boolean;
collapseNav: boolean;
automaticRedirect: boolean;
} = {
};
export const DEFAULT_SETTINGS: Settings = {
search: true,
size: "medium",
menuWidth: 15,
@@ -30,7 +31,14 @@ export const DEFAULT_SETTINGS: {
};
export const settings = useStorage(DOZZLE_SETTINGS_KEY, DEFAULT_SETTINGS);
settings.value = { ...DEFAULT_SETTINGS, ...settings.value };
settings.value = { ...DEFAULT_SETTINGS, ...settings.value, ...config.serverSettings };
watch(settings, (value) => {
fetch(withBase("/api/profile/settings"), {
method: "PUT",
body: JSON.stringify(value),
});
});
export const {
collapseNav,
+43 -4
View File
@@ -4,7 +4,9 @@ title: Authentication
# Setting Up Authentication
Dozzle support two models of authentication. If you have already setup authentication behind a proxy then Dozzle can work out of the box by reading forwarded headers. If you do not currently have an authentication solution then Dozzle has a simple file based user management solution. Authentication providers are setup using `--auth-provider` flag.
Dozzle support two configurations for authentication. In the first configuration, you bring your own authentication method by protecting Dozzle through a proxy. Dozzle can read appropriate headers out of the box.
If you do not have an authentication solution then Dozzle has a simple file based user management solution. Authentication providers are setup using `--auth-provider` flag. In both of these configurations, Dozzle will try to save user settings to disk. This data is written to `/data`.
## Forward Proxy
@@ -178,14 +180,51 @@ Valid SSL keys are required because Authelia only supports SSL.
## File Based User Management
::: info
More details coming soon.
Dozzle supports multi-user authentication by setting `--auth-provider` to `simple`. In this mode, Dozzle will try to read `/data/users.yml`. The content of the file looks like
```yml
users:
admin:
name: "Admin"
# Just sha-256 which can be computed with echo -n password | shasum -a 256
password: "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"
email: me@email.net
```
Dozzle uses `email` to generate avatars using [Gravatar](https://gravatar.com/). It is optional.
The password is hashed using `sha256` which can be generated with `echo -n "secret-password" | shasum -a 256` or `echo -n "secret-password" | sha256sum` on linux.
You will need to mount this file for Dozzle to find it. Here is an example:
::: code-group
```sh [cli]
$ docker run -v /var/run/docker.sock:/var/run/docker.sock -v /path/to/dozzle/data:/data -p 8080:8080 amir20/dozzle --auth-provider simple
```
```yaml [docker-compose.yml]
version: "3"
services:
dozzle:
image: amir20/dozzle:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /path/to/dozzle/data:/data
ports:
- 8080:8080
environment:
DOZZLE_AUTH_PROVIDER: simple
```
:::
Dozzle uses [JWT](https://en.wikipedia.org/wiki/JSON_Web_Token) to generate tokens for authentication. This token is saved in a cookie.
## Single Username/Password
::: danger
This authentication method will be removed in v6.x in favor of a file based solution currently in development.
`--username` and `--passowrd` flags will be removed in v6.x in favor of `--auth-provider`.
:::
Dozzle supports a very simple authentication out of the box with just username and password. You should deploy using SSL to keep the credentials safe. See configuration to use `--username` and `--password`. You can also use docker secrets `--usernamefile` and `--passwordfile`.
+4 -4
View File
@@ -4,11 +4,11 @@
"name": "docs",
"devDependencies": {
"@netlify/functions": "^2.3.0",
"@unocss/preset-typography": "^0.56.5",
"@unocss/reset": "^0.56.5",
"@unocss/transformer-directives": "^0.56.5",
"@unocss/preset-typography": "^0.57.1",
"@unocss/reset": "^0.57.1",
"@unocss/transformer-directives": "^0.57.1",
"dozzle": "workspace:*",
"sitemap": "^7.1.1",
"unocss": "^0.56.5"
"unocss": "^0.57.1"
}
}
+172 -175
View File
@@ -9,14 +9,14 @@ devDependencies:
specifier: ^2.3.0
version: 2.3.0
'@unocss/preset-typography':
specifier: ^0.56.5
version: 0.56.5
specifier: ^0.57.1
version: 0.57.1
'@unocss/reset':
specifier: ^0.56.5
version: 0.56.5
specifier: ^0.57.1
version: 0.57.1
'@unocss/transformer-directives':
specifier: ^0.56.5
version: 0.56.5
specifier: ^0.57.1
version: 0.57.1
dozzle:
specifier: workspace:*
version: link:..
@@ -24,8 +24,8 @@ devDependencies:
specifier: ^7.1.1
version: 7.1.1
unocss:
specifier: ^0.56.5
version: 0.56.5(postcss@8.4.30)(vite@4.4.9)
specifier: ^0.57.1
version: 0.57.1(postcss@8.4.31)(vite@4.5.0)
packages:
@@ -34,7 +34,7 @@ packages:
engines: {node: '>=6.0.0'}
dependencies:
'@jridgewell/gen-mapping': 0.3.3
'@jridgewell/trace-mapping': 0.3.19
'@jridgewell/trace-mapping': 0.3.20
dev: true
/@antfu/install-pkg@0.1.1:
@@ -250,8 +250,8 @@ packages:
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
dev: true
/@iconify/utils@2.1.10:
resolution: {integrity: sha512-0/+5hxjzCZ9RoYpqxnOzbnpQyMdZRuHcMxPJeuX+x/aZkAAD/N4TajDjAPT7LpX+M0bfLExj/p0bbDkUfp0lrg==}
/@iconify/utils@2.1.11:
resolution: {integrity: sha512-M/w3PkN8zQYXi8N6qK/KhnYMfEbbb6Sk8RZVn8g+Pmmu5ybw177RpsaGwpziyHeUsu4etrexYSWq3rwnIqzYCg==}
dependencies:
'@antfu/install-pkg': 0.1.1
'@antfu/utils': 0.7.6
@@ -269,7 +269,7 @@ packages:
dependencies:
'@jridgewell/set-array': 1.1.2
'@jridgewell/sourcemap-codec': 1.4.15
'@jridgewell/trace-mapping': 0.3.19
'@jridgewell/trace-mapping': 0.3.20
dev: true
/@jridgewell/resolve-uri@3.1.1:
@@ -286,8 +286,8 @@ packages:
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
dev: true
/@jridgewell/trace-mapping@0.3.19:
resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==}
/@jridgewell/trace-mapping@0.3.20:
resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==}
dependencies:
'@jridgewell/resolve-uri': 3.1.1
'@jridgewell/sourcemap-codec': 1.4.15
@@ -339,241 +339,238 @@ packages:
resolution: {integrity: sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==}
dev: true
/@rollup/pluginutils@5.0.4:
resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==}
/@rollup/pluginutils@5.0.5:
resolution: {integrity: sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^1.20.0||^2.0.0||^3.0.0
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
peerDependenciesMeta:
rollup:
optional: true
dependencies:
'@types/estree': 1.0.2
'@types/estree': 1.0.3
estree-walker: 2.0.2
picomatch: 2.3.1
dev: true
/@types/estree@1.0.2:
resolution: {integrity: sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==}
/@types/estree@1.0.3:
resolution: {integrity: sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==}
dev: true
/@types/node@17.0.45:
resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==}
dev: true
/@types/node@18.14.2:
resolution: {integrity: sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==}
dev: true
/@types/sax@1.2.4:
resolution: {integrity: sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==}
/@types/sax@1.2.6:
resolution: {integrity: sha512-A1mpYCYu1aHFayy8XKN57ebXeAbh9oQIZ1wXcno6b1ESUAfMBDMx7mf/QGlYwcMRaFryh9YBuH03i/3FlPGDkQ==}
dependencies:
'@types/node': 18.14.2
'@types/node': 17.0.45
dev: true
/@unocss/astro@0.56.5(vite@4.4.9):
resolution: {integrity: sha512-nkxyGV9mA7DZ5LEr4Gap/SggM60MFNUfn56ngpxCqjQHJOMRJrAcR99hCVn+78vZ9xuZl9HxdIwgZLzn41thMw==}
/@unocss/astro@0.57.1(vite@4.5.0):
resolution: {integrity: sha512-KNaqN/SGM/uz1QitajIkzNEw0jy9Zx9Wp8fl4GhfGYEMAN2+M4cuvBZRmlb6cLctSXmSAJQDG91ivbD1JijGnw==}
peerDependencies:
vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
peerDependenciesMeta:
vite:
optional: true
dependencies:
'@unocss/core': 0.56.5
'@unocss/reset': 0.56.5
'@unocss/vite': 0.56.5(vite@4.4.9)
vite: 4.4.9
'@unocss/core': 0.57.1
'@unocss/reset': 0.57.1
'@unocss/vite': 0.57.1(vite@4.5.0)
vite: 4.5.0
transitivePeerDependencies:
- rollup
dev: true
/@unocss/cli@0.56.5:
resolution: {integrity: sha512-VYaqu7Dr1n9ebFFdQM+9Jyg/o9BVKRShlV8bQsBS58gkXiWsA/uAl1Uy2vzpLSrT0F6uGyDmYUF6p4DaUnUO+w==}
/@unocss/cli@0.57.1:
resolution: {integrity: sha512-wKuOaygrPNzDm5L7+2SfHsIi3knJrAQ8nH6OasVqB+bGDz6ybDlULV7wvUco6Os72ydh7YbWC2/WpqFii8U/3w==}
engines: {node: '>=14'}
hasBin: true
dependencies:
'@ampproject/remapping': 2.2.1
'@rollup/pluginutils': 5.0.4
'@unocss/config': 0.56.5
'@unocss/core': 0.56.5
'@unocss/preset-uno': 0.56.5
'@rollup/pluginutils': 5.0.5
'@unocss/config': 0.57.1
'@unocss/core': 0.57.1
'@unocss/preset-uno': 0.57.1
cac: 6.7.14
chokidar: 3.5.3
colorette: 2.0.20
consola: 3.2.3
fast-glob: 3.3.1
magic-string: 0.30.3
magic-string: 0.30.5
pathe: 1.1.1
perfect-debounce: 1.0.0
transitivePeerDependencies:
- rollup
dev: true
/@unocss/config@0.56.5:
resolution: {integrity: sha512-rscnFIYgUlN/0hXHdhANyjFcDjDutt3JO0ZRITdNLzoglh7GVNiDTURBJwUZejF/vGJ7IkMd3qOdNhPFuRY1Bg==}
/@unocss/config@0.57.1:
resolution: {integrity: sha512-mbuVO0mH1PX7rEkViMNWb3jG1ji7TUydo2DdnMHhJE+dOrGtnQzhzXGlAd4qqel1fnt/VWuOyZKwJA3QO6VCtg==}
engines: {node: '>=14'}
dependencies:
'@unocss/core': 0.56.5
unconfig: 0.3.10
'@unocss/core': 0.57.1
unconfig: 0.3.11
dev: true
/@unocss/core@0.56.5:
resolution: {integrity: sha512-fx5VhOjSHn0HdV2D34pEwFMAHJcJQRTCp1xEE4GzxY1irXzaa+m2aYf5PZjmDxehiOC16IH7TO9FOWANXk1E0w==}
/@unocss/core@0.57.1:
resolution: {integrity: sha512-cqQW/4gCuk+bFMPg9lBanuRNQ9Lx1l4PpMN/6uKxI5WROpq7ce/Xb4uGvAxKLh3ITtFSpXs2cLfsy7QD6cVD/Q==}
dev: true
/@unocss/extractor-arbitrary-variants@0.56.5:
resolution: {integrity: sha512-p2pyzz/ONvc5CGcaB9OZvWE8qkRSgyuhaQqFQLdBFeUhveHC0CGP0iSnXwBgAFHWM7DJo4/JpWeZ+mBt0ogVLA==}
/@unocss/extractor-arbitrary-variants@0.57.1:
resolution: {integrity: sha512-9s+azHhBnwjxm46TsD1RY0krDAwOR8tcw58Vtl3emd6C0VQsAOdoprt7UHE7GEXMvDVq7nMf8lAT0BM0LteW3w==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/core': 0.57.1
dev: true
/@unocss/inspector@0.56.5:
resolution: {integrity: sha512-UK/X2JyqxB1uueIFlffFsBioxMptanBbJYjrmOoLPdAFoOPp9o8IIFkFs3OKWc8imvyl3w+F0opncmdJnDMllw==}
/@unocss/inspector@0.57.1:
resolution: {integrity: sha512-qV7ta7iHGX2EpZJ4IWY/05kgyhKFeWlvVJbrOnGsaH8gVt33T/43YAhB/8K5GIXBXIwkhwk13iB13nlg2gSheg==}
dependencies:
'@unocss/rule-utils': 0.56.5
'@unocss/rule-utils': 0.57.1
gzip-size: 6.0.0
sirv: 2.0.3
dev: true
/@unocss/postcss@0.56.5(postcss@8.4.30):
resolution: {integrity: sha512-oDY1vCdrCQZx/oxDkq3z77a0RoO+WVQT090oDZzLFO/cPWH3elSOHwnoJU/KzrpJLbUFpyTQKZ/k3VbBaEdGTA==}
/@unocss/postcss@0.57.1(postcss@8.4.31):
resolution: {integrity: sha512-DexrV+v/qkVh6t660rXigNr2Y6lON8jxD1z2KVk2bjHKhFflF6q6seps6d/MquyLJI1mXF2uANTeFAeL2q6evw==}
engines: {node: '>=14'}
peerDependencies:
postcss: ^8.4.21
dependencies:
'@unocss/config': 0.56.5
'@unocss/core': 0.56.5
'@unocss/rule-utils': 0.56.5
'@unocss/config': 0.57.1
'@unocss/core': 0.57.1
'@unocss/rule-utils': 0.57.1
css-tree: 2.3.1
fast-glob: 3.3.1
magic-string: 0.30.3
postcss: 8.4.30
magic-string: 0.30.5
postcss: 8.4.31
dev: true
/@unocss/preset-attributify@0.56.5:
resolution: {integrity: sha512-476NVv1kUmiD0ObtJceUB1ldiQvGStEUlwoHFOFl8srZbRuRlwq8Uz4sxCePf3sn2FP8UHw+By+nxwxMQuHpww==}
/@unocss/preset-attributify@0.57.1:
resolution: {integrity: sha512-pvGQHaqBlB0jQysWhNbcKLOGrkj8b53k0sAa9LYxQjD1fa8t/dwbuMpZv4twX+gysF0vBhxRoWBPLH1/S6zRZg==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/core': 0.57.1
dev: true
/@unocss/preset-icons@0.56.5:
resolution: {integrity: sha512-Pc973z/M7+TsIPRli9xSE+rjzQnX9r0PppTOD5lrD8PqvNSGIrSWZUFDc5NqL09hKHkIdVrDLC+2ouLYqTI7iA==}
/@unocss/preset-icons@0.57.1:
resolution: {integrity: sha512-ve4jC6yREfS0mv97DCld9xLjMuiSCcsQPKucdtpUfCjLMqtGd1ZGGdFv02Q+92NkW7HDfgj+izEw1SKh9695Ow==}
dependencies:
'@iconify/utils': 2.1.10
'@unocss/core': 0.56.5
'@iconify/utils': 2.1.11
'@unocss/core': 0.57.1
ofetch: 1.3.3
transitivePeerDependencies:
- supports-color
dev: true
/@unocss/preset-mini@0.56.5:
resolution: {integrity: sha512-/KhlThhs1ilauM7MwRSpahLbIPZ5VGeGvaUsU8+ZlNT3sis4yoVYkPtR14tL2IT6jhOU05N/uu3aBj+1bP8GjQ==}
/@unocss/preset-mini@0.57.1:
resolution: {integrity: sha512-v9ZsIUGDfZNXbIrOc7zrBp+RFbFFGSQN/vKIf761js4fJ31j6lan4pPQPGcY17xHConkI1HJT/+yb/UVJaAcHw==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/extractor-arbitrary-variants': 0.56.5
'@unocss/rule-utils': 0.56.5
'@unocss/core': 0.57.1
'@unocss/extractor-arbitrary-variants': 0.57.1
'@unocss/rule-utils': 0.57.1
dev: true
/@unocss/preset-tagify@0.56.5:
resolution: {integrity: sha512-ANtI7E92fuzF40MD/3V72myNqrcGNXAD3TjXHIxAPQP2F+DcYIl2TBPHVsGUt2Rc5Kid2kvvsWan6sRAQVGPng==}
/@unocss/preset-tagify@0.57.1:
resolution: {integrity: sha512-GV8knxnsOVH/XiG2KB+mVZeEJqr0PZvvkSTPftGPbjttoKVZ+28Y5q9/qezH7p4W6RYVAAK+3qHHy5wWZosiMw==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/core': 0.57.1
dev: true
/@unocss/preset-typography@0.56.5:
resolution: {integrity: sha512-fA/q5S+s7BV3TRWRvXqG7xpa8WNfG19uaZx288FcKauMR0TX4jUM0EkkngpwrTgeXXohh5awx4OEW3E1s1Q2oA==}
/@unocss/preset-typography@0.57.1:
resolution: {integrity: sha512-C4cqCiGW0OSoSXsVQKgfLulYxY5C8M40f+a8VtBlAaEaN6eSlEt+catXb0chF9T2mvz/b87b0PahPvPwJdDf1Q==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/preset-mini': 0.56.5
'@unocss/core': 0.57.1
'@unocss/preset-mini': 0.57.1
dev: true
/@unocss/preset-uno@0.56.5:
resolution: {integrity: sha512-3hzE0X1oxMbHLvWyTj/4BrJQ7OAL428BpzEJos0RsxifM04vOJX4GC4khIbmTl8KIMECMtATK3ren3JqzD2bFw==}
/@unocss/preset-uno@0.57.1:
resolution: {integrity: sha512-0+DKZiowYjYzq2swJzQA2dhqDvLJdm0Y437ITzc2GzZMKGUUuNi+w2v3/SzwkpkRd9zTB9/YaOIJVfdrx6ZOXQ==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/preset-mini': 0.56.5
'@unocss/preset-wind': 0.56.5
'@unocss/rule-utils': 0.56.5
'@unocss/core': 0.57.1
'@unocss/preset-mini': 0.57.1
'@unocss/preset-wind': 0.57.1
'@unocss/rule-utils': 0.57.1
dev: true
/@unocss/preset-web-fonts@0.56.5:
resolution: {integrity: sha512-1YPbqpHK6NaXWHceNJTl2A+dNbliB6FeU5Tvkox1KOLTTwvzUF80uWHAE/l05Oc9EZyolZ8OsM37p2eJAb0wpw==}
/@unocss/preset-web-fonts@0.57.1:
resolution: {integrity: sha512-9DCIMlBRaGrljLmeciH4WqP+uRx2z2nLxvrvEmGbpJJpMn2H4higR5Zu5tDyKYGr9QBl9vXdWgib+43OSswkqA==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/core': 0.57.1
ofetch: 1.3.3
dev: true
/@unocss/preset-wind@0.56.5:
resolution: {integrity: sha512-iyMPvCEZkrGLHFXXlcqxDo/UcSK7KWw4x7/QUz7irrvc78cxYVuPm98QZgpCRcCwKerKVyFLjGOtwQ0kmVSVsQ==}
/@unocss/preset-wind@0.57.1:
resolution: {integrity: sha512-5UairNahUXNDe9AggPtTCodyPjl6NgPCsiEB22LVgN20UjBXjaqzN5wUe1OgtpLoAUaSk0KI7eLWhnWbTbST3A==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/preset-mini': 0.56.5
'@unocss/rule-utils': 0.56.5
'@unocss/core': 0.57.1
'@unocss/preset-mini': 0.57.1
'@unocss/rule-utils': 0.57.1
dev: true
/@unocss/reset@0.56.5:
resolution: {integrity: sha512-//Pv2ITAdnpWB9FIr0JiQVl1rL1XgISR8mu3OikhCfi6d/4OH+o6/WyE7evF1pOmk1JjsQlznOABIZXQlcpbHQ==}
/@unocss/reset@0.57.1:
resolution: {integrity: sha512-f/ofoudjFN/HMtv1XV5phP58pOmNruBhr0GbVdBNylyieMQkFHowA7iSemChnC/fTbCcY6oSOAcFl4n9AefjdA==}
dev: true
/@unocss/rule-utils@0.56.5:
resolution: {integrity: sha512-CXIGHCIC9B8WUl9KbbFMSZHcsIgfmI/+X0bjBv6xrgBVC1EQ2Acq4PYnJIbaRGBRAhl9wYjNL7Zq2UWOdowHAw==}
/@unocss/rule-utils@0.57.1:
resolution: {integrity: sha512-Hdicz7YORZx7SHICldzOGjPNeJwk/Xhy3cycqiPbg6nB6d639bpgZn5BsbDzHCPKpguwDomUqTZS6+C3s7tUVg==}
engines: {node: '>=14'}
dependencies:
'@unocss/core': 0.56.5
'@unocss/core': 0.57.1
magic-string: 0.30.5
dev: true
/@unocss/scope@0.56.5:
resolution: {integrity: sha512-q2eHYLuqF7RZEVGti205X2JOKSH6lBJGoQIjPtWgodNTg3S7qmUinHG0XzikI30L3EF3VljIh5TbtwGPcvbNsA==}
/@unocss/scope@0.57.1:
resolution: {integrity: sha512-ZAzg6lLGwKNQGCvJXEie3TvGztkAyajEFqygu0mjtHb+CmDql4iAjoygs+3dnRI5hSDwfMYFrJ2azX26+2CsoA==}
dev: true
/@unocss/transformer-attributify-jsx-babel@0.56.5:
resolution: {integrity: sha512-QUlbmWpdfzdgEXNcOJwSvKDHB/ID/X3zlpK+fXyCKTkqiYgCwMFmLXll2HtNhIgH2E1gWo/lDlwpiW/QjQb/rw==}
/@unocss/transformer-attributify-jsx-babel@0.57.1:
resolution: {integrity: sha512-EOCPB8OGmhroAuFU0i0W5p6GmJpx6mAkP4KmsqVLd4QMgw+8aXkG7SKyLnxQZnekM0/dSo0TcpVGeGrZaUNgvQ==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/core': 0.57.1
dev: true
/@unocss/transformer-attributify-jsx@0.56.5:
resolution: {integrity: sha512-SQW7t58s26qHYuD8v3covXtWoXlflw3FV5dlBCw/2iOfNo3OTVUWReAB5y0XQIT3828nHnPqeQq4IhmnuOENdw==}
/@unocss/transformer-attributify-jsx@0.57.1:
resolution: {integrity: sha512-ohgSEwm2j98ltPWl1zRPvZhRjQPpd7qZtgoROTQh6n2W7wEO1SlnYjgBBz+pGuo2dkfBN5NjuZJ93AEjS10Ysw==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/core': 0.57.1
dev: true
/@unocss/transformer-compile-class@0.56.5:
resolution: {integrity: sha512-uT/+bVDN26hJ4a5FtbOT4PxAVDUTxwZCEVCesPAE5RnGd7f+KYUnk3XdDa77xyklPQsxPhr4MEjA0HGPHtSH8Q==}
/@unocss/transformer-compile-class@0.57.1:
resolution: {integrity: sha512-z0WZN6hbgpyBm2xqIrojqEjpQMhiyzHRbaBjWzI/6ieHWoFo5ajIwnReaFUEfJRNruLTd7/9hFDZdRXRPhttFw==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/core': 0.57.1
dev: true
/@unocss/transformer-directives@0.56.5:
resolution: {integrity: sha512-ykXbvG1LbqTqlYImMtkJUeH8BtuiE+8T/txUVyooUoVgr2qSELUu2FxC6rTX2EUx+F5BZhaQd6GsdzgaDwXgIg==}
/@unocss/transformer-directives@0.57.1:
resolution: {integrity: sha512-rIk3XEU2NywEJUOkngBSmJfvS3IVgxkkqgMvuIqz8ZDbwWhepuMxsiI0QR3ypkipGr/eKK5DJ7eK0OVlo6FPFA==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/rule-utils': 0.56.5
'@unocss/core': 0.57.1
'@unocss/rule-utils': 0.57.1
css-tree: 2.3.1
dev: true
/@unocss/transformer-variant-group@0.56.5:
resolution: {integrity: sha512-e+7XtICuOtcOgGyxI06i0LK6R446KLFvzv+lw3WbwhD8OcsSFUAtCaAw0l+cyyiiZ/k2tLdUR0O4hYwQVa8f1A==}
/@unocss/transformer-variant-group@0.57.1:
resolution: {integrity: sha512-qwydzn2Lqz/8zW6UUXdORaUl8humsG8ll74LN/z8cjEsqtXZkVdkV0l6Brpp9Xp/XPbKwO+II+KH3/1LGwXSzQ==}
dependencies:
'@unocss/core': 0.56.5
'@unocss/core': 0.57.1
dev: true
/@unocss/vite@0.56.5(vite@4.4.9):
resolution: {integrity: sha512-X4nvIukXTH//d+Oc97nJogK04sVGw4fc5LhVV1DjHQVmAOAmhTJCG6SxWGoSeqqUMx5X3gI9fVILK+5O8yl5EA==}
/@unocss/vite@0.57.1(vite@4.5.0):
resolution: {integrity: sha512-kEBDvGgQNkX2n87S6Ao5seyFb1kuWZ5p96dGOS7VFpD7HvR5xholkJXaVhUK9/exCldjLExbo5UtVlbxFLUFYg==}
peerDependencies:
vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
dependencies:
'@ampproject/remapping': 2.2.1
'@rollup/pluginutils': 5.0.4
'@unocss/config': 0.56.5
'@unocss/core': 0.56.5
'@unocss/inspector': 0.56.5
'@unocss/scope': 0.56.5
'@unocss/transformer-directives': 0.56.5
'@rollup/pluginutils': 5.0.5
'@unocss/config': 0.57.1
'@unocss/core': 0.57.1
'@unocss/inspector': 0.57.1
'@unocss/scope': 0.57.1
'@unocss/transformer-directives': 0.57.1
chokidar: 3.5.3
fast-glob: 3.3.1
magic-string: 0.30.3
vite: 4.4.9
magic-string: 0.30.5
vite: 4.5.0
transitivePeerDependencies:
- rollup
dev: true
@@ -666,12 +663,12 @@ packages:
ms: 2.1.2
dev: true
/defu@6.1.2:
resolution: {integrity: sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==}
/defu@6.1.3:
resolution: {integrity: sha512-Vy2wmG3NTkmHNg/kzpuvHhkqeIx3ODWqasgCRbKtbXEN0G+HpEEv9BtJLp7ZG1CZloFaC41Ah3ZFbq7aqCqMeQ==}
dev: true
/destr@2.0.1:
resolution: {integrity: sha512-M1Ob1zPSIvlARiJUkKqvAZ3VAqQY6Jcuth/pBKQ2b1dX/Qx0OnJ8Vux6J2H5PTMQeRzWrrbTu70VxBfv/OPDJA==}
/destr@2.0.2:
resolution: {integrity: sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==}
dev: true
/duplexer@0.1.2:
@@ -853,8 +850,8 @@ packages:
p-locate: 5.0.0
dev: true
/magic-string@0.30.3:
resolution: {integrity: sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==}
/magic-string@0.30.5:
resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==}
engines: {node: '>=12'}
dependencies:
'@jridgewell/sourcemap-codec': 1.4.15
@@ -892,7 +889,7 @@ packages:
acorn: 8.10.0
pathe: 1.1.1
pkg-types: 1.0.3
ufo: 1.3.0
ufo: 1.3.1
dev: true
/mrmime@1.0.1:
@@ -929,9 +926,9 @@ packages:
/ofetch@1.3.3:
resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==}
dependencies:
destr: 2.0.1
destr: 2.0.2
node-fetch-native: 1.4.0
ufo: 1.3.0
ufo: 1.3.1
dev: true
/onetime@5.1.2:
@@ -990,8 +987,8 @@ packages:
pathe: 1.1.1
dev: true
/postcss@8.4.30:
resolution: {integrity: sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==}
/postcss@8.4.31:
resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
engines: {node: ^10 || ^12 || >=14}
dependencies:
nanoid: 3.3.6
@@ -1015,8 +1012,8 @@ packages:
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
dev: true
/rollup@3.29.3:
resolution: {integrity: sha512-T7du6Hum8jOkSWetjRgbwpM6Sy0nECYrYRSmZjayFcOddtKJWU4d17AC3HNUk7HRuqy4p+G7aEZclSHytqUmEg==}
/rollup@3.29.4:
resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==}
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
hasBin: true
optionalDependencies:
@@ -1029,8 +1026,8 @@ packages:
queue-microtask: 1.2.3
dev: true
/sax@1.2.4:
resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
/sax@1.3.0:
resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==}
dev: true
/shebang-command@2.0.0:
@@ -1064,9 +1061,9 @@ packages:
hasBin: true
dependencies:
'@types/node': 17.0.45
'@types/sax': 1.2.4
'@types/sax': 1.2.6
arg: 5.0.2
sax: 1.2.4
sax: 1.3.0
dev: true
/source-map-js@1.0.2:
@@ -1091,24 +1088,24 @@ packages:
engines: {node: '>=6'}
dev: true
/ufo@1.3.0:
resolution: {integrity: sha512-bRn3CsoojyNStCZe0BG0Mt4Nr/4KF+rhFlnNXybgqt5pXHNFRlqinSoQaTrGyzE4X8aHplSb+TorH+COin9Yxw==}
/ufo@1.3.1:
resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==}
dev: true
/unconfig@0.3.10:
resolution: {integrity: sha512-tj317lhIq2iZF/NXrJnU1t2UaGUKKz1eL1sK2t63Oq66V9BxqvZV12m55fp/fpQJ+DDmVlLgo7cnLVOZkhlO/A==}
/unconfig@0.3.11:
resolution: {integrity: sha512-bV/nqePAKv71v3HdVUn6UefbsDKQWRX+bJIkiSm0+twIds6WiD2bJLWWT3i214+J/B4edufZpG2w7Y63Vbwxow==}
dependencies:
'@antfu/utils': 0.7.6
defu: 6.1.2
defu: 6.1.3
jiti: 1.20.0
mlly: 1.4.2
dev: true
/unocss@0.56.5(postcss@8.4.30)(vite@4.4.9):
resolution: {integrity: sha512-tO+9St4CntSjHpLXZqBo0/etS06MtvFF1NEny/qFJCL9sCopWwmDKuzW6/LIb4wfqZLdMpVFoEACMNv8nP849A==}
/unocss@0.57.1(postcss@8.4.31)(vite@4.5.0):
resolution: {integrity: sha512-xLsyJ8+T1/Ux93yrqOvuQy268wF5rSzydlsbqZ5EVfi01PxYyydez3nycPqbyPZientkJ0Yohzd5aBqmZgku3A==}
engines: {node: '>=14'}
peerDependencies:
'@unocss/webpack': 0.56.5
'@unocss/webpack': 0.57.1
vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
peerDependenciesMeta:
'@unocss/webpack':
@@ -1116,27 +1113,27 @@ packages:
vite:
optional: true
dependencies:
'@unocss/astro': 0.56.5(vite@4.4.9)
'@unocss/cli': 0.56.5
'@unocss/core': 0.56.5
'@unocss/extractor-arbitrary-variants': 0.56.5
'@unocss/postcss': 0.56.5(postcss@8.4.30)
'@unocss/preset-attributify': 0.56.5
'@unocss/preset-icons': 0.56.5
'@unocss/preset-mini': 0.56.5
'@unocss/preset-tagify': 0.56.5
'@unocss/preset-typography': 0.56.5
'@unocss/preset-uno': 0.56.5
'@unocss/preset-web-fonts': 0.56.5
'@unocss/preset-wind': 0.56.5
'@unocss/reset': 0.56.5
'@unocss/transformer-attributify-jsx': 0.56.5
'@unocss/transformer-attributify-jsx-babel': 0.56.5
'@unocss/transformer-compile-class': 0.56.5
'@unocss/transformer-directives': 0.56.5
'@unocss/transformer-variant-group': 0.56.5
'@unocss/vite': 0.56.5(vite@4.4.9)
vite: 4.4.9
'@unocss/astro': 0.57.1(vite@4.5.0)
'@unocss/cli': 0.57.1
'@unocss/core': 0.57.1
'@unocss/extractor-arbitrary-variants': 0.57.1
'@unocss/postcss': 0.57.1(postcss@8.4.31)
'@unocss/preset-attributify': 0.57.1
'@unocss/preset-icons': 0.57.1
'@unocss/preset-mini': 0.57.1
'@unocss/preset-tagify': 0.57.1
'@unocss/preset-typography': 0.57.1
'@unocss/preset-uno': 0.57.1
'@unocss/preset-web-fonts': 0.57.1
'@unocss/preset-wind': 0.57.1
'@unocss/reset': 0.57.1
'@unocss/transformer-attributify-jsx': 0.57.1
'@unocss/transformer-attributify-jsx-babel': 0.57.1
'@unocss/transformer-compile-class': 0.57.1
'@unocss/transformer-directives': 0.57.1
'@unocss/transformer-variant-group': 0.57.1
'@unocss/vite': 0.57.1(vite@4.5.0)
vite: 4.5.0
transitivePeerDependencies:
- postcss
- rollup
@@ -1147,8 +1144,8 @@ packages:
resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==}
dev: true
/vite@4.4.9:
resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==}
/vite@4.5.0:
resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
peerDependencies:
@@ -1176,8 +1173,8 @@ packages:
optional: true
dependencies:
esbuild: 0.18.20
postcss: 8.4.30
rollup: 3.29.3
postcss: 8.4.31
rollup: 3.29.4
optionalDependencies:
fsevents: 2.3.3
dev: true
+12 -1
View File
@@ -5,7 +5,7 @@ require (
github.com/alexflint/go-arg v1.4.3
github.com/beme/abide v0.0.0-20190723115211-635a09831760
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker v24.0.6+incompatible
github.com/docker/docker v24.0.7+incompatible
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1
@@ -31,11 +31,22 @@ require github.com/go-chi/chi/v5 v5.0.10
require (
github.com/alexflint/go-scalar v1.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/go-chi/jwtauth/v5 v5.1.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/google/go-cmp v0.5.5 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect
github.com/kr/pretty v0.2.1 // indirect
github.com/lestrrat-go/blackmagic v1.0.1 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc v1.0.4 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/jwx/v2 v2.0.11 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
+49
View File
@@ -61,12 +61,17 @@ github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE=
github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -81,9 +86,13 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/jwtauth/v5 v5.1.1 h1:Pjixqu5YkjE9sCLpzE01L0Q4sQzJIPdo7uz9r8ftp/c=
github.com/go-chi/jwtauth/v5 v5.1.1/go.mod h1:CYP1WSbzD4MPuKCr537EM3kfFhSQgpUEtMJFuYJjqWU=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -161,6 +170,19 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8=
github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
github.com/lestrrat-go/jwx/v2 v2.0.11 h1:ViHMnaMeaO0qV16RZWBHM7GTrAnX2aFLVKofc7FuKLQ=
github.com/lestrrat-go/jwx/v2 v2.0.11/go.mod h1:ZtPtMFlrfDrH2Y0iwfa3dRFn8VzwBrB+cyrm3IBWdDg=
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk=
@@ -179,6 +201,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
@@ -195,6 +219,7 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
@@ -204,6 +229,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -216,7 +242,11 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -250,6 +280,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -284,6 +316,9 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -305,6 +340,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/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.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -343,10 +380,18 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -355,6 +400,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
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.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -412,6 +459,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
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.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+16 -27
View File
@@ -12,13 +12,9 @@ import (
type contextKey string
const RemoteUser contextKey = "remoteUser"
const remoteUser contextKey = "remoteUser"
type User struct {
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
Avatar string `json:"avatar,omitempty"`
type proxyAuthAuth struct {
}
func hashEmail(email string) string {
@@ -29,30 +25,23 @@ func hashEmail(email string) string {
return hex.EncodeToString(hash[:])
}
func newUser(username, email, name string) *User {
avatar := ""
if email != "" {
avatar = "https://gravatar.com/avatar/" + hashEmail(email)
}
return &User{
Username: username,
Email: email,
Name: name,
Avatar: avatar,
}
func NewForwardProxyAuth() *proxyAuthAuth {
return &proxyAuthAuth{}
}
func ForwardProxyAuthorizationRequired(next http.Handler) http.Handler {
func (p *proxyAuthAuth) AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Remote-Email") == "" {
log.Error("Unable to find remote email. Please check your proxy configuration. Expecting header 'Remote-Email'")
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
if r.Header.Get("Remote-Email") != "" {
user := newUser(r.Header.Get("Remote-User"), r.Header.Get("Remote-Email"), r.Header.Get("Remote-Name"))
ctx := context.WithValue(r.Context(), remoteUser, user)
next.ServeHTTP(w, r.WithContext(ctx))
} else {
next.ServeHTTP(w, r)
}
user := newUser(r.Header.Get("Remote-User"), r.Header.Get("Remote-Email"), r.Header.Get("Remote-Name"))
ctx := context.WithValue(r.Context(), RemoteUser, user)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func (p *proxyAuthAuth) CreateToken(username, password string) (string, error) {
log.Fatalf("CreateToken not implemented for proxy auth")
return "", nil
}
+49
View File
@@ -0,0 +1,49 @@
package auth
import (
"crypto/sha256"
"errors"
"net/http"
"time"
"github.com/go-chi/jwtauth/v5"
)
type simpleAuthContext struct {
UserDatabase *UserDatabase
tokenAuth *jwtauth.JWTAuth
}
var ErrInvalidCredentials = errors.New("invalid credentials")
func NewSimpleAuth(userDatabase *UserDatabase) *simpleAuthContext {
h := sha256.New()
for _, user := range userDatabase.Users {
h.Write([]byte(user.Password))
}
tokenAuth := jwtauth.New("HS256", h.Sum(nil), nil)
return &simpleAuthContext{
UserDatabase: userDatabase,
tokenAuth: tokenAuth,
}
}
func (a *simpleAuthContext) CreateToken(username, password string) (string, error) {
user := a.UserDatabase.FindByPassword(username, password)
if user == nil {
return "", ErrInvalidCredentials
}
_, tokenString, err := a.tokenAuth.Encode(map[string]interface{}{"username": user.Username, "email": user.Email, "name": user.Name, "timestamp": time.Now()})
if err != nil {
return "", err
}
return tokenString, nil
}
func (a *simpleAuthContext) AuthMiddleware(next http.Handler) http.Handler {
return jwtauth.Verifier(a.tokenAuth)(next)
}
+113
View File
@@ -0,0 +1,113 @@
package auth
import (
"context"
"crypto/sha256"
"encoding/hex"
"net/http"
"os"
"github.com/go-chi/jwtauth/v5"
"gopkg.in/yaml.v3"
)
type User struct {
Username string `json:"username"`
Email string `json:"email" yaml:"email"`
Name string `json:"name" yaml:"name"`
Avatar string `json:"avatar,omitempty"`
Password string `json:"-" yaml:"password"`
}
func newUser(username, email, name string) *User {
avatar := ""
if email != "" {
avatar = "https://gravatar.com/avatar/" + hashEmail(email)
}
return &User{
Username: username,
Email: email,
Name: name,
Avatar: avatar,
}
}
type UserDatabase struct {
Users map[string]*User `yaml:"users"`
}
func ReadUsersFromFile(path string) (*UserDatabase, error) {
users := UserDatabase{}
file, err := os.Open(path)
if err != nil {
return &users, err
}
defer file.Close()
if err := yaml.NewDecoder(file).Decode(&users); err != nil {
return &users, err
}
for username, user := range users.Users {
user.Username = username
}
return &users, nil
}
func (u *UserDatabase) Find(username string) *User {
user, ok := u.Users[username]
if !ok {
return nil
}
return user
}
func (u *UserDatabase) FindByPassword(username, password string) *User {
user := u.Find(username)
if user == nil {
return nil
}
if user.Password != sha256sum(password) {
return nil
}
return user
}
func sha256sum(s string) string {
bytes := sha256.Sum256([]byte(s))
return hex.EncodeToString(bytes[:])
}
func UserFromContext(ctx context.Context) *User {
if user, ok := ctx.Value(remoteUser).(*User); ok {
return user
} else {
if _, claims, err := jwtauth.FromContext(ctx); err == nil {
username, ok := claims["username"].(string)
if !ok {
return nil
}
if username == "" {
return nil
}
email := claims["email"].(string)
name := claims["name"].(string)
return newUser(username, email, name)
}
return nil
}
}
func RequireAuthentication(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user := UserFromContext(r.Context())
if user != nil {
next.ServeHTTP(w, r)
} else {
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
})
}
+99
View File
@@ -0,0 +1,99 @@
package profile
import (
"encoding/json"
"errors"
"os"
"path/filepath"
"github.com/amir20/dozzle/internal/auth"
log "github.com/sirupsen/logrus"
)
type Settings struct {
Search bool `json:"search"`
MenuWidth float32 `json:"menuWidth"`
SmallerScrollbars bool `json:"smallerScrollbars"`
ShowTimestamp bool `json:"showTimestamp"`
ShowStd bool `json:"showStd"`
ShowAllContainers bool `json:"showAllContainers"`
SoftWrap bool `json:"softWrap"`
CollapseNav bool `json:"collapseNav"`
AutomaticRedirect bool `json:"automaticRedirect"`
Size string `json:"size,omitempty"`
LightTheme string `json:"lightTheme,omitempty"`
HourStyle string `json:"hourStyle,omitempty"`
}
var data_path string
func init() {
path, err := filepath.Abs("./data")
if err != nil {
log.Fatalf("Unable to get absolute path for data directory: %s", err)
return
}
if _, err := os.Stat(path); os.IsNotExist(err) {
if err := os.Mkdir(path, 0755); err != nil {
log.Fatalf("Unable to create data directory: %s", err)
return
}
}
data_path = path
}
func SaveUserSettings(user *auth.User, settings *Settings) error {
path := filepath.Join(data_path, user.Username)
// Create user directory if it doesn't exist
if _, err := os.Stat(path); os.IsNotExist(err) {
if err := os.Mkdir(path, 0755); err != nil {
return err
}
}
settings_path := filepath.Join(path, "settings.json")
data, err := json.MarshalIndent(settings, "", " ")
if err != nil {
return err
}
f, err := os.Create(settings_path)
if err != nil {
return err
}
defer f.Close()
if _, err := f.Write(data); err != nil {
return err
}
log.Debugf("Saved settings for user %s", user.Username)
return f.Sync()
}
func LoadUserSettings(user *auth.User) (*Settings, error) {
path := filepath.Join(data_path, user.Username)
settings_path := filepath.Join(path, "settings.json")
if _, err := os.Stat(settings_path); os.IsNotExist(err) {
return &Settings{}, errors.New("Settings file does not exist")
}
f, err := os.Open(settings_path)
if err != nil {
return nil, err
}
defer f.Close()
var settings Settings
if err := json.NewDecoder(f).Decode(&settings); err != nil {
return nil, err
}
return &settings, nil
}
+1 -1
View File
@@ -75,7 +75,7 @@ Content-Type: text/html
HTTP/1.1 200 OK
Connection: close
Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' gravatar.com data:; manifest-src 'self'; connect-src 'self' api.github.com;
Content-Type: application/ld+json; charset=UTF-8
Content-Type: application/x-jsonl; charset=UTF-8
{"m":"INFO Testing stdout logs...","ts":1589396137772,"id":466600245,"l":"info","s":"stdout"}
{"m":"INFO Testing stderr logs...","ts":1589396197772,"id":1101501603,"l":"info","s":"stderr"}
+34
View File
@@ -101,6 +101,40 @@ func (h *handler) validateCredentials(w http.ResponseWriter, r *http.Request) {
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
func (h *handler) createToken(w http.ResponseWriter, r *http.Request) {
user := r.PostFormValue("username")
pass := r.PostFormValue("password")
if token, err := h.config.Authorizer.CreateToken(user, pass); err == nil {
http.SetCookie(w, &http.Cookie{
Name: "jwt",
Value: token,
HttpOnly: true,
Path: "/",
SameSite: http.SameSiteLaxMode,
})
log.Infof("Token created for user %s", user)
w.WriteHeader(http.StatusOK)
w.Write([]byte(http.StatusText(http.StatusOK)))
} else {
log.Errorf("Error while creating token: %v", err)
http.Error(w, err.Error(), http.StatusUnauthorized)
}
}
func (h *handler) deleteToken(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, &http.Cookie{
Name: "jwt",
Value: "",
HttpOnly: true,
Path: "/",
SameSite: http.SameSiteLaxMode,
Expires: time.Unix(0, 0),
})
w.WriteHeader(http.StatusOK)
w.Write([]byte(http.StatusText(http.StatusOK)))
}
func (h *handler) clearSession(w http.ResponseWriter, r *http.Request) {
if !secured {
log.Panic("Validating credentials with secured=false should not happen")
+55 -35
View File
@@ -13,6 +13,7 @@ import (
"github.com/amir20/dozzle/internal/analytics"
"github.com/amir20/dozzle/internal/auth"
"github.com/amir20/dozzle/internal/docker"
"github.com/amir20/dozzle/internal/profile"
log "github.com/sirupsen/logrus"
)
@@ -21,39 +22,12 @@ func (h *handler) index(w http.ResponseWriter, req *http.Request) {
_, err := h.content.Open(req.URL.Path)
if err == nil && req.URL.Path != "" && req.URL.Path != "/" {
fileServer.ServeHTTP(w, req)
if !h.config.NoAnalytics {
go func() {
host, _ := os.Hostname()
var client DockerClient
for _, v := range h.clients {
client = v
break
}
if containers, err := client.ListContainers(); err == nil {
totalContainers := len(containers)
runningContainers := 0
for _, container := range containers {
if container.State == "running" {
runningContainers++
}
}
re := analytics.RequestEvent{
ClientId: host,
TotalContainers: totalContainers,
RunningContainers: runningContainers,
}
analytics.SendRequestEvent(re)
}
}()
}
} else {
if !isAuthorized(req) && req.URL.Path != "login" {
http.Redirect(w, req, path.Clean(h.config.Base+"/login"), http.StatusTemporaryRedirect)
return
}
go h.sendRequestEvent()
h.executeTemplate(w, req)
}
}
@@ -77,9 +51,9 @@ func (h *handler) executeTemplate(w http.ResponseWriter, req *http.Request) {
log.Panic(err)
}
path := ""
base := ""
if h.config.Base != "/" {
path = h.config.Base
base = h.config.Base
}
hosts := make([]*docker.Host, 0, len(h.clients))
@@ -91,24 +65,42 @@ func (h *handler) executeTemplate(w http.ResponseWriter, req *http.Request) {
})
config := map[string]interface{}{
"base": path,
"base": base,
"version": h.config.Version,
"authorizationNeeded": h.isAuthorizationNeeded(req),
"secured": secured,
"hostname": h.config.Hostname,
"hosts": hosts,
"authProvider": h.config.AuthProvider,
}
if h.config.AuthProvider == "forward-proxy" {
user := req.Context().Value(auth.RemoteUser).(*auth.User)
user := auth.UserFromContext(req.Context())
if user != nil {
if settings, err := profile.LoadUserSettings(user); err == nil {
config["serverSettings"] = settings
} else {
config["serverSettings"] = struct{}{}
}
config["user"] = user
} else if h.config.AuthProvider == FORWARD_PROXY {
log.Error("Unable to find remote user. Please check your proxy configuration. Expecting headers Remote-Email, Remote-User, Remote-Name.")
log.Debugf("Dumping all headers for url /%s", req.URL.String())
for k, v := range req.Header {
log.Debugf("%s: %s", k, v)
}
http.Error(w, "Unauthorized user", http.StatusUnauthorized)
return
} else if h.config.AuthProvider == SIMPLE && req.URL.Path != "login" {
log.Debugf("Redirecting to login page for url /%s", req.URL.String())
http.Redirect(w, req, path.Clean(h.config.Base+"/login"), http.StatusTemporaryRedirect)
return
}
data := map[string]interface{}{
"Config": config,
"Dev": h.config.Dev,
"Manifest": h.readManifest(),
"Base": path,
"Base": base,
}
err = tmpl.Execute(w, data)
@@ -138,5 +130,33 @@ func (h *handler) readManifest() map[string]interface{} {
}
return manifest
}
}
func (h *handler) sendRequestEvent() {
if !h.config.NoAnalytics {
host, _ := os.Hostname()
var client DockerClient
for _, v := range h.clients {
client = v
break
}
if containers, err := client.ListContainers(); err == nil {
totalContainers := len(containers)
runningContainers := 0
for _, container := range containers {
if container.State == "running" {
runningContainers++
}
}
re := analytics.RequestEvent{
ClientId: host,
TotalContainers: totalContainers,
RunningContainers: runningContainers,
}
analytics.SendRequestEvent(re)
}
}
}
+1 -1
View File
@@ -51,7 +51,7 @@ func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) {
}
func (h *handler) fetchLogsBetweenDates(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/ld+json; charset=UTF-8")
w.Header().Set("Content-Type", "application/x-jsonl; charset=UTF-8")
from, _ := time.Parse(time.RFC3339, r.URL.Query().Get("from"))
to, _ := time.Parse(time.RFC3339, r.URL.Query().Get("to"))
+32
View File
@@ -0,0 +1,32 @@
package web
import (
"encoding/json"
"net/http"
"github.com/amir20/dozzle/internal/auth"
"github.com/amir20/dozzle/internal/profile"
log "github.com/sirupsen/logrus"
)
func (h *handler) saveSettings(w http.ResponseWriter, r *http.Request) {
var settings profile.Settings
if err := json.NewDecoder(r.Body).Decode(&settings); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
user := auth.UserFromContext(r.Context())
if user == nil {
http.Error(w, "Unable to find user", http.StatusInternalServerError)
return
}
if err := profile.SaveUserSettings(user, &settings); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
log.Errorf("Unable to save user settings: %s", err)
return
}
w.WriteHeader(http.StatusOK)
}
+30 -7
View File
@@ -16,6 +16,14 @@ import (
log "github.com/sirupsen/logrus"
)
type AuthProvider string
const (
NONE AuthProvider = "none"
SIMPLE AuthProvider = "simple"
FORWARD_PROXY AuthProvider = "forward-proxy"
)
// Config is a struct for configuring the web service
type Config struct {
Base string
@@ -26,7 +34,8 @@ type Config struct {
Hostname string
NoAnalytics bool
Dev bool
AuthProvider string
AuthProvider AuthProvider
Authorizer Authorizer
}
type handler struct {
@@ -47,6 +56,11 @@ type DockerClient interface {
Host() *docker.Host
}
type Authorizer interface {
AuthMiddleware(http.Handler) http.Handler
CreateToken(string, string) (string, error)
}
func CreateServer(clients map[string]DockerClient, content fs.FS, config Config) *http.Server {
handler := &handler{
clients: clients,
@@ -69,17 +83,21 @@ func createRouter(h *handler) *chi.Mux {
}
r.Route(base, func(r chi.Router) {
if h.config.Authorizer != nil {
r.Use(h.config.Authorizer.AuthMiddleware)
}
r.Group(func(r chi.Router) {
if h.config.AuthProvider == "forward-proxy" {
r.Use(auth.ForwardProxyAuthorizationRequired)
}
r.Group(func(r chi.Router) {
r.Use(authorizationRequired)
if h.config.AuthProvider != NONE {
r.Use(auth.RequireAuthentication)
}
r.Use(authorizationRequired) // TODO remove this
r.Get("/api/logs/stream/{host}/{id}", h.streamLogs)
r.Get("/api/logs/download/{host}/{id}", h.downloadLogs)
r.Get("/api/logs/{host}/{id}", h.fetchLogsBetweenDates)
r.Get("/api/events/stream", h.streamEvents)
r.Get("/logout", h.clearSession)
r.Put("/api/profile/settings", h.saveSettings)
r.Get("/logout", h.clearSession) // TODO remove this
r.Get("/version", h.version)
})
@@ -89,7 +107,12 @@ func createRouter(h *handler) *chi.Mux {
})
})
r.Post("/api/validateCredentials", h.validateCredentials)
if h.config.AuthProvider == SIMPLE {
r.Post("/api/token", h.createToken)
r.Delete("/api/token", h.deleteToken)
}
r.Post("/api/validateCredentials", h.validateCredentials) // TODO remove this
r.Get("/healthcheck", h.healthcheck)
})
+2 -2
View File
@@ -92,7 +92,7 @@ func Test_createRoutes_foobar_file(t *testing.T) {
func Test_createRoutes_version(t *testing.T) {
fs := afero.NewMemMapFs()
require.NoError(t, afero.WriteFile(fs, "index.html", []byte("index page"), 0644), "WriteFile should have no error.")
handler := createHandler(nil, afero.NewIOFS(fs), Config{Base: "/", Version: "dev"})
handler := createHandler(nil, afero.NewIOFS(fs), Config{Base: "/", Version: "dev", AuthProvider: NONE})
req, err := http.NewRequest("GET", "/version", nil)
require.NoError(t, err, "NewRequest should not return an error.")
rr := httptest.NewRecorder()
@@ -181,7 +181,7 @@ func Test_createRoutes_username_password_valid_session(t *testing.T) {
mockedClient := new(MockedClient)
mockedClient.On("FindContainer", "123").Return(docker.Container{ID: "123"}, nil)
mockedClient.On("ContainerLogs", mock.Anything, "123", "", docker.STDALL).Return(io.NopCloser(strings.NewReader("test data")), io.EOF)
handler := createHandler(mockedClient, nil, Config{Base: "/", Username: "amir", Password: "password"})
handler := createHandler(mockedClient, nil, Config{Base: "/", Username: "amir", Password: "password", AuthProvider: NONE})
// Get cookie first
req, err := http.NewRequest("GET", "/api/logs/stream/localhost/123?stdout=1&stderr=1", nil)
+1 -1
View File
@@ -80,5 +80,5 @@ func createHandler(client DockerClient, content fs.FS, config Config) *chi.Mux {
}
func createDefaultHandler(client DockerClient) *chi.Mux {
return createHandler(client, nil, Config{Base: "/"})
return createHandler(client, nil, Config{Base: "/", AuthProvider: NONE})
}
+28 -1
View File
@@ -7,6 +7,7 @@ import (
"net/http"
"os"
"os/signal"
"path/filepath"
"reflect"
"strings"
"syscall"
@@ -14,6 +15,7 @@ import (
"github.com/alexflint/go-arg"
"github.com/amir20/dozzle/internal/analytics"
"github.com/amir20/dozzle/internal/auth"
"github.com/amir20/dozzle/internal/docker"
"github.com/amir20/dozzle/internal/healthcheck"
"github.com/amir20/dozzle/internal/web"
@@ -172,6 +174,30 @@ func createClients(args args,
func createServer(args args, clients map[string]web.DockerClient) *http.Server {
_, dev := os.LookupEnv("DEV")
var provider web.AuthProvider = web.NONE
var authorizer web.Authorizer
if args.AuthProvider == "forward-proxy" {
provider = web.FORWARD_PROXY
authorizer = auth.NewForwardProxyAuth()
} else if args.AuthProvider == "simple" {
provider = web.SIMPLE
path, err := filepath.Abs("./data/users.yml")
if err != nil {
log.Fatalf("Could not find absolute path to users.yml file: %s", err)
}
if _, err := os.Stat(path); os.IsNotExist(err) {
log.Fatalf("Could not find users.yml file at %s", path)
}
users, err := auth.ReadUsersFromFile(path)
if err != nil {
log.Fatalf("Could not read users.yml file at %s: %s", path, err)
}
authorizer = auth.NewSimpleAuth(users)
}
config := web.Config{
Addr: args.Addr,
Base: args.Base,
@@ -181,7 +207,8 @@ func createServer(args args, clients map[string]web.DockerClient) *http.Server {
Hostname: args.Hostname,
NoAnalytics: args.NoAnalytics,
Dev: dev,
AuthProvider: args.AuthProvider,
AuthProvider: provider,
Authorizer: authorizer,
}
assets, err := fs.Sub(content, "dist")
+13 -13
View File
@@ -1,12 +1,12 @@
{
"name": "dozzle",
"version": "5.1.0",
"version": "5.2.0",
"description": "Realtime log viewer for docker containers. ",
"homepage": "https://github.com/amir20/dozzle#readme",
"bugs": {
"url": "https://github.com/amir20/dozzle/issues"
},
"packageManager": "pnpm@8.9.2",
"packageManager": "pnpm@8.10.0",
"repository": {
"type": "git",
"url": "git+https://github.com/amir20/dozzle.git"
@@ -29,7 +29,7 @@
"dependencies": {
"@iconify-json/carbon": "^1.1.21",
"@iconify-json/cil": "^1.1.5",
"@iconify-json/mdi": "^1.1.54",
"@iconify-json/mdi": "^1.1.55",
"@iconify-json/mdi-light": "^1.1.7",
"@iconify-json/octicon": "^1.1.49",
"@iconify-json/ph": "^1.1.6",
@@ -47,25 +47,25 @@
"d3-selection": "^3.0.0",
"d3-shape": "^3.2.0",
"d3-transition": "^3.0.1",
"daisyui": "^3.9.3",
"daisyui": "^3.9.4",
"date-fns": "^2.30.0",
"entities": "^4.5.0",
"fuse.js": "^6.6.2",
"fuse.js": "^7.0.0",
"lodash.debounce": "^4.0.8",
"pinia": "^2.1.7",
"postcss": "^8.4.31",
"postcss-mixins": "^9.0.4",
"splitpanes": "^3.1.5",
"tailwindcss": "^3.3.3",
"unplugin-auto-import": "^0.16.6",
"tailwindcss": "^3.3.5",
"unplugin-auto-import": "^0.16.7",
"unplugin-icons": "^0.17.1",
"unplugin-vue-components": "^0.25.2",
"unplugin-vue-macros": "^2.6.1",
"vite": "4.5.0",
"vite-plugin-pages": "^0.31.0",
"vite-plugin-vue-layouts": "^0.8.0",
"vue": "^3.3.6",
"vue-i18n": "^9.5.0",
"vue": "^3.3.7",
"vue-i18n": "^9.6.2",
"vue-router": "^4.2.5"
},
"devDependencies": {
@@ -79,10 +79,10 @@
"@types/d3-shape": "^3.1.4",
"@types/d3-transition": "^3.0.6",
"@types/lodash.debounce": "^4.0.8",
"@types/node": "^20.8.7",
"@types/node": "^20.8.9",
"@types/semver": "^7.5.4",
"@vitejs/plugin-vue": "4.4.0",
"@vue/compiler-sfc": "^3.3.6",
"@vue/compiler-sfc": "^3.3.7",
"@vue/test-utils": "^2.4.1",
"bumpp": "^9.2.0",
"c8": "^8.0.1",
@@ -96,9 +96,9 @@
"simple-git-hooks": "^2.9.0",
"ts-node": "^10.9.1",
"typescript": "^5.2.2",
"vitepress": "1.0.0-rc.23",
"vitepress": "1.0.0-rc.24",
"vitest": "^0.34.6",
"vue-tsc": "^1.8.19"
"vue-tsc": "^1.8.22"
},
"lint-staged": {
"*.{js,vue,css,ts,html,md}": [
+639 -796
View File
File diff suppressed because it is too large Load Diff
View File
+3
View File
@@ -65,6 +65,9 @@ export default defineConfig(() => ({
}),
],
server: {
watch: {
ignored: ["**/data/**"],
},
proxy: {
"/api": {
target: {