mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 12:51:55 +00:00
sveltekit: Setup unit tests with vitest (#54953)
This PR adds vitest and faker for unit testing, and to use it properly already I refactored the promise->store helper to be more flexible. **Unit testing** vitest works prefectly together with vite (it's from the same author/community). It will use the same configuration and so there is very little additional configuration necessary. I only had to update vite.config.ts to not overwrite `process` (but according to https://vitejs.dev/config/shared-options.html#define I might not be doing it right anyway... will look into this another time). The API is pretty compatible with jest, so there shouldn't be any surprises. Tests can be run with `pnpm vitest`. **Faker** I stared to use faker on a differnt branch to generate more (and more realistic) test data for storybook stories and unit test. Eventually I'd like to use this to generate mock data for any of our GraphQL APIs. One great feature is the ability to _seed_ the random number generator so that you can get random but repeatable values in tests. **Promise<>store utility** Working with promises in a reactive way can be tricky. There is a risk of stale data ovewriting current data when an older promise resolves after a newer one. Observables can help here but since we are trying to move away from them, I introduced a simple store to handle promises. I extended it now to handle more cases, especially being able to access the previous value while a new promise is loading. The API might seem clunky (and I'd be happy to improve it eventually), but this way makes it easier to remember to call `set` whenever the promise changes. ## Test plan `pnpm vitest` Run dev server, open pages affected by promise store changes (repo pages) and verify that they behave as expected.
This commit is contained in:
parent
406c2afea8
commit
fff87e4a50
@ -14,6 +14,8 @@
|
||||
# gazelle:js_test_files **/__mocks__/**/*.{ts,tsx}
|
||||
# gazelle:js_test_files **/fixtures/**/*.{ts,tsx}
|
||||
# gazelle:js_test_files **/WebStory.{ts,tsx}
|
||||
# TODO(bazel): sveltekit tests
|
||||
# gazelle:exclude **/web-sveltekit/**/*.test.ts
|
||||
|
||||
# TODO(bazel): put fixtures + testutils + ? into own rules
|
||||
# js_{fixture}_files **/*.{fixture,fixtures}.{ts,tsx}
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
"build-storybook": "storybook build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^8.0.2",
|
||||
"@playwright/test": "1.25.0",
|
||||
"@storybook/addon-essentials": "^7.0.26",
|
||||
"@storybook/addon-interactions": "^7.0.26",
|
||||
@ -41,7 +42,8 @@
|
||||
"svelte": "^4.0.0",
|
||||
"svelte-check": "^3.4.3",
|
||||
"tslib": "2.1.0",
|
||||
"vite": "^4.3.9"
|
||||
"vite": "^4.3.9",
|
||||
"vitest": "^0.33.0"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
|
||||
import type { GitCommitFields } from '$lib/graphql-operations'
|
||||
import Icon from '$lib/Icon.svelte'
|
||||
import { getRelativeTime } from '$lib/relativeTime'
|
||||
import { currentDate as now } from '$lib/stores'
|
||||
import UserAvatar from '$lib/UserAvatar.svelte'
|
||||
import { getRelativeTime } from '$lib/utils'
|
||||
|
||||
export let commit: GitCommitFields
|
||||
export let alwaysExpanded: boolean = false
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { numberWithCommas } from '$lib/common'
|
||||
import type { GitRefFields } from '$lib/graphql-operations'
|
||||
import { getRelativeTime } from '$lib/relativeTime'
|
||||
import { currentDate as now } from '$lib/stores'
|
||||
import { getRelativeTime } from '$lib/utils'
|
||||
|
||||
export let ref: GitRefFields
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ export const fetchTreeEntries = memoizeObservable(
|
||||
const MAX_FILE_TREE_ENTRIES = 1000
|
||||
export const NODE_LIMIT: unique symbol = Symbol()
|
||||
type ExpandableFileTreeNodeValues = TreeEntryFields
|
||||
type FileTreeNodeValue = ExpandableFileTreeNodeValues | typeof NODE_LIMIT
|
||||
export type FileTreeNodeValue = ExpandableFileTreeNodeValues | typeof NODE_LIMIT
|
||||
|
||||
export const fetchSidebarFileTree = memoize(
|
||||
async ({
|
||||
|
||||
@ -4,7 +4,6 @@ import { logger } from '$lib/common'
|
||||
import { type TemporarySettings, TemporarySettingsStorage, migrateLocalStorageToTemporarySettings } from '$lib/shared'
|
||||
|
||||
import { getStores } from './stores'
|
||||
import type { LoadingData } from './utils'
|
||||
|
||||
const loggedOutUserStore = new TemporarySettingsStorage(null, false)
|
||||
|
||||
@ -27,6 +26,11 @@ export function createTemporarySettingsStorage(storage = loggedOutUserStore): Wr
|
||||
}
|
||||
}
|
||||
|
||||
type LoadingData<D, E> =
|
||||
| { loading: true }
|
||||
| { loading: false; data: D; error: null }
|
||||
| { loading: false; data: null; error: E }
|
||||
|
||||
type TemporarySettingsKey = keyof TemporarySettings
|
||||
type TemporarySettingStatus<K extends TemporarySettingsKey> = LoadingData<TemporarySettings[K], unknown>
|
||||
|
||||
|
||||
@ -1,90 +0,0 @@
|
||||
import type { Observable } from 'rxjs'
|
||||
import { shareReplay } from 'rxjs/operators'
|
||||
import { type Readable, type Writable, writable, get, type Unsubscriber } from 'svelte/store'
|
||||
|
||||
export type LoadingData<D, E = Error> =
|
||||
| { loading: true }
|
||||
| { loading: false; data: D; error: null }
|
||||
| { loading: false; data: null; error: E }
|
||||
|
||||
/**
|
||||
* Converts a promise to a readable store which emits data, loading and error states.
|
||||
* Sometimes load functions return deferred promises and the data needs to be
|
||||
* "post processed" in code (i.e. not using {#await}).
|
||||
* Usually when working with async data one has to be careful with outdated data.
|
||||
* If the load function has been called again we don't want to process the
|
||||
* previous data anymore.
|
||||
* Using a (reactive) store makes that simpler since Svelte will automatically unsubscribe
|
||||
* when the store changes.
|
||||
*/
|
||||
export function asStore<T, E = Error>(
|
||||
promise: Promise<T>
|
||||
): Readable<LoadingData<T, E>> & { set(promise: Promise<T>): void } {
|
||||
const { subscribe, set } = writable<LoadingData<T, E>>({ loading: true })
|
||||
|
||||
function process(currentPromise: Promise<T>) {
|
||||
promise = currentPromise
|
||||
currentPromise.then(
|
||||
result => {
|
||||
if (currentPromise === promise) {
|
||||
set({ loading: false, data: result, error: null })
|
||||
}
|
||||
},
|
||||
error => {
|
||||
if (currentPromise === promise) {
|
||||
set({ loading: false, data: null, error })
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
process(promise)
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set: process,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to convert an Observable to a Svelte Readable. Useful when a
|
||||
* real Readable is needed to satisfy an interface.
|
||||
*/
|
||||
export function readableObservable<T>(observable: Observable<T>): Readable<T> {
|
||||
const sharedObservable = observable.pipe(shareReplay(1))
|
||||
return {
|
||||
subscribe(subscriber) {
|
||||
const subscription = sharedObservable.subscribe(subscriber)
|
||||
return () => subscription.unsubscribe()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a helper store that syncs with the currently set store.
|
||||
*/
|
||||
export function createForwardStore<T>(store: Writable<T>): Writable<T> & { updateStore(store: Writable<T>): void } {
|
||||
const { subscribe, set } = writable<T>(get(store), () => link(store))
|
||||
|
||||
let unsubscribe: Unsubscriber | null = null
|
||||
function link(store: Writable<T>): Unsubscriber {
|
||||
unsubscribe?.()
|
||||
return (unsubscribe = store.subscribe(set))
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set(value) {
|
||||
store.set(value)
|
||||
},
|
||||
update(value) {
|
||||
store.update(value)
|
||||
},
|
||||
updateStore(newStore) {
|
||||
if (newStore !== store) {
|
||||
store = newStore
|
||||
link(store)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
45
client/web-sveltekit/src/lib/utils/__snapshots__/time.test.ts.snap
generated
Normal file
45
client/web-sveltekit/src/lib/utils/__snapshots__/time.test.ts.snap
generated
Normal file
@ -0,0 +1,45 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`getRelativeTime > random times 1`] = `"2 years ago"`;
|
||||
|
||||
exports[`getRelativeTime > random times 2`] = `"2 years ago"`;
|
||||
|
||||
exports[`getRelativeTime > random times 3`] = `"last year"`;
|
||||
|
||||
exports[`getRelativeTime > random times 4`] = `"last year"`;
|
||||
|
||||
exports[`getRelativeTime > random times 5`] = `"10 months ago"`;
|
||||
|
||||
exports[`getRelativeTime > random times 6`] = `"10 months ago"`;
|
||||
|
||||
exports[`getRelativeTime > random times 7`] = `"6 months ago"`;
|
||||
|
||||
exports[`getRelativeTime > random times 8`] = `"5 months ago"`;
|
||||
|
||||
exports[`getRelativeTime > random times 9`] = `"5 months ago"`;
|
||||
|
||||
exports[`getRelativeTime > random times 10`] = `"last month"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > days 1`] = `"12 days ago"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > hours 1`] = `"7 hours ago"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > last day 1`] = `"24 hours ago"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > last hour 1`] = `"60 minutes ago"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > last minute 1`] = `"60 seconds ago"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > last month 1`] = `"last month"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > last second 1`] = `"1 second ago"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > last year 1`] = `"12 months ago"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > minutes 1`] = `"25 minutes ago"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > months 1`] = `"4 months ago"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > seconds 1`] = `"25 seconds ago"`;
|
||||
|
||||
exports[`getRelativeTime > specific times > years 1`] = `"8 years ago"`;
|
||||
3
client/web-sveltekit/src/lib/utils/index.ts
Normal file
3
client/web-sveltekit/src/lib/utils/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './promises'
|
||||
export * from './time'
|
||||
export * from './stores'
|
||||
107
client/web-sveltekit/src/lib/utils/promises.test.ts
Normal file
107
client/web-sveltekit/src/lib/utils/promises.test.ts
Normal file
@ -0,0 +1,107 @@
|
||||
import { get } from 'svelte/store'
|
||||
import { describe, it, vi, beforeAll, afterAll, expect } from 'vitest'
|
||||
|
||||
import { createPromiseStore } from './promises'
|
||||
|
||||
beforeAll(() => {
|
||||
vi.useFakeTimers()
|
||||
})
|
||||
afterAll(() => {
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
describe('createPromiseStore', () => {
|
||||
describe('initial promise', () => {
|
||||
it('correctly updates each store for resolved initial promises', async () => {
|
||||
const { pending, value, error, set } = createPromiseStore<number>()
|
||||
set(Promise.resolve(1))
|
||||
|
||||
expect(get(pending)).toBe(true)
|
||||
expect(get(value)).toBe(null)
|
||||
expect(get(error)).toBe(null)
|
||||
|
||||
await vi.runOnlyPendingTimersAsync()
|
||||
|
||||
expect(get(pending)).toBe(false)
|
||||
expect(get(value)).toBe(1)
|
||||
expect(get(error)).toBe(null)
|
||||
})
|
||||
|
||||
it('correctly updates each store for rejected initial promises', async () => {
|
||||
const { pending, value, error, set } = createPromiseStore<number>()
|
||||
set(Promise.reject(1))
|
||||
|
||||
expect(get(pending)).toBe(true)
|
||||
expect(get(value)).toBe(null)
|
||||
expect(get(error)).toBe(null)
|
||||
|
||||
await vi.runOnlyPendingTimersAsync()
|
||||
|
||||
expect(get(pending)).toBe(false)
|
||||
expect(get(value)).toBe(null)
|
||||
expect(get(error)).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('updates', () => {
|
||||
it('updates the store values when a new promise is set', async () => {
|
||||
const { pending, value, error, set } = createPromiseStore<number>()
|
||||
set(Promise.resolve(1))
|
||||
await vi.runOnlyPendingTimersAsync()
|
||||
expect(get(pending)).toBe(false)
|
||||
|
||||
set(Promise.reject(2))
|
||||
expect(get(pending)).toBe(true)
|
||||
|
||||
await vi.runOnlyPendingTimersAsync()
|
||||
|
||||
expect(get(pending)).toBe(false)
|
||||
expect(get(value)).toBe(null)
|
||||
expect(get(error)).toBe(2)
|
||||
|
||||
set(Promise.resolve(3))
|
||||
expect(get(pending)).toBe(true)
|
||||
|
||||
await vi.runOnlyPendingTimersAsync()
|
||||
|
||||
expect(get(pending)).toBe(false)
|
||||
expect(get(value)).toBe(3)
|
||||
expect(get(error)).toBe(null)
|
||||
})
|
||||
|
||||
it('updates the store with the latest resolved promise', async () => {
|
||||
const { pending, value, set } = createPromiseStore<number>()
|
||||
set(Promise.resolve(1))
|
||||
set(Promise.resolve(2))
|
||||
|
||||
await vi.runOnlyPendingTimersAsync()
|
||||
|
||||
expect(get(pending)).toBe(false)
|
||||
expect(get(value)).toBe(2)
|
||||
})
|
||||
|
||||
it('retains the old value while a new promise is resolved', async () => {
|
||||
const { pending, value, latestValue, set } = createPromiseStore<number>()
|
||||
set(Promise.resolve(1))
|
||||
await vi.runOnlyPendingTimersAsync()
|
||||
|
||||
set(Promise.resolve(2))
|
||||
|
||||
expect(get(pending)).toBe(true)
|
||||
expect(get(value)).toBe(null)
|
||||
expect(get(latestValue)).toBe(1)
|
||||
})
|
||||
|
||||
it('retains the old error while a new promise is resolved', async () => {
|
||||
const { pending, error, latestError, set } = createPromiseStore<number>()
|
||||
set(Promise.reject(1))
|
||||
await vi.runOnlyPendingTimersAsync()
|
||||
|
||||
set(Promise.resolve(2))
|
||||
|
||||
expect(get(pending)).toBe(true)
|
||||
expect(get(error)).toBe(null)
|
||||
expect(get(latestError)).toBe(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
92
client/web-sveltekit/src/lib/utils/promises.ts
Normal file
92
client/web-sveltekit/src/lib/utils/promises.ts
Normal file
@ -0,0 +1,92 @@
|
||||
import { type Readable, writable, readonly, derived } from 'svelte/store'
|
||||
|
||||
interface PromiseStore<D, E = Error> {
|
||||
/**
|
||||
* True when the promise is pending, false otherwise.
|
||||
* Initial value: false
|
||||
*/
|
||||
pending: Readable<boolean>
|
||||
/**
|
||||
* The current value or null if the current promise was rejected or is pending.
|
||||
* Initial value: null
|
||||
*/
|
||||
value: Readable<D | null>
|
||||
/**
|
||||
* The current error or null if the current promise was resolved or is pending.
|
||||
* Initial value: null
|
||||
*/
|
||||
error: Readable<E | null>
|
||||
/**
|
||||
* The value of the latest settled promise. While a new promise is pending this will contain
|
||||
* the value of the previously settled promise (or null if the promise was rejected).
|
||||
* Initial value: null
|
||||
*/
|
||||
latestValue: Readable<D | null>
|
||||
/**
|
||||
* The value of the latest promise. While a new promise is pending this will contain
|
||||
* the value of the previously settled promise (or null if the promise was resolved).
|
||||
* Initial value: null
|
||||
*/
|
||||
latestError: Readable<E | null>
|
||||
/**
|
||||
* Sets the passed promise as the current promise and tracks its status.
|
||||
* Does nothing if the same promise as the current one is passed. The argument
|
||||
* is optional to make it easier to work with optional data coming from loaders.
|
||||
*/
|
||||
set: (promise?: Promise<D> | null) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns multiple stores to track the promises state, resolved value and rejection error.
|
||||
* The store ensures that `value` is updated with latest resolved promise.
|
||||
*/
|
||||
export function createPromiseStore<D, E = Error>(): PromiseStore<Awaited<D>, E> {
|
||||
let currentPromise: Promise<Awaited<D>> | null | undefined
|
||||
|
||||
const pending = writable<boolean>(false)
|
||||
const value = writable<Awaited<D> | null>(null)
|
||||
const error = writable<E | null>(null)
|
||||
|
||||
function resolve(promise?: Promise<Awaited<D>> | null) {
|
||||
currentPromise = promise
|
||||
if (!promise) {
|
||||
value.set(null)
|
||||
error.set(null)
|
||||
pending.set(false)
|
||||
return
|
||||
}
|
||||
|
||||
pending.set(true)
|
||||
promise.then(
|
||||
result => {
|
||||
if (currentPromise === promise) {
|
||||
value.set(result)
|
||||
error.set(null)
|
||||
pending.set(false)
|
||||
}
|
||||
},
|
||||
errorValue => {
|
||||
if (currentPromise === promise) {
|
||||
value.set(null)
|
||||
error.set(errorValue)
|
||||
pending.set(false)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
resolve(currentPromise)
|
||||
|
||||
return {
|
||||
pending: readonly(pending),
|
||||
value: derived([pending, value], ([$pending, $value]) => ($pending ? null : $value)),
|
||||
error: derived([pending, error], ([$pending, $error]) => ($pending ? null : $error)),
|
||||
latestValue: readonly(value),
|
||||
latestError: readonly(error),
|
||||
set: promise => {
|
||||
if (promise !== currentPromise) {
|
||||
resolve(promise)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
41
client/web-sveltekit/src/lib/utils/stores.test.ts
Normal file
41
client/web-sveltekit/src/lib/utils/stores.test.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { get, writable } from 'svelte/store'
|
||||
import { describe, it, expect } from 'vitest'
|
||||
|
||||
import { createForwardStore } from './stores'
|
||||
|
||||
describe('createForwardStore', () => {
|
||||
it('syncs the initial value of the passed store', () => {
|
||||
const store = createForwardStore(writable(1))
|
||||
expect(get(store)).toBe(1)
|
||||
})
|
||||
|
||||
it('updates when the passed store updates', () => {
|
||||
const origin = writable(1)
|
||||
const store = createForwardStore(origin)
|
||||
|
||||
origin.set(2)
|
||||
|
||||
expect(get(store)).toBe(2)
|
||||
})
|
||||
|
||||
it('syncs with a new store', () => {
|
||||
const origin = writable(1)
|
||||
const store = createForwardStore(origin)
|
||||
store.updateStore(writable(2))
|
||||
|
||||
// Update the original store to verify that the forward store doesn't
|
||||
// subscribe to it anymore
|
||||
origin.set(3)
|
||||
|
||||
expect(get(store)).toBe(2)
|
||||
})
|
||||
|
||||
it('updates the original store', () => {
|
||||
const origin = writable(1)
|
||||
const store = createForwardStore(origin)
|
||||
|
||||
store.set(2)
|
||||
|
||||
expect(get(origin)).toBe(2)
|
||||
})
|
||||
})
|
||||
30
client/web-sveltekit/src/lib/utils/stores.ts
Normal file
30
client/web-sveltekit/src/lib/utils/stores.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { get, writable, type Unsubscriber, type Writable } from 'svelte/store'
|
||||
|
||||
/**
|
||||
* Returns a helper store that syncs with the currently set store.
|
||||
*/
|
||||
export function createForwardStore<T>(store: Writable<T>): Writable<T> & { updateStore(store: Writable<T>): void } {
|
||||
const { subscribe, set } = writable<T>(get(store), () => link(store))
|
||||
|
||||
let unsubscribe: Unsubscriber | null = null
|
||||
function link(store: Writable<T>): Unsubscriber {
|
||||
unsubscribe?.()
|
||||
return (unsubscribe = store.subscribe(set))
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set(value) {
|
||||
store.set(value)
|
||||
},
|
||||
update(value) {
|
||||
store.update(value)
|
||||
},
|
||||
updateStore(newStore) {
|
||||
if (newStore !== store) {
|
||||
store = newStore
|
||||
link(store)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
68
client/web-sveltekit/src/lib/utils/time.test.ts
Normal file
68
client/web-sveltekit/src/lib/utils/time.test.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { faker } from '@faker-js/faker'
|
||||
import { it, vi, beforeAll, afterAll, expect, describe } from 'vitest'
|
||||
|
||||
import { getRelativeTime } from './time'
|
||||
|
||||
const defaults = {
|
||||
Y: 2023,
|
||||
M: 5,
|
||||
D: 14,
|
||||
h: 12,
|
||||
m: 30,
|
||||
s: 30,
|
||||
}
|
||||
|
||||
function d(options?: Partial<typeof defaults>): Date {
|
||||
const combined = { ...defaults, ...options }
|
||||
return new Date(combined.Y, combined.M, combined.D, combined.h, combined.m, combined.s)
|
||||
}
|
||||
|
||||
beforeAll(() => {
|
||||
vi.useFakeTimers()
|
||||
vi.setSystemTime(d())
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
describe('getRelativeTime', () => {
|
||||
it('uses the current time as reference by default', () => {
|
||||
expect(getRelativeTime(d({ h: 3 }))).toMatchInlineSnapshot('"9 hours ago"')
|
||||
})
|
||||
|
||||
it('uses the provided reference date', () => {
|
||||
expect(getRelativeTime(d({ D: 5 }), d({ D: 10 }))).toMatchInlineSnapshot('"5 days ago"')
|
||||
})
|
||||
|
||||
describe('specific times', () => {
|
||||
it.each([
|
||||
['last second', d({ s: 29 })],
|
||||
['seconds', d({ s: 5 })],
|
||||
['last minute', d({ m: 29 })],
|
||||
['minutes', d({ m: 5 })],
|
||||
['last hour', d({ h: 11 })],
|
||||
['hours', d({ h: 5 })],
|
||||
['last day', d({ D: 13 })],
|
||||
['days', d({ D: 2 })],
|
||||
['last month', d({ M: 4 })],
|
||||
['months', d({ M: 1 })],
|
||||
['last year', d({ Y: 2022 })],
|
||||
['years', d({ Y: 2015 })],
|
||||
])('%s', (_, date) => {
|
||||
expect(getRelativeTime(date)).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
||||
it('random times', () => {
|
||||
faker.seed(42)
|
||||
faker.setDefaultRefDate(d())
|
||||
|
||||
for (const date of faker.date.betweens({ from: d({ Y: 2021 }), to: d(), count: 10 })) {
|
||||
expect(getRelativeTime(date)).toMatchSnapshot()
|
||||
}
|
||||
|
||||
faker.seed()
|
||||
faker.setDefaultRefDate()
|
||||
})
|
||||
})
|
||||
@ -53,7 +53,7 @@
|
||||
$: ({ repoName, revision, parentPath, resolvedRevision } = data)
|
||||
$: commitID = isErrorLike(resolvedRevision) ? '' : resolvedRevision.commitID
|
||||
// Only update the file tree provider (which causes the tree to rerender) when repo, revision/commit or file path
|
||||
// changes
|
||||
// update
|
||||
$: updateFileTreeProvider(repoName, revision, commitID, parentPath)
|
||||
|
||||
const sidebarSize = getSeparatorPosition('repo-sidebar', 0.2)
|
||||
|
||||
@ -8,14 +8,20 @@
|
||||
import { NODE_LIMIT } from '$lib/repo/api/tree'
|
||||
import SidebarToggleButton from '$lib/repo/SidebarToggleButton.svelte'
|
||||
import { sidebarOpen } from '$lib/repo/stores'
|
||||
import { asStore } from '$lib/utils'
|
||||
import { createPromiseStore } from '$lib/utils'
|
||||
|
||||
import type { PageData } from './$types'
|
||||
|
||||
export let data: PageData
|
||||
|
||||
$: treeEntries = asStore(data.fileTree.deferred.then(({ values }) => values))
|
||||
$: commits = asStore(data.commits.deferred)
|
||||
const { value: treeOrError, set: setTree } = createPromiseStore<typeof data.fileTree.deferred>()
|
||||
const {
|
||||
pending: loadingCommits,
|
||||
value: commits,
|
||||
set: setCommits,
|
||||
} = createPromiseStore<typeof data.commits.deferred>()
|
||||
$: setTree(data.fileTree.deferred)
|
||||
$: setCommits(data.commits.deferred)
|
||||
</script>
|
||||
|
||||
{#if !$sidebarOpen}
|
||||
@ -32,10 +38,10 @@
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
{#if !$treeEntries.loading && $treeEntries.data}
|
||||
{#if $treeOrError && !isErrorLike($treeOrError)}
|
||||
<h3>Files and directories</h3>
|
||||
<ul class="files">
|
||||
{#each $treeEntries.data as entry}
|
||||
{#each $treeOrError.values as entry}
|
||||
<li>
|
||||
{#if entry !== NODE_LIMIT}
|
||||
<a
|
||||
@ -53,10 +59,10 @@
|
||||
|
||||
<h3 class="mt-3">Changes</h3>
|
||||
<ul class="commits">
|
||||
{#if $commits.loading}
|
||||
{#if $loadingCommits}
|
||||
<LoadingSpinner />
|
||||
{:else if $commits.data}
|
||||
{#each $commits.data as commit (commit.url)}
|
||||
{:else if $commits}
|
||||
{#each $commits as commit (commit.url)}
|
||||
<li><Commit {commit} /></li>
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
|
||||
import { page } from '$app/stores'
|
||||
import CodeMirrorBlob from '$lib/CodeMirrorBlob.svelte'
|
||||
import type { BlobFileFields } from '$lib/graphql-operations'
|
||||
import Icon from '$lib/Icon.svelte'
|
||||
import FileHeader from '$lib/repo/FileHeader.svelte'
|
||||
import { asStore } from '$lib/utils'
|
||||
import { createPromiseStore } from '$lib/utils'
|
||||
|
||||
import type { PageData } from './$types'
|
||||
import FormatAction from './FormatAction.svelte'
|
||||
@ -14,14 +13,13 @@
|
||||
|
||||
export let data: PageData
|
||||
|
||||
$: blob = asStore(data.blob.deferred)
|
||||
$: highlights = asStore(data.highlights.deferred)
|
||||
$: loading = $blob.loading
|
||||
let blobData: BlobFileFields
|
||||
$: if (!$blob.loading && $blob.data) {
|
||||
blobData = $blob.data
|
||||
}
|
||||
$: formatted = !!blobData?.richHTML
|
||||
// We use the latest value here because we want to keep showing the old document while loading
|
||||
// the new one.
|
||||
const { pending: loading, latestValue: blobData, set: setBlob } = createPromiseStore<typeof data.blob.deferred>()
|
||||
const { value: highlights, set: setHighlights } = createPromiseStore<typeof data.highlights.deferred>()
|
||||
$: setBlob(data.blob.deferred)
|
||||
$: setHighlights(data.highlights.deferred)
|
||||
$: formatted = !!$blobData?.richHTML
|
||||
$: showRaw = $page.url.searchParams.get('view') === 'raw'
|
||||
</script>
|
||||
|
||||
@ -37,18 +35,15 @@
|
||||
</svelte:fragment>
|
||||
</FileHeader>
|
||||
|
||||
<div class="content" class:loading>
|
||||
{#if blobData}
|
||||
{#if blobData.richHTML && !showRaw}
|
||||
<div class="content" class:loading={$loading}>
|
||||
{#if $blobData}
|
||||
{#if $blobData.richHTML && !showRaw}
|
||||
<div class="rich">
|
||||
{@html blobData.richHTML}
|
||||
{@html $blobData.richHTML}
|
||||
</div>
|
||||
{:else}
|
||||
<CodeMirrorBlob
|
||||
blob={blobData}
|
||||
highlights={($highlights && !$highlights.loading && $highlights.data) || ''}
|
||||
wrapLines={$lineWrap}
|
||||
/>
|
||||
<!-- TODO: ensure that only the highlights for the currently loaded blob data are used -->
|
||||
<CodeMirrorBlob blob={$blobData} highlights={$highlights || ''} wrapLines={$lineWrap} />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@ -4,15 +4,15 @@
|
||||
import { isErrorLike } from '$lib/common'
|
||||
import Icon from '$lib/Icon.svelte'
|
||||
import FileHeader from '$lib/repo/FileHeader.svelte'
|
||||
import { asStore } from '$lib/utils'
|
||||
import { createPromiseStore } from '$lib/utils'
|
||||
|
||||
import type { PageData } from './$types'
|
||||
|
||||
export let data: PageData
|
||||
|
||||
$: treeDataStatus = asStore(data.treeEntries.deferred)
|
||||
$: treeOrError = (!$treeDataStatus.loading && $treeDataStatus.data) || null
|
||||
$: entries = treeOrError && !isErrorLike(treeOrError) ? treeOrError.entries : []
|
||||
const { value: treeOrError, set } = createPromiseStore<typeof data.treeEntries.deferred>()
|
||||
$: set(data.treeEntries.deferred)
|
||||
$: entries = $treeOrError && !isErrorLike($treeOrError) ? $treeOrError.entries : []
|
||||
</script>
|
||||
|
||||
<FileHeader>
|
||||
@ -22,16 +22,14 @@
|
||||
<div class="content">
|
||||
<h2>Files and directories</h2>
|
||||
<ul>
|
||||
{#if treeOrError}
|
||||
{#each entries as entry}
|
||||
<li>
|
||||
<a href={entry.url}>
|
||||
<Icon svgPath={entry.isDirectory ? mdiFolderOutline : mdiFileDocumentOutline} inline />
|
||||
{entry.name}
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
{/if}
|
||||
{#each entries as entry}
|
||||
<li>
|
||||
<a href={entry.url}>
|
||||
<Icon svgPath={entry.isDirectory ? mdiFolderOutline : mdiFileDocumentOutline} inline />
|
||||
{entry.name}
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
@ -2,13 +2,13 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { mdiFileCodeOutline, mdiFolderArrowUpOutline, mdiFolderOpenOutline, mdiFolderOutline } from '@mdi/js'
|
||||
import { onMount, tick } from 'svelte'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
import type { TreeEntryFields } from '@sourcegraph/shared/src/graphql-operations'
|
||||
|
||||
import { afterNavigate, goto } from '$app/navigation'
|
||||
import Icon from '$lib/Icon.svelte'
|
||||
import { type FileTreeProvider, NODE_LIMIT } from '$lib/repo/api/tree'
|
||||
import { type FileTreeProvider, NODE_LIMIT, type FileTreeNodeValue } from '$lib/repo/api/tree'
|
||||
import { getSidebarFileTreeStateForRepo } from '$lib/repo/stores'
|
||||
import TreeView, { setTreeContext } from '$lib/TreeView.svelte'
|
||||
import { createForwardStore } from '$lib/utils'
|
||||
@ -82,7 +82,7 @@
|
||||
treeView.scrollSelectedItemIntoView()
|
||||
}
|
||||
|
||||
let treeView: TreeView<FileTreeProvider>
|
||||
let treeView: TreeView<FileTreeNodeValue>
|
||||
let repoName = treeProvider.getRepoName()
|
||||
// Since context is only set once when the component is created
|
||||
// we need to dynamically sync any changes to the corresponding
|
||||
|
||||
@ -1,39 +1,40 @@
|
||||
<script lang="ts">
|
||||
import LoadingSpinner from '$lib/LoadingSpinner.svelte'
|
||||
import GitReference from '$lib/repo/GitReference.svelte'
|
||||
import { asStore } from '$lib/utils'
|
||||
import { createPromiseStore } from '$lib/utils'
|
||||
|
||||
import type { PageData } from './$types'
|
||||
|
||||
export let data: PageData
|
||||
|
||||
$: branches = asStore(data.branches.deferred)
|
||||
$: defaultBranch = !$branches.loading && $branches.data ? $branches.data.defaultBranch : null
|
||||
$: activeBranches = !$branches.loading && $branches.data ? $branches.data.activeBranches : null
|
||||
const { pending, value: branches, set } = createPromiseStore<typeof data.branches.deferred>()
|
||||
$: set(data.branches.deferred)
|
||||
$: defaultBranch = $branches?.defaultBranch
|
||||
$: activeBranches = $branches?.activeBranches
|
||||
</script>
|
||||
|
||||
{#if $branches.loading}
|
||||
{#if $pending}
|
||||
<LoadingSpinner />
|
||||
{:else if $branches.data}
|
||||
{#if defaultBranch}
|
||||
<table class="mb-3">
|
||||
<thead><tr><th colspan="3">Default branch</th></tr></thead>
|
||||
<tbody>
|
||||
<GitReference ref={defaultBranch} />
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if activeBranches && activeBranches.length > 0}
|
||||
<table>
|
||||
<thead><tr><th colspan="3">Active branches</th></tr></thead>
|
||||
<tbody>
|
||||
{#each activeBranches as branch (branch.id)}
|
||||
<GitReference ref={branch} />
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
{#if defaultBranch}
|
||||
<table class="mb-3">
|
||||
<thead><tr><th colspan="3">Default branch</th></tr></thead>
|
||||
<tbody>
|
||||
<GitReference ref={defaultBranch} />
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
|
||||
{#if activeBranches && activeBranches.length > 0}
|
||||
<table>
|
||||
<thead><tr><th colspan="3">Active branches</th></tr></thead>
|
||||
<tbody>
|
||||
{#each activeBranches as branch (branch.id)}
|
||||
<GitReference ref={branch} />
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
<script lang="ts">
|
||||
import LoadingSpinner from '$lib/LoadingSpinner.svelte'
|
||||
import GitReference from '$lib/repo/GitReference.svelte'
|
||||
import { asStore } from '$lib/utils'
|
||||
import { createPromiseStore } from '$lib/utils'
|
||||
|
||||
import type { PageData } from './$types'
|
||||
|
||||
export let data: PageData
|
||||
|
||||
$: branches = asStore(data.branches.deferred)
|
||||
$: nodes = !$branches.loading && $branches.data ? $branches.data.nodes : null
|
||||
$: total = !$branches.loading && $branches.data ? $branches.data.totalCount : null
|
||||
const { pending, value: branches, set } = createPromiseStore<typeof data.branches.deferred>()
|
||||
$: set(data.branches.deferred)
|
||||
$: nodes = $branches?.nodes
|
||||
$: total = $branches?.totalCount
|
||||
</script>
|
||||
|
||||
{#if $branches.loading}
|
||||
{#if $pending}
|
||||
<LoadingSpinner />
|
||||
{:else if nodes}
|
||||
<!-- TODO: Search input to filter branches by name -->
|
||||
|
||||
@ -1,40 +1,43 @@
|
||||
<script lang="ts">
|
||||
import Commit from '$lib/Commit.svelte'
|
||||
import LoadingSpinner from '$lib/LoadingSpinner.svelte'
|
||||
import { asStore } from '$lib/utils'
|
||||
import { createPromiseStore } from '$lib/utils'
|
||||
|
||||
import type { PageData } from './$types'
|
||||
import FileDiff from './FileDiff.svelte'
|
||||
|
||||
export let data: PageData
|
||||
|
||||
$: commit = asStore(data.commit.deferred)
|
||||
$: diff = asStore(data.diff.deferred)
|
||||
const { pending: commitPending, value: commit, set: setCommit } = createPromiseStore<typeof data.commit.deferred>()
|
||||
$: setCommit(data.commit.deferred)
|
||||
const { pending: diffPending, value: diff, set: setDiff } = createPromiseStore<typeof data.diff.deferred>()
|
||||
$: setDiff(data.diff.deferred)
|
||||
$: pending = $diffPending || $commitPending
|
||||
</script>
|
||||
|
||||
<section>
|
||||
{#if !$commit.loading && $commit.data}
|
||||
{#if $commit}
|
||||
<div class="header">
|
||||
<div class="info"><Commit commit={$commit.data} alwaysExpanded /></div>
|
||||
<div class="info"><Commit commit={$commit} alwaysExpanded /></div>
|
||||
<div>
|
||||
<span>Commit: {$commit.data.abbreviatedOID}</span>
|
||||
<span>Commit: {$commit.abbreviatedOID}</span>
|
||||
<span class="parents">
|
||||
{$commit.data.parents.length} parents:
|
||||
{#each $commit.data.parents as parent}
|
||||
{$commit.parents.length} parents:
|
||||
{#each $commit.parents as parent}
|
||||
<a href={parent.url}>{parent.abbreviatedOID}</a>{' '}
|
||||
{/each}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{#if !$diff.loading && $diff.data}
|
||||
{#if $diff}
|
||||
<ul>
|
||||
{#each $diff.data.nodes as node}
|
||||
{#each $diff.nodes as node}
|
||||
<li><FileDiff fileDiff={node} /></li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if $commit.loading || $diff.loading}
|
||||
{#if pending}
|
||||
<LoadingSpinner />
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
@ -1,23 +1,24 @@
|
||||
<script lang="ts">
|
||||
import Commit from '$lib/Commit.svelte'
|
||||
import { asStore } from '$lib/utils'
|
||||
import { createPromiseStore } from '$lib/utils'
|
||||
|
||||
import type { PageData } from './$types'
|
||||
|
||||
export let data: PageData
|
||||
|
||||
$: commits = asStore(data.commits.deferred)
|
||||
const { pending, value: commits, set } = createPromiseStore<typeof data.commits.deferred>()
|
||||
$: set(data.commits.deferred)
|
||||
</script>
|
||||
|
||||
<section>
|
||||
<div>
|
||||
<h2>View commits from this repsitory</h2>
|
||||
<h3>Changes</h3>
|
||||
{#if $commits.loading}
|
||||
{#if $pending}
|
||||
Loading...
|
||||
{:else if $commits.data}
|
||||
{:else if $commits}
|
||||
<ul>
|
||||
{#each $commits.data as commit (commit.url)}
|
||||
{#each $commits as commit (commit.url)}
|
||||
<li><Commit {commit} /></li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
import { page } from '$app/stores'
|
||||
import LoadingSpinner from '$lib/LoadingSpinner.svelte'
|
||||
import Paginator from '$lib/Paginator.svelte'
|
||||
import { getRelativeTime } from '$lib/relativeTime'
|
||||
import { currentDate } from '$lib/stores'
|
||||
import UserAvatar from '$lib/UserAvatar.svelte'
|
||||
import { asStore } from '$lib/utils'
|
||||
import { createPromiseStore, getRelativeTime } from '$lib/utils'
|
||||
import { Button, ButtonGroup } from '$lib/wildcard'
|
||||
|
||||
import type { PageData } from './$types'
|
||||
@ -20,20 +19,26 @@
|
||||
['All time', ''],
|
||||
]
|
||||
|
||||
$: timePeriod = data.after
|
||||
$: contributorsLoader = asStore(data.deferred.contributors)
|
||||
$: loading = $contributorsLoader.loading
|
||||
let connection: Extract<typeof $contributorsLoader, { loading: false }>['data']
|
||||
$: if (!$contributorsLoader.loading && $contributorsLoader.data) {
|
||||
connection = $contributorsLoader.data
|
||||
const { pending, latestValue: contributors, set } = createPromiseStore<typeof data.deferred.contributors>()
|
||||
$: set(data.deferred.contributors)
|
||||
|
||||
// We want to show stale contributors data when the user navigates to
|
||||
// the next or previous page for the current time period. When the user
|
||||
// changes the time period we want to show a loading indicator instead.
|
||||
let currentContributors = $contributors
|
||||
$: if (!$pending && $contributors) {
|
||||
currentContributors = $contributors
|
||||
}
|
||||
|
||||
$: timePeriod = data.after
|
||||
|
||||
async function setTimePeriod(event: MouseEvent) {
|
||||
const element = event.target as HTMLButtonElement
|
||||
timePeriod = element.dataset.value ?? ''
|
||||
const newURL = new URL($page.url)
|
||||
newURL.search = timePeriod ? `after=${timePeriod}` : ''
|
||||
connection = null
|
||||
// Don't show stale contributors when switching the time period
|
||||
currentContributors = null
|
||||
await goto(newURL)
|
||||
}
|
||||
</script>
|
||||
@ -58,12 +63,12 @@
|
||||
{/each}
|
||||
</ButtonGroup>
|
||||
</form>
|
||||
{#if !connection && loading}
|
||||
{#if !currentContributors && $pending}
|
||||
<div class="mt-3">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
{:else if connection}
|
||||
{@const nodes = connection.nodes}
|
||||
{:else if currentContributors}
|
||||
{@const nodes = currentContributors.nodes}
|
||||
<table class="mt-3">
|
||||
<tbody>
|
||||
{#each nodes as contributor}
|
||||
@ -84,9 +89,9 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="d-flex flex-column align-items-center">
|
||||
<Paginator disabled={loading} pageInfo={connection.pageInfo} />
|
||||
<Paginator disabled={$pending} pageInfo={currentContributors.pageInfo} />
|
||||
<p class="mt-1 text-muted">
|
||||
<small>Total contributors: {connection.totalCount}</small>
|
||||
<small>Total contributors: {currentContributors.totalCount}</small>
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@ -1,20 +1,22 @@
|
||||
<script lang="ts">
|
||||
import LoadingSpinner from '$lib/LoadingSpinner.svelte'
|
||||
import GitReference from '$lib/repo/GitReference.svelte'
|
||||
import { asStore } from '$lib/utils'
|
||||
import { createPromiseStore } from '$lib/utils'
|
||||
|
||||
import type { PageData } from './$types'
|
||||
|
||||
export let data: PageData
|
||||
|
||||
$: tags = asStore(data.tags.deferred)
|
||||
$: nodes = !$tags.loading && $tags.data ? $tags.data.nodes : null
|
||||
$: total = !$tags.loading && $tags.data ? $tags.data.totalCount : null
|
||||
const { pending, value: tags, set } = createPromiseStore<typeof data.tags.deferred>()
|
||||
$: set(data.tags.deferred)
|
||||
|
||||
$: nodes = $tags?.nodes
|
||||
$: total = $tags?.totalCount
|
||||
</script>
|
||||
|
||||
<section>
|
||||
<div>
|
||||
{#if $tags.loading}
|
||||
{#if $pending}
|
||||
<LoadingSpinner />
|
||||
{:else if nodes}
|
||||
<!-- TODO: Search input to filter tags by name -->
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
import { sveltekit } from '@sveltejs/kit/vite'
|
||||
import type { UserConfig } from 'vite'
|
||||
import { defineConfig } from 'vite'
|
||||
|
||||
const config: UserConfig = {
|
||||
const config = defineConfig(({ mode }) => ({
|
||||
plugins: [sveltekit()],
|
||||
define: {
|
||||
'process.platform': '"browser"',
|
||||
'process.env': '{}',
|
||||
},
|
||||
define:
|
||||
mode === 'test'
|
||||
? {}
|
||||
: {
|
||||
'process.platform': '"browser"',
|
||||
'process.env': '{}',
|
||||
},
|
||||
css: {
|
||||
modules: {
|
||||
localsConvention: 'camelCase',
|
||||
@ -29,6 +32,6 @@ const config: UserConfig = {
|
||||
'linguist-languages',
|
||||
],
|
||||
},
|
||||
}
|
||||
}))
|
||||
|
||||
export default config
|
||||
|
||||
325
pnpm-lock.yaml
325
pnpm-lock.yaml
@ -1700,6 +1700,9 @@ importers:
|
||||
specifier: ^1.29.0
|
||||
version: 1.29.0
|
||||
devDependencies:
|
||||
'@faker-js/faker':
|
||||
specifier: ^8.0.2
|
||||
version: 8.0.2
|
||||
'@playwright/test':
|
||||
specifier: 1.25.0
|
||||
version: 1.25.0
|
||||
@ -1772,6 +1775,9 @@ importers:
|
||||
vite:
|
||||
specifier: ^4.3.9
|
||||
version: 4.3.9(@types/node@13.13.5)(sass@1.32.4)
|
||||
vitest:
|
||||
specifier: ^0.33.0
|
||||
version: 0.33.0(jsdom@16.7.0)(sass@1.32.4)
|
||||
|
||||
client/wildcard:
|
||||
dependencies:
|
||||
@ -5611,6 +5617,11 @@ packages:
|
||||
resolution: {integrity: sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
||||
/@faker-js/faker@8.0.2:
|
||||
resolution: {integrity: sha512-Uo3pGspElQW91PCvKSIAXoEgAUlRnH29sX2/p89kg7sP1m2PzCufHINd0FhTXQf6DYGiUlVncdSPa2F9wxed2A==}
|
||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0, npm: '>=6.14.13'}
|
||||
dev: true
|
||||
|
||||
/@fal-works/esbuild-plugin-global-externals@2.1.2:
|
||||
resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==}
|
||||
dev: true
|
||||
@ -11490,7 +11501,7 @@ packages:
|
||||
'@storybook/node-logger': 7.0.26
|
||||
'@storybook/svelte': 7.0.26(svelte@4.0.0)
|
||||
'@sveltejs/vite-plugin-svelte': 2.4.2(svelte@4.0.0)(vite@4.3.9)
|
||||
magic-string: 0.30.0
|
||||
magic-string: 0.30.1
|
||||
svelte: 4.0.0
|
||||
sveltedoc-parser: 4.2.1
|
||||
ts-dedent: 2.2.0
|
||||
@ -11715,7 +11726,7 @@ packages:
|
||||
devalue: 4.3.2
|
||||
esm-env: 1.0.0
|
||||
kleur: 4.1.5
|
||||
magic-string: 0.30.0
|
||||
magic-string: 0.30.1
|
||||
mime: 3.0.0
|
||||
sade: 1.8.1
|
||||
set-cookie-parser: 2.6.0
|
||||
@ -11754,7 +11765,7 @@ packages:
|
||||
debug: 4.3.4
|
||||
deepmerge: 4.3.1
|
||||
kleur: 4.1.5
|
||||
magic-string: 0.30.0
|
||||
magic-string: 0.30.1
|
||||
svelte: 4.0.0
|
||||
svelte-hmr: 0.15.2(svelte@4.0.0)
|
||||
vite: 4.3.9(@types/node@13.13.5)(sass@1.32.4)
|
||||
@ -12080,6 +12091,16 @@ packages:
|
||||
- webpack-cli
|
||||
dev: true
|
||||
|
||||
/@types/chai-subset@1.3.3:
|
||||
resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==}
|
||||
dependencies:
|
||||
'@types/chai': 4.3.5
|
||||
dev: true
|
||||
|
||||
/@types/chai@4.3.5:
|
||||
resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==}
|
||||
dev: true
|
||||
|
||||
/@types/chrome@0.0.106:
|
||||
resolution: {integrity: sha512-sCQa+QJL/Kl+6ngU4xD1VjTFIkQDizOHN94zbb7byK9D3U79x/KXjqXyS7lHoa2q9xw3bWePb+giLhBKOILRuA==}
|
||||
dependencies:
|
||||
@ -13281,7 +13302,7 @@ packages:
|
||||
find-up: 5.0.0
|
||||
javascript-stringify: 2.1.0
|
||||
lodash: 4.17.21
|
||||
mlly: 1.3.0
|
||||
mlly: 1.4.0
|
||||
outdent: 0.8.0
|
||||
vite: 4.3.9(@types/node@13.13.5)(sass@1.32.4)
|
||||
vite-node: 0.28.5(@types/node@13.13.5)(sass@1.32.4)
|
||||
@ -13510,6 +13531,44 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@vitest/expect@0.33.0:
|
||||
resolution: {integrity: sha512-sVNf+Gla3mhTCxNJx+wJLDPp/WcstOe0Ksqz4Vec51MmgMth/ia0MGFEkIZmVGeTL5HtjYR4Wl/ZxBxBXZJTzQ==}
|
||||
dependencies:
|
||||
'@vitest/spy': 0.33.0
|
||||
'@vitest/utils': 0.33.0
|
||||
chai: 4.3.7
|
||||
dev: true
|
||||
|
||||
/@vitest/runner@0.33.0:
|
||||
resolution: {integrity: sha512-UPfACnmCB6HKRHTlcgCoBh6ppl6fDn+J/xR8dTufWiKt/74Y9bHci5CKB8tESSV82zKYtkBJo9whU3mNvfaisg==}
|
||||
dependencies:
|
||||
'@vitest/utils': 0.33.0
|
||||
p-limit: 4.0.0
|
||||
pathe: 1.1.1
|
||||
dev: true
|
||||
|
||||
/@vitest/snapshot@0.33.0:
|
||||
resolution: {integrity: sha512-tJjrl//qAHbyHajpFvr8Wsk8DIOODEebTu7pgBrP07iOepR5jYkLFiqLq2Ltxv+r0uptUb4izv1J8XBOwKkVYA==}
|
||||
dependencies:
|
||||
magic-string: 0.30.1
|
||||
pathe: 1.1.1
|
||||
pretty-format: 29.5.0
|
||||
dev: true
|
||||
|
||||
/@vitest/spy@0.33.0:
|
||||
resolution: {integrity: sha512-Kv+yZ4hnH1WdiAkPUQTpRxW8kGtH8VRTnus7ZTGovFYM1ZezJpvGtb9nPIjPnptHbsyIAxYZsEpVPYgtpjGnrg==}
|
||||
dependencies:
|
||||
tinyspy: 2.1.1
|
||||
dev: true
|
||||
|
||||
/@vitest/utils@0.33.0:
|
||||
resolution: {integrity: sha512-pF1w22ic965sv+EN6uoePkAOTkAPWM03Ri/jXNyMIKBb/XHLDPfhLvf/Fa9g0YECevAIz56oVYXhodLvLQ/awA==}
|
||||
dependencies:
|
||||
diff-sequences: 29.4.3
|
||||
loupe: 2.3.6
|
||||
pretty-format: 29.5.0
|
||||
dev: true
|
||||
|
||||
/@vscode/codicons@0.0.29:
|
||||
resolution: {integrity: sha512-AXhTv1nl3r4W5DqAfXXKiawQNW+tLBNlXn/GcsnFCL0j17sQ2AY+az9oB9K6wjkibq1fndNJvmT8RYN712Fdww==}
|
||||
dev: false
|
||||
@ -13886,12 +13945,12 @@ packages:
|
||||
acorn: 7.4.1
|
||||
acorn-walk: 7.2.0
|
||||
|
||||
/acorn-import-assertions@1.8.0(acorn@8.8.2):
|
||||
/acorn-import-assertions@1.8.0(acorn@8.10.0):
|
||||
resolution: {integrity: sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==}
|
||||
peerDependencies:
|
||||
acorn: ^8
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
|
||||
/acorn-jsx@5.3.2(acorn@7.4.1):
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
@ -13901,12 +13960,12 @@ packages:
|
||||
acorn: 7.4.1
|
||||
dev: true
|
||||
|
||||
/acorn-jsx@5.3.2(acorn@8.8.2):
|
||||
/acorn-jsx@5.3.2(acorn@8.10.0):
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
peerDependencies:
|
||||
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
|
||||
/acorn-walk@7.2.0:
|
||||
resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==}
|
||||
@ -13921,8 +13980,8 @@ packages:
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
|
||||
/acorn@8.8.2:
|
||||
resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
|
||||
/acorn@8.10.0:
|
||||
resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
|
||||
@ -14430,6 +14489,10 @@ packages:
|
||||
util: 0.12.5
|
||||
dev: true
|
||||
|
||||
/assertion-error@1.1.0:
|
||||
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
|
||||
dev: true
|
||||
|
||||
/assign-symbols@1.0.0:
|
||||
resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -15668,6 +15731,19 @@ packages:
|
||||
resolution: {integrity: sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==}
|
||||
dev: true
|
||||
|
||||
/chai@4.3.7:
|
||||
resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==}
|
||||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
assertion-error: 1.1.0
|
||||
check-error: 1.0.2
|
||||
deep-eql: 4.1.3
|
||||
get-func-name: 2.0.0
|
||||
loupe: 2.3.6
|
||||
pathval: 1.1.1
|
||||
type-detect: 4.0.8
|
||||
dev: true
|
||||
|
||||
/chalk@1.1.3:
|
||||
resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -15782,6 +15858,10 @@ packages:
|
||||
/charenc@0.0.2:
|
||||
resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==}
|
||||
|
||||
/check-error@1.0.2:
|
||||
resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==}
|
||||
dev: true
|
||||
|
||||
/cheerio-select@2.1.0:
|
||||
resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==}
|
||||
dependencies:
|
||||
@ -16195,7 +16275,7 @@ packages:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.4.15
|
||||
'@types/estree': 1.0.0
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
estree-walker: 3.0.3
|
||||
periscopic: 3.1.0
|
||||
dev: true
|
||||
@ -17744,6 +17824,13 @@ packages:
|
||||
resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==}
|
||||
dev: true
|
||||
|
||||
/deep-eql@4.1.3:
|
||||
resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
|
||||
engines: {node: '>=6'}
|
||||
dependencies:
|
||||
type-detect: 4.0.8
|
||||
dev: true
|
||||
|
||||
/deep-extend@0.6.0:
|
||||
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
|
||||
engines: {node: '>=4.0.0'}
|
||||
@ -18022,6 +18109,11 @@ packages:
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
|
||||
dev: true
|
||||
|
||||
/diff-sequences@29.4.3:
|
||||
resolution: {integrity: sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
dev: true
|
||||
|
||||
/diff@4.0.2:
|
||||
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
@ -19251,8 +19343,8 @@ packages:
|
||||
resolution: {integrity: sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn-jsx: 5.3.2(acorn@8.8.2)
|
||||
acorn: 8.10.0
|
||||
acorn-jsx: 5.3.2(acorn@8.10.0)
|
||||
eslint-visitor-keys: 3.4.1
|
||||
dev: true
|
||||
|
||||
@ -19260,8 +19352,8 @@ packages:
|
||||
resolution: {integrity: sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn-jsx: 5.3.2(acorn@8.8.2)
|
||||
acorn: 8.10.0
|
||||
acorn-jsx: 5.3.2(acorn@8.10.0)
|
||||
eslint-visitor-keys: 3.4.1
|
||||
|
||||
/esprima@4.0.1:
|
||||
@ -20365,6 +20457,10 @@ packages:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
|
||||
/get-func-name@2.0.0:
|
||||
resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==}
|
||||
dev: true
|
||||
|
||||
/get-intrinsic@1.2.1:
|
||||
resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==}
|
||||
dependencies:
|
||||
@ -23725,7 +23821,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
abab: 2.0.6
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
acorn-globals: 6.0.0
|
||||
cssom: 0.4.4
|
||||
cssstyle: 2.3.0
|
||||
@ -23767,7 +23863,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
abab: 2.0.6
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
acorn-globals: 6.0.0
|
||||
cssom: 0.5.0
|
||||
cssstyle: 2.3.0
|
||||
@ -24375,6 +24471,11 @@ packages:
|
||||
resolution: {integrity: sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==}
|
||||
engines: {node: '>= 12.13.0'}
|
||||
|
||||
/local-pkg@0.4.3:
|
||||
resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
|
||||
engines: {node: '>=14'}
|
||||
dev: true
|
||||
|
||||
/locate-character@3.0.0:
|
||||
resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
|
||||
dev: true
|
||||
@ -24615,6 +24716,12 @@ packages:
|
||||
signal-exit: 3.0.7
|
||||
dev: true
|
||||
|
||||
/loupe@2.3.6:
|
||||
resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
|
||||
dependencies:
|
||||
get-func-name: 2.0.0
|
||||
dev: true
|
||||
|
||||
/lower-case-first@2.0.2:
|
||||
resolution: {integrity: sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==}
|
||||
dependencies:
|
||||
@ -24700,8 +24807,8 @@ packages:
|
||||
'@jridgewell/sourcemap-codec': 1.4.15
|
||||
dev: true
|
||||
|
||||
/magic-string@0.30.0:
|
||||
resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==}
|
||||
/magic-string@0.30.1:
|
||||
resolution: {integrity: sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.4.15
|
||||
@ -25718,8 +25825,8 @@ packages:
|
||||
/micromark-extension-mdxjs@1.0.1:
|
||||
resolution: {integrity: sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==}
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn-jsx: 5.3.2(acorn@8.8.2)
|
||||
acorn: 8.10.0
|
||||
acorn-jsx: 5.3.2(acorn@8.10.0)
|
||||
micromark-extension-mdx-expression: 1.0.8
|
||||
micromark-extension-mdx-jsx: 1.0.5
|
||||
micromark-extension-mdx-md: 1.0.1
|
||||
@ -26100,10 +26207,10 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
/mlly@1.3.0:
|
||||
resolution: {integrity: sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==}
|
||||
/mlly@1.4.0:
|
||||
resolution: {integrity: sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==}
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
pathe: 1.1.1
|
||||
pkg-types: 1.0.3
|
||||
ufo: 1.1.2
|
||||
@ -27091,6 +27198,13 @@ packages:
|
||||
dependencies:
|
||||
yocto-queue: 0.1.0
|
||||
|
||||
/p-limit@4.0.0:
|
||||
resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
yocto-queue: 1.0.0
|
||||
dev: true
|
||||
|
||||
/p-locate@2.0.0:
|
||||
resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==}
|
||||
engines: {node: '>=4'}
|
||||
@ -27452,6 +27566,10 @@ packages:
|
||||
/pathe@1.1.1:
|
||||
resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==}
|
||||
|
||||
/pathval@1.1.1:
|
||||
resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
|
||||
dev: true
|
||||
|
||||
/peek-stream@1.1.3:
|
||||
resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==}
|
||||
dependencies:
|
||||
@ -27555,7 +27673,7 @@ packages:
|
||||
resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==}
|
||||
dependencies:
|
||||
jsonc-parser: 3.2.0
|
||||
mlly: 1.3.0
|
||||
mlly: 1.4.0
|
||||
pathe: 1.1.1
|
||||
|
||||
/playwright-core@1.25.0:
|
||||
@ -28420,7 +28538,6 @@ packages:
|
||||
'@jest/schemas': 29.6.0
|
||||
ansi-styles: 5.2.0
|
||||
react-is: 18.2.0
|
||||
dev: false
|
||||
|
||||
/pretty-format@3.8.0:
|
||||
resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==}
|
||||
@ -30620,6 +30737,10 @@ packages:
|
||||
get-intrinsic: 1.2.1
|
||||
object-inspect: 1.12.3
|
||||
|
||||
/siginfo@2.0.0:
|
||||
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
||||
dev: true
|
||||
|
||||
/signal-exit@3.0.7:
|
||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||
|
||||
@ -31194,6 +31315,10 @@ packages:
|
||||
dependencies:
|
||||
escape-string-regexp: 2.0.0
|
||||
|
||||
/stackback@0.0.2:
|
||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||
dev: true
|
||||
|
||||
/stackframe@1.3.4:
|
||||
resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==}
|
||||
|
||||
@ -31223,6 +31348,10 @@ packages:
|
||||
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
/std-env@3.3.3:
|
||||
resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==}
|
||||
dev: true
|
||||
|
||||
/stdin@0.0.1:
|
||||
resolution: {integrity: sha512-2bacd1TXzqOEsqRa+eEWkRdOSznwptrs4gqFcpMq5tOtmJUGPZd10W5Lam6wQ4YQ/+qjQt4e9u35yXCF6mrlfQ==}
|
||||
dev: true
|
||||
@ -31542,6 +31671,12 @@ packages:
|
||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
/strip-literal@1.0.1:
|
||||
resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==}
|
||||
dependencies:
|
||||
acorn: 8.10.0
|
||||
dev: true
|
||||
|
||||
/strnum@1.0.5:
|
||||
resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==}
|
||||
dev: false
|
||||
@ -31900,7 +32035,7 @@ packages:
|
||||
'@ampproject/remapping': 2.2.1
|
||||
'@jridgewell/sourcemap-codec': 1.4.15
|
||||
'@jridgewell/trace-mapping': 0.3.18
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
aria-query: 5.3.0
|
||||
axobject-query: 3.2.1
|
||||
code-red: 1.0.3
|
||||
@ -31908,7 +32043,7 @@ packages:
|
||||
estree-walker: 3.0.3
|
||||
is-reference: 3.0.1
|
||||
locate-character: 3.0.0
|
||||
magic-string: 0.30.0
|
||||
magic-string: 0.30.1
|
||||
periscopic: 3.1.0
|
||||
dev: true
|
||||
|
||||
@ -32170,7 +32305,7 @@ packages:
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
commander: 2.20.3
|
||||
source-map: 0.6.1
|
||||
source-map-support: 0.5.21
|
||||
@ -32182,7 +32317,7 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.3
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
|
||||
@ -32275,6 +32410,20 @@ packages:
|
||||
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
|
||||
dev: false
|
||||
|
||||
/tinybench@2.5.0:
|
||||
resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==}
|
||||
dev: true
|
||||
|
||||
/tinypool@0.6.0:
|
||||
resolution: {integrity: sha512-FdswUUo5SxRizcBc6b1GSuLpLjisa8N8qMyYoP3rl+bym+QauhtJP5bvZY1ytt8krKGmMLYIRl36HBZfeAoqhQ==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
dev: true
|
||||
|
||||
/tinyspy@2.1.1:
|
||||
resolution: {integrity: sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
dev: true
|
||||
|
||||
/title-case@3.0.3:
|
||||
resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==}
|
||||
dependencies:
|
||||
@ -32509,7 +32658,7 @@ packages:
|
||||
'@tsconfig/node14': 1.0.1
|
||||
'@tsconfig/node16': 1.0.2
|
||||
'@types/node': 13.13.5
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
acorn-walk: 8.2.0
|
||||
arg: 4.1.0
|
||||
create-require: 1.1.1
|
||||
@ -32539,7 +32688,7 @@ packages:
|
||||
'@tsconfig/node14': 1.0.1
|
||||
'@tsconfig/node16': 1.0.2
|
||||
'@types/node': 13.13.5
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
acorn-walk: 8.2.0
|
||||
arg: 4.1.0
|
||||
create-require: 1.1.1
|
||||
@ -33135,7 +33284,7 @@ packages:
|
||||
/unplugin@0.10.2:
|
||||
resolution: {integrity: sha512-6rk7GUa4ICYjae5PrAllvcDeuT8pA9+j5J5EkxbMFaV+SalHhxZ7X2dohMzu6C3XzsMT+6jwR/+pwPNR3uK9MA==}
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
chokidar: 3.5.3
|
||||
webpack-sources: 3.2.3
|
||||
webpack-virtual-modules: 0.4.6
|
||||
@ -33621,7 +33770,7 @@ packages:
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.3.4
|
||||
mlly: 1.3.0
|
||||
mlly: 1.4.0
|
||||
pathe: 1.1.1
|
||||
picocolors: 1.0.0
|
||||
source-map: 0.6.1
|
||||
@ -33636,6 +33785,27 @@ packages:
|
||||
- supports-color
|
||||
- terser
|
||||
|
||||
/vite-node@0.33.0(@types/node@13.13.5)(sass@1.32.4):
|
||||
resolution: {integrity: sha512-19FpHYbwWWxDr73ruNahC+vtEdza52kA90Qb3La98yZ0xULqV8A5JLNPUff0f5zID4984tW7l3DH2przTJUZSw==}
|
||||
engines: {node: '>=v14.18.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.3.4
|
||||
mlly: 1.4.0
|
||||
pathe: 1.1.1
|
||||
picocolors: 1.0.0
|
||||
vite: 4.3.9(@types/node@13.13.5)(sass@1.32.4)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
- sass
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
dev: true
|
||||
|
||||
/vite@4.3.9(@types/node@13.13.5)(sass@1.32.4):
|
||||
resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
@ -33680,6 +33850,71 @@ packages:
|
||||
vite: 4.3.9(@types/node@13.13.5)(sass@1.32.4)
|
||||
dev: true
|
||||
|
||||
/vitest@0.33.0(jsdom@16.7.0)(sass@1.32.4):
|
||||
resolution: {integrity: sha512-1CxaugJ50xskkQ0e969R/hW47za4YXDUfWJDxip1hwbnhUjYolpfUn2AMOulqG/Dtd9WYAtkHmM/m3yKVrEejQ==}
|
||||
engines: {node: '>=v14.18.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@edge-runtime/vm': '*'
|
||||
'@vitest/browser': '*'
|
||||
'@vitest/ui': '*'
|
||||
happy-dom: '*'
|
||||
jsdom: '*'
|
||||
playwright: '*'
|
||||
safaridriver: '*'
|
||||
webdriverio: '*'
|
||||
peerDependenciesMeta:
|
||||
'@edge-runtime/vm':
|
||||
optional: true
|
||||
'@vitest/browser':
|
||||
optional: true
|
||||
'@vitest/ui':
|
||||
optional: true
|
||||
happy-dom:
|
||||
optional: true
|
||||
jsdom:
|
||||
optional: true
|
||||
playwright:
|
||||
optional: true
|
||||
safaridriver:
|
||||
optional: true
|
||||
webdriverio:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@types/chai': 4.3.5
|
||||
'@types/chai-subset': 1.3.3
|
||||
'@types/node': 13.13.5
|
||||
'@vitest/expect': 0.33.0
|
||||
'@vitest/runner': 0.33.0
|
||||
'@vitest/snapshot': 0.33.0
|
||||
'@vitest/spy': 0.33.0
|
||||
'@vitest/utils': 0.33.0
|
||||
acorn: 8.10.0
|
||||
acorn-walk: 8.2.0
|
||||
cac: 6.7.14
|
||||
chai: 4.3.7
|
||||
debug: 4.3.4
|
||||
jsdom: 16.7.0
|
||||
local-pkg: 0.4.3
|
||||
magic-string: 0.30.1
|
||||
pathe: 1.1.1
|
||||
picocolors: 1.0.0
|
||||
std-env: 3.3.3
|
||||
strip-literal: 1.0.1
|
||||
tinybench: 2.5.0
|
||||
tinypool: 0.6.0
|
||||
vite: 4.3.9(@types/node@13.13.5)(sass@1.32.4)
|
||||
vite-node: 0.33.0(@types/node@13.13.5)(sass@1.32.4)
|
||||
why-is-node-running: 2.2.2
|
||||
transitivePeerDependencies:
|
||||
- less
|
||||
- sass
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
dev: true
|
||||
|
||||
/vlq@1.0.1:
|
||||
resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==}
|
||||
dev: false
|
||||
@ -33690,7 +33925,7 @@ packages:
|
||||
deprecated: The library contains critical security issues and should not be used for production! The maintenance of the project has been discontinued. Consider migrating your code to isolated-vm.
|
||||
hasBin: true
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
acorn-walk: 8.2.0
|
||||
|
||||
/vsce@2.7.0:
|
||||
@ -33858,7 +34093,7 @@ packages:
|
||||
engines: {node: '>= 10.13.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
acorn: 8.8.2
|
||||
acorn: 8.10.0
|
||||
acorn-walk: 8.2.0
|
||||
chalk: 4.1.2
|
||||
commander: 7.2.0
|
||||
@ -34089,8 +34324,8 @@ packages:
|
||||
'@webassemblyjs/ast': 1.11.1
|
||||
'@webassemblyjs/wasm-edit': 1.11.1
|
||||
'@webassemblyjs/wasm-parser': 1.11.1
|
||||
acorn: 8.8.2
|
||||
acorn-import-assertions: 1.8.0(acorn@8.8.2)
|
||||
acorn: 8.10.0
|
||||
acorn-import-assertions: 1.8.0(acorn@8.10.0)
|
||||
browserslist: 4.21.7
|
||||
chrome-trace-event: 1.0.2
|
||||
enhanced-resolve: 5.10.0
|
||||
@ -34222,6 +34457,15 @@ packages:
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
||||
/why-is-node-running@2.2.2:
|
||||
resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==}
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
siginfo: 2.0.0
|
||||
stackback: 0.0.2
|
||||
dev: true
|
||||
|
||||
/wide-align@1.1.3:
|
||||
resolution: {integrity: sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==}
|
||||
dependencies:
|
||||
@ -34764,6 +35008,11 @@ packages:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
/yocto-queue@1.0.0:
|
||||
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
|
||||
engines: {node: '>=12.20'}
|
||||
dev: true
|
||||
|
||||
/zdog@1.1.3:
|
||||
resolution: {integrity: sha512-raRj6r0gPzopFm5XWBJZr/NuV4EEnT4iE+U3dp5FV5pCb588Gmm3zLIp/j9yqqcMiHH8VNQlerLTgOqL7krh6w==}
|
||||
dev: false
|
||||
|
||||
Loading…
Reference in New Issue
Block a user