test: ssr

This commit is contained in:
Guillaume Chau
2023-09-12 11:34:12 +02:00
parent 1ac1372dff
commit 574bd8f2b1
41 changed files with 1205 additions and 50 deletions
+73
View File
@@ -0,0 +1,73 @@
name: E2E composable + SSR
on:
push:
branches:
- main
- v4
- feat/*
- fix/*
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
build-and-test:
runs-on: ubuntu-latest
name: Build and test
env:
dir: ./packages/test-e2e-ssr
steps:
- uses: actions/checkout@v2
- name: Install node
uses: actions/setup-node@v2
with:
node-version: 18
- name: Install pnpm
uses: pnpm/action-setup@v2.0.1
with:
version: 8.6.2
- name: Get pnpm store directory
id: pnpm-cache
run: |
echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
- name: Cache pnpm modules
uses: actions/cache@v2
with:
path: |
${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
~/.cache/Cypress
key: pnpm-v1-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
pnpm-v1-${{ runner.os }}-
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm run build
- name: E2E tests
working-directory: ${{env.dir}}
run: pnpm run test:e2e
- uses: actions/upload-artifact@v2
if: failure()
with:
name: cypress-screenshots
path: ${{env.dir}}/tests/e2e/screenshots
- uses: actions/upload-artifact@v2
if: always()
with:
name: cypress-videos
path: ${{env.dir}}/tests/e2e/videos
@@ -22,19 +22,19 @@
"graphql-tag": "^2.12.6",
"test-server": "workspace:*",
"vue": "^3.3.4",
"@vitejs/plugin-vue": "^4.2.3",
"vue-router": "^4.2.4"
},
"devDependencies": {
"vite": "^4.4.2",
"vue-tsc": "^1.8.3",
"typescript": "^5.0.2",
"cypress-vite": "^1.4.1",
"@vitejs/plugin-vue": "^4.2.3",
"autoprefixer": "^10.4.14",
"axios": "^1.4.0",
"cypress": "^12.17.0",
"cypress-vite": "^1.4.1",
"postcss": "^8.4.25",
"start-server-and-test": "^2.0.0",
"tailwindcss": "^3.3.2",
"postcss": "^8.4.25",
"autoprefixer": "^10.4.14"
"typescript": "^5.0.2",
"vite": "^4.4.2",
"vue-tsc": "^1.8.3"
}
}
@@ -12,7 +12,7 @@
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env",
"vite/client",
"cypress"
],
"paths": {
+3
View File
@@ -0,0 +1,3 @@
> 1%
last 2 versions
not dead
+5
View File
@@ -0,0 +1,5 @@
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
+27
View File
@@ -0,0 +1,27 @@
.DS_Store
node_modules
/dist
/tests/e2e/videos/
/tests/e2e/screenshots/
/tests/e2e/downloads/
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+24
View File
@@ -0,0 +1,24 @@
# test-e2e-global-composable-vue3
## Project setup
```
pnpm install
```
### Compiles and hot-reloads for development
```
pnpm run serve
```
### Compiles and minifies for production
```
pnpm run build
```
### Run your end-to-end tests
```
pnpm run test:e2e
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
+31
View File
@@ -0,0 +1,31 @@
import { defineConfig } from 'cypress'
import vitePreprocessor from 'cypress-vite'
import axios from 'axios'
export default defineConfig({
fixturesFolder: 'tests/e2e/fixtures',
screenshotsFolder: 'tests/e2e/screenshots',
videosFolder: 'tests/e2e/videos',
downloadsFolder: 'tests/e2e/downloads',
e2e: {
baseUrl: 'http://localhost:8080',
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
setupNodeEvents (on) {
on('task', {
async 'db:reset' () {
await axios.get('http://localhost:4042/_reset')
return true
},
async 'db:seed' () {
await axios.get('http://localhost:4042/_seed')
return true
},
})
on('file:preprocessor', vitePreprocessor())
},
specPattern: 'tests/e2e/specs/**/*.cy.{js,jsx,ts,tsx}',
supportFile: 'tests/e2e/support/index.ts',
},
})
+14
View File
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>My app</title>
<script>window._INITIAL_STATE_ = <!--state--></script>
</head>
<body>
<div id="app"><!--app-render--></div>
<script type="module" src="/src/entry-client.ts"></script>
</body>
</html>
+42
View File
@@ -0,0 +1,42 @@
{
"name": "test-e2e-ssr",
"version": "4.0.0-alpha.16",
"private": true,
"scripts": {
"dev": "node ./server.mjs",
"test": "pnpm run test:e2e",
"test:e2e": "start-server-and-test api 'http-get://localhost:4042/graphql?query=%7B__typename%7D' test:e2e:run",
"test:e2e:run": "start-server-and-test dev http://localhost:8080 test:e2e:cy",
"test:e2e:cy": "cypress run --headless",
"test:e2e:dev": "cypress open",
"api": "test-server --simulate-latency 50",
"api:dev": "test-server --simulate-latency 500"
},
"dependencies": {
"@apollo/client": "^3.7.16",
"@vue/apollo-composable": "workspace:*",
"@vue/apollo-util": "workspace:*",
"devalue": "^4.3.2",
"express": "^4.18.2",
"graphql": "^16.7.1",
"graphql-tag": "^2.12.6",
"isomorphic-fetch": "^3.0.0",
"test-server": "workspace:*",
"vue": "^3.3.4",
"vue-router": "^4.2.4"
},
"devDependencies": {
"@types/node": "^20.6.0",
"@vitejs/plugin-vue": "^4.2.3",
"autoprefixer": "^10.4.14",
"axios": "^1.4.0",
"cypress": "^12.17.0",
"cypress-vite": "^1.4.1",
"postcss": "^8.4.25",
"start-server-and-test": "^2.0.0",
"tailwindcss": "^3.3.2",
"typescript": "^5.0.2",
"vite": "^4.4.2",
"vue-tsc": "^1.8.3"
}
}
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
+43
View File
@@ -0,0 +1,43 @@
import express from 'express'
import fs from 'node:fs'
import { createServer } from 'vite'
import { uneval } from 'devalue'
const server = express()
const viteServer = await createServer({
server: {
middlewareMode: true,
},
appType: 'custom',
})
server.use(viteServer.middlewares)
server.get('*', async (req, res) => {
try {
const url = req.originalUrl
console.log(url)
let template = fs.readFileSync('./index.html', 'utf8')
const { render } = await viteServer.ssrLoadModule('/src/entry-server.ts')
const { html, context } = await render(url)
console.log(context)
template = template
.replace('<!--state-->', uneval(context.state))
.replace('<!--app-render-->', html)
res.send(template)
} catch (e) {
console.error(e)
res.send(e.stack)
}
})
server.use(express.static('.'))
server.listen(8080, () => {
console.log('Server is running on http://localhost:8080')
})
+35
View File
@@ -0,0 +1,35 @@
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client/core'
import { onError } from '@apollo/client/link/error'
import { logErrorMessages } from '@vue/apollo-util'
import { isServer } from './env.js'
export function createApollo () {
const cache = new InMemoryCache()
const restoreCache = !isServer && !!window._INITIAL_STATE_?.apollo
if (restoreCache) {
cache.restore(window._INITIAL_STATE_.apollo)
}
// HTTP connection to the API
const httpLink = createHttpLink({
// You should use an absolute URL here
uri: 'http://localhost:4042/graphql',
})
// Handle errors
const errorLink = onError(error => {
logErrorMessages(error)
})
const apolloClient = new ApolloClient({
cache,
link: errorLink.concat(httpLink),
ssrForceFetchDelay: restoreCache ? 100 : undefined,
ssrMode: isServer,
})
return {
apolloClient,
}
}
+22
View File
@@ -0,0 +1,22 @@
import { createApp } from 'vue'
import { DefaultApolloClient } from '@vue/apollo-composable'
import { createApollo } from './apollo'
import App from './components/App.vue'
import { createMyRouter } from './router'
import '@/assets/styles/tailwind.css'
export function createMyApp () {
const app = createApp(App)
const { apolloClient } = createApollo()
app.provide(DefaultApolloClient, apolloClient)
const { router } = createMyRouter()
app.use(router)
return {
app,
router,
apolloClient,
}
}
@@ -0,0 +1,5 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@@ -0,0 +1,22 @@
<template>
<GlobalLoading />
<div class="flex h-screen items-stretch bg-gray-100">
<ChannelList class="w-1/4 border-r border-gray-200" />
<router-view class="flex-1 overflow-auto" />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import ChannelList from './ChannelList.vue'
import GlobalLoading from './GlobalLoading.vue'
export default defineComponent({
name: 'App',
components: {
ChannelList,
GlobalLoading,
},
})
</script>
@@ -0,0 +1,67 @@
<script lang="ts" setup>
import gql from 'graphql-tag'
import { useQuery } from '@vue/apollo-composable'
import { computed } from 'vue'
import ClientOnly from './ClientOnly.vue'
interface Channel {
id: string
label: string
}
const { result, loading } = useQuery<{
channels: Channel[]
}>(gql`
query channels {
channels {
id
label
}
}
`)
const channels = computed(() => result.value?.channels ?? [])
</script>
<template>
<div
v-if="loading"
class="p-12 text-gray-500"
>
Loading channels...
</div>
<div
v-else
class="flex flex-col bg-white"
>
<router-link
v-for="channel of channels"
:key="channel.id"
v-slot="{ href, navigate, isActive }"
:to="{
name: 'channel',
params: {
id: channel.id,
},
}"
custom
>
<a
:href="href"
class="channel-link px-4 py-2 hover:bg-green-100 text-green-700"
:class="{
'bg-green-200 hover:bg-green-300 text-green-900': isActive,
}"
@click="navigate"
>
# {{ channel.label }}
</a>
</router-link>
<div class="mt-auto p-2 text-gray-500">
<ClientOnly>
Client loaded
</ClientOnly>
</div>
</div>
</template>
@@ -0,0 +1,108 @@
<script>
import gql from 'graphql-tag'
import { defineComponent, onMounted, ref, watch, computed } from 'vue'
import { useQuery } from '@vue/apollo-composable'
import MessageItem from './MessageItem.vue'
import MessageForm from './MessageForm.vue'
export default defineComponent({
components: {
MessageItem,
MessageForm,
},
props: {
id: {
type: String,
required: true,
},
},
setup (props) {
const { result, loading, refetch } = useQuery(gql`
query channel ($id: ID!) {
channel (id: $id) {
id
label
messages {
id
text
}
}
}
`, () => ({
id: props.id,
}), {
notifyOnNetworkStatusChange: true,
})
const channel = computed(() => result.value?.channel)
const messagesEl = ref()
function scrollToBottom () {
if (!messagesEl.value) return
messagesEl.value.scrollTop = messagesEl.value.scrollHeight
}
watch(() => channel.value?.messages, () => {
scrollToBottom()
})
onMounted(() => {
scrollToBottom()
})
return {
loading,
refetch,
channel,
messagesEl,
}
},
})
</script>
<template>
<div>
<div
v-if="loading"
class="loading-channel fixed top-0 left-0 w-full flex"
>
<div class="px-4 py-2 rounded-b mx-auto bg-white border-b border-l border-r border-gray-200">
Loading channel...
</div>
</div>
<div
v-if="channel"
class="flex flex-col h-full"
>
<div class="flex-none p-6 border-b border-gray-200 bg-white">
Currently viewing # {{ channel.label }}
<a
class="text-green-500 cursor-pointer"
data-test-id="refetch"
@click="refetch()"
>Refetch</a>
</div>
<div
ref="messagesEl"
class="flex-1 overflow-y-auto"
>
<MessageItem
v-for="message of channel.messages"
:key="message.id"
:message="message"
class="m-2"
/>
</div>
<MessageForm
:channel-id="channel.id"
class="flex-none m-2 mt-0"
/>
</div>
</div>
</template>
@@ -0,0 +1,13 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
const displayed = ref(false)
onMounted(() => {
displayed.value = true
})
</script>
<template>
<slot v-if="displayed" />
</template>
@@ -0,0 +1,16 @@
<script lang="ts" setup>
import { useGlobalQueryLoading } from '@vue/apollo-composable'
const loading = useGlobalQueryLoading()
</script>
<template>
<div
class="fixed bg-white p-4 rounded-br top-0 right-0"
data-test-id="global-loading"
>
<div v-if="loading">
Global loading...
</div>
</div>
</template>
@@ -0,0 +1,68 @@
<script lang="ts">
import gql from 'graphql-tag'
import { useLazyQuery } from '@vue/apollo-composable'
import { defineComponent, computed, ref } from 'vue'
export default defineComponent({
setup () {
const { result, loading, load, refetch } = useLazyQuery(gql`
query list {
list
}
`)
const list = computed(() => result.value?.list ?? [])
const refetched = ref(false)
function r () {
refetched.value = true
refetch()
}
function loadOrRefetch () {
load() || r()
}
return {
loadOrRefetch,
loading,
list,
refetched,
}
},
})
</script>
<template>
<div class="m-6">
<div>
<button
class="bg-green-200 rounded-lg p-4"
@click="loadOrRefetch()"
>
Load list
</button>
<span data-test-id="refetched">
Refetched: {{ refetched }}
</span>
</div>
<div
v-if="loading"
class="loading"
>
Loading...
</div>
<ul class="my-4">
<li
v-for="(item, index) of list"
:key="index"
class="list-disc ml-6"
>
{{ item }}
</li>
</ul>
</div>
</template>
@@ -0,0 +1,49 @@
<script lang="ts">
import gql from 'graphql-tag'
import { useLazyQuery } from '@vue/apollo-composable'
import { defineComponent, computed, reactive } from 'vue'
export default defineComponent({
setup () {
const { result, loading, load } = useLazyQuery(gql`
query channel ($id: ID!) {
channel (id: $id) {
id
label
messages {
id
}
}
}
`, {
id: 'general',
})
const channel = computed(() => result.value?.channel)
load(undefined, {
id: 'general',
})
return {
loading,
channel,
}
},
})
</script>
<template>
<div class="m-6">
<div
v-if="loading"
class="loading"
>
Loading...
</div>
<div v-if="channel">
<div>Loaded channel: {{ channel.label }}</div>
<div>Messages: {{ channel.messages.length }}</div>
</div>
</div>
</template>
@@ -0,0 +1,76 @@
<script lang="ts">
import gql from 'graphql-tag'
import { useMutation } from '@vue/apollo-composable'
import { defineComponent, ref } from 'vue'
export default defineComponent({
props: {
channelId: {
type: String,
required: true,
},
},
setup (props) {
const text = ref('')
const { mutate } = useMutation(gql`
mutation sendMessage ($input: AddMessageInput!) {
message: addMessage (input: $input) {
id
text
}
}
`, {
update: (cache, { data: { message } }) => {
cache.modify({
id: cache.identify({
__typename: 'Channel',
id: props.channelId,
}),
fields: {
messages: (existingMessages = []) => [
...existingMessages,
message,
],
},
})
},
})
async function sendMessage () {
await mutate({
input: {
channelId: props.channelId,
text: text.value,
},
}, {
optimisticResponse: {
__typename: 'Mutation',
message: {
id: Date.now().toString(),
text: text.value,
},
},
})
text.value = ''
}
return {
text,
sendMessage,
}
},
})
</script>
<template>
<div class="border border-gray-200 rounded-lg bg-white">
<input
v-model="text"
placeholder="Type a message..."
class="w-full px-4 py-2 bg-transparent"
@keyup.enter="sendMessage()"
>
</div>
</template>
@@ -0,0 +1,20 @@
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
props: {
message: {
type: Object,
required: true,
},
},
})
</script>
<template>
<div>
<div class="message inline-block bg-green-100 border border-green-200 rounded-2xl px-4 py-2">
{{ message.text }}
</div>
</div>
</template>
@@ -0,0 +1,5 @@
<template>
<div class="flex items-center justify-center">
Welcome
</div>
</template>
+11
View File
@@ -0,0 +1,11 @@
export interface Context {
state: {
apollo?: any
}
}
declare global {
interface Window {
_INITIAL_STATE_: Context['state']
}
}
@@ -0,0 +1,7 @@
import { createMyApp } from './app.js'
const { app, router } = createMyApp()
router.isReady().then(() => {
app.mount('#app')
})
+28
View File
@@ -0,0 +1,28 @@
import 'isomorphic-fetch'
import { renderToString } from 'vue/server-renderer'
import { createMyApp } from './app.js'
import { Context } from '@apollo/client'
export async function render (url: string) {
const {
app,
router,
apolloClient,
} = await createMyApp()
await router.push(url)
await router.isReady()
const context: Context = {
state: {},
}
const html = await renderToString(app, context)
context.state.apollo = apolloClient.extract()
return {
html,
context,
}
}
+1
View File
@@ -0,0 +1 @@
export const isServer = typeof window === 'undefined'
+33
View File
@@ -0,0 +1,33 @@
import { createRouter, createWebHistory, createMemoryHistory } from 'vue-router'
import { isServer } from './env.js'
export function createMyRouter () {
const router = createRouter({
history: isServer ? createMemoryHistory() : createWebHistory(),
routes: [
{
path: '/',
name: 'home',
component: () => import('./components/Welcome.vue'),
},
{
path: '/channel/:id',
name: 'channel',
component: () => import('./components/ChannelView.vue'),
props: true,
},
{
path: '/lazy-query',
component: () => import('./components/LazyQuery.vue'),
},
{
path: '/lazy-query-immediately',
component: () => import('./components/LazyQueryImmediately.vue'),
},
],
})
return {
router,
}
}
+5
View File
@@ -0,0 +1,5 @@
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent
export default component
}
+8
View File
@@ -0,0 +1,8 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
theme: {
extend: {},
},
plugins: [],
}
@@ -0,0 +1,12 @@
module.exports = {
plugins: [
'cypress',
],
env: {
mocha: true,
'cypress/globals': true,
},
rules: {
strict: 'off',
},
}
@@ -0,0 +1,38 @@
describe('Vue 3 + Apollo Composable', () => {
beforeEach(() => {
cy.task('db:seed')
})
it('loads channels', () => {
cy.intercept('http://localhost:4042/graphql', (req) => {
throw new Error('Should not be called')
})
cy.visit('/')
cy.contains('#app', 'Client loaded')
cy.get('#app').should('not.contain', 'Loading channels...')
cy.get('.channel-link').should('have.lengthOf', 2)
cy.contains('.channel-link', '# General')
cy.contains('.channel-link', '# Random')
})
it('load one channel', () => {
let shouldCallGraphQL = false
cy.intercept('http://localhost:4042/graphql', (req) => {
if (!shouldCallGraphQL) {
throw new Error('Should not be called')
}
})
cy.visit('/channel/general')
cy.contains('#app', 'Client loaded')
cy.contains('#app', 'Currently viewing # General')
cy.get('.message').should('have.lengthOf', 2)
cy.contains('.message', 'Meow?')
cy.contains('.message', 'Meow!')
shouldCallGraphQL = true
cy.get('.channel-link').eq(1).click()
cy.get('[data-test-id="global-loading"]').should('contain', 'Global loading...')
cy.contains('#app', 'Currently viewing # Random')
cy.get('.message').should('have.lengthOf', 1)
cy.contains('.message', 'Hello world!')
})
})
@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')
+41
View File
@@ -0,0 +1,41 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"vite/client",
"cypress",
"node"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
+13
View File
@@ -0,0 +1,13 @@
import { resolve } from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, './src'),
},
},
})
+22
View File
@@ -27,4 +27,26 @@ export function resetDatabase (): void {
]
}
export function seedDatabase (): void {
channels[0].messages = [
{
id: '1',
channel: channels[0],
text: 'Meow?',
},
{
id: '2',
channel: channels[0],
text: 'Meow!',
},
]
channels[1].messages = [
{
id: '3',
channel: channels[1],
text: 'Hello world!',
},
]
}
resetDatabase()
+6 -1
View File
@@ -7,7 +7,7 @@ import { expressMiddleware } from '@apollo/server/express4'
import { WebSocketServer } from 'ws'
import { useServer } from 'graphql-ws/lib/use/ws'
import { schema } from './schema.js'
import { resetDatabase } from './data.js'
import { resetDatabase, seedDatabase } from './data.js'
import { simulateLatency } from './util.js'
const app = express()
@@ -23,6 +23,11 @@ app.get('/_reset', (req, res) => {
res.status(200).end()
})
app.get('/_seed', (req, res) => {
seedDatabase()
res.status(200).end()
})
const server = new ApolloServer({
schema,
plugins: [
+153 -41
View File
@@ -177,9 +177,6 @@ importers:
'@apollo/client':
specifier: ^3.7.16
version: 3.7.16(graphql@16.7.1)
'@vitejs/plugin-vue':
specifier: ^4.2.3
version: 4.2.3(vite@4.4.2)(vue@3.3.4)
'@vue/apollo-composable':
specifier: workspace:*
version: link:../vue-apollo-composable
@@ -202,6 +199,9 @@ importers:
specifier: ^4.2.4
version: 4.2.4(vue@3.3.4)
devDependencies:
'@vitejs/plugin-vue':
specifier: ^4.2.3
version: 4.2.3(vite@4.4.2)(vue@3.3.4)
autoprefixer:
specifier: ^10.4.14
version: 10.4.14(postcss@8.4.25)
@@ -228,7 +228,80 @@ importers:
version: 5.0.2
vite:
specifier: ^4.4.2
version: 4.4.2
version: 4.4.2(@types/node@20.6.0)
vue-tsc:
specifier: ^1.8.3
version: 1.8.3(typescript@5.0.2)
packages/test-e2e-ssr:
dependencies:
'@apollo/client':
specifier: ^3.7.16
version: 3.7.16(graphql@16.7.1)
'@vue/apollo-composable':
specifier: workspace:*
version: link:../vue-apollo-composable
'@vue/apollo-util':
specifier: workspace:*
version: link:../vue-apollo-util
devalue:
specifier: ^4.3.2
version: 4.3.2
express:
specifier: ^4.18.2
version: 4.18.2
graphql:
specifier: ^16.7.1
version: 16.7.1
graphql-tag:
specifier: ^2.12.6
version: 2.12.6(graphql@16.7.1)
isomorphic-fetch:
specifier: ^3.0.0
version: 3.0.0
test-server:
specifier: workspace:*
version: link:../test-server
vue:
specifier: ^3.3.4
version: 3.3.4
vue-router:
specifier: ^4.2.4
version: 4.2.4(vue@3.3.4)
devDependencies:
'@types/node':
specifier: ^20.6.0
version: 20.6.0
'@vitejs/plugin-vue':
specifier: ^4.2.3
version: 4.2.3(vite@4.4.2)(vue@3.3.4)
autoprefixer:
specifier: ^10.4.14
version: 10.4.14(postcss@8.4.25)
axios:
specifier: ^1.4.0
version: 1.4.0
cypress:
specifier: ^12.17.0
version: 12.17.0
cypress-vite:
specifier: ^1.4.1
version: 1.4.1(vite@4.4.2)
postcss:
specifier: ^8.4.25
version: 8.4.25
start-server-and-test:
specifier: ^2.0.0
version: 2.0.0
tailwindcss:
specifier: ^3.3.2
version: 3.3.2
typescript:
specifier: ^5.0.2
version: 5.0.2
vite:
specifier: ^4.4.2
version: 4.4.2(@types/node@20.6.0)
vue-tsc:
specifier: ^1.8.3
version: 1.8.3(typescript@5.0.2)
@@ -1280,7 +1353,7 @@ packages:
'@babel/helper-plugin-utils': 7.20.2
debug: 4.3.4(supports-color@8.1.1)
lodash.debounce: 4.0.8
resolve: 1.22.1
resolve: 1.22.2
semver: 6.3.0
transitivePeerDependencies:
- supports-color
@@ -1296,7 +1369,7 @@ packages:
'@babel/helper-plugin-utils': 7.20.2
debug: 4.3.4(supports-color@8.1.1)
lodash.debounce: 4.0.8
resolve: 1.22.1
resolve: 1.22.2
semver: 6.3.0
transitivePeerDependencies:
- supports-color
@@ -3431,6 +3504,7 @@ packages:
cpu: [arm64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-arm@0.18.11:
@@ -3439,6 +3513,7 @@ packages:
cpu: [arm]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-x64@0.18.11:
@@ -3447,6 +3522,7 @@ packages:
cpu: [x64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/darwin-arm64@0.18.11:
@@ -3455,6 +3531,7 @@ packages:
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@esbuild/darwin-x64@0.18.11:
@@ -3463,6 +3540,7 @@ packages:
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@esbuild/freebsd-arm64@0.18.11:
@@ -3471,6 +3549,7 @@ packages:
cpu: [arm64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/freebsd-x64@0.18.11:
@@ -3479,6 +3558,7 @@ packages:
cpu: [x64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-arm64@0.18.11:
@@ -3487,6 +3567,7 @@ packages:
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-arm@0.18.11:
@@ -3495,6 +3576,7 @@ packages:
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-ia32@0.18.11:
@@ -3503,6 +3585,7 @@ packages:
cpu: [ia32]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-loong64@0.14.54:
@@ -3520,6 +3603,7 @@ packages:
cpu: [loong64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-mips64el@0.18.11:
@@ -3528,6 +3612,7 @@ packages:
cpu: [mips64el]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-ppc64@0.18.11:
@@ -3536,6 +3621,7 @@ packages:
cpu: [ppc64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-riscv64@0.18.11:
@@ -3544,6 +3630,7 @@ packages:
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-s390x@0.18.11:
@@ -3552,6 +3639,7 @@ packages:
cpu: [s390x]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-x64@0.18.11:
@@ -3560,6 +3648,7 @@ packages:
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/netbsd-x64@0.18.11:
@@ -3568,6 +3657,7 @@ packages:
cpu: [x64]
os: [netbsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/openbsd-x64@0.18.11:
@@ -3576,6 +3666,7 @@ packages:
cpu: [x64]
os: [openbsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/sunos-x64@0.18.11:
@@ -3584,6 +3675,7 @@ packages:
cpu: [x64]
os: [sunos]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-arm64@0.18.11:
@@ -3592,6 +3684,7 @@ packages:
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-ia32@0.18.11:
@@ -3600,6 +3693,7 @@ packages:
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-x64@0.18.11:
@@ -3608,6 +3702,7 @@ packages:
cpu: [x64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@eslint/eslintrc@0.4.3:
@@ -4135,7 +4230,7 @@ packages:
/@types/accepts@1.3.5:
resolution: {integrity: sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: false
/@types/babel__core@7.20.0:
@@ -4171,32 +4266,32 @@ packages:
resolution: {integrity: sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==}
dependencies:
'@types/connect': 3.4.35
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: false
/@types/body-parser@1.19.2:
resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==}
dependencies:
'@types/connect': 3.4.35
'@types/node': 18.14.0
'@types/node': 20.6.0
/@types/bonjour@3.5.10:
resolution: {integrity: sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: true
/@types/connect-history-api-fallback@1.3.5:
resolution: {integrity: sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==}
dependencies:
'@types/express-serve-static-core': 4.17.33
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: true
/@types/connect@3.4.35:
resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
/@types/content-disposition@0.5.5:
resolution: {integrity: sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==}
@@ -4208,7 +4303,7 @@ packages:
'@types/connect': 3.4.35
'@types/express': 4.17.17
'@types/keygrip': 1.0.2
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: false
/@types/cors@2.8.10:
@@ -4218,7 +4313,7 @@ packages:
/@types/cors@2.8.13:
resolution: {integrity: sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: true
/@types/eslint-scope@3.7.4:
@@ -4246,7 +4341,7 @@ packages:
/@types/express-serve-static-core@4.17.33:
resolution: {integrity: sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
'@types/qs': 6.9.7
'@types/range-parser': 1.2.4
@@ -4261,7 +4356,7 @@ packages:
/@types/fs-capacitor@2.0.0:
resolution: {integrity: sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: false
/@types/graphql@14.5.0:
@@ -4286,7 +4381,7 @@ packages:
/@types/http-proxy@1.17.9:
resolution: {integrity: sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: true
/@types/istanbul-lib-coverage@2.0.4:
@@ -4321,7 +4416,7 @@ packages:
/@types/keyv@3.1.4:
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: true
/@types/koa-compose@3.2.5:
@@ -4340,7 +4435,7 @@ packages:
'@types/http-errors': 2.0.1
'@types/keygrip': 1.0.2
'@types/koa-compose': 3.2.5
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: false
/@types/long@4.0.2:
@@ -4357,7 +4452,7 @@ packages:
/@types/node-fetch@2.6.4:
resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
form-data: 3.0.1
dev: false
@@ -4369,8 +4464,8 @@ packages:
resolution: {integrity: sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==}
dev: true
/@types/node@18.14.0:
resolution: {integrity: sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==}
/@types/node@20.6.0:
resolution: {integrity: sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==}
/@types/normalize-package-data@2.4.1:
resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
@@ -4389,13 +4484,13 @@ packages:
/@types/resolve@0.0.8:
resolution: {integrity: sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: true
/@types/responselike@1.0.0:
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: true
/@types/retry@0.12.0:
@@ -4416,7 +4511,7 @@ packages:
resolution: {integrity: sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==}
dependencies:
'@types/mime': 3.0.1
'@types/node': 18.14.0
'@types/node': 20.6.0
/@types/shortid@0.0.29:
resolution: {integrity: sha512-9BCYD9btg2CY4kPcpMQ+vCR8U6V8f/KvixYD5ZbxoWlkhddNF5IeZMVL3p+QFUkg+Hb+kPAG9Jgk4bnnF1v/Fw==}
@@ -4433,7 +4528,7 @@ packages:
/@types/sockjs@0.3.33:
resolution: {integrity: sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: true
/@types/stack-utils@1.0.1:
@@ -4447,13 +4542,13 @@ packages:
/@types/ws@7.4.7:
resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: false
/@types/ws@8.5.5:
resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: true
/@types/yargs-parser@21.0.0:
@@ -4470,7 +4565,7 @@ packages:
resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==}
requiresBuild: true
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
dev: true
optional: true
@@ -4605,9 +4700,9 @@ packages:
vite: ^4.0.0
vue: '*'
dependencies:
vite: 4.4.2
vite: 4.4.2(@types/node@20.6.0)
vue: 3.3.4
dev: false
dev: true
/@volar/language-core@1.7.10:
resolution: {integrity: sha512-18Gmth5M0UI3hDDqhZngjMnb6WCslcfglkOdepRIhGxRYe7xR7DRRzciisYDMZsvOQxDYme+uaohg0dKUxLV2Q==}
@@ -4693,7 +4788,7 @@ packages:
babel-plugin-dynamic-import-node: 2.3.3
core-js: 3.28.0
core-js-compat: 3.28.0
semver: 7.3.8
semver: 7.5.4
vue: 3.2.47
transitivePeerDependencies:
- supports-color
@@ -5012,7 +5107,7 @@ packages:
open: 8.4.2
ora: 5.4.1
read-pkg: 5.2.0
semver: 7.3.8
semver: 7.5.4
strip-ansi: 6.0.1
transitivePeerDependencies:
- encoding
@@ -7801,7 +7896,7 @@ packages:
dependencies:
chokidar: 3.5.3
debug: 4.3.4(supports-color@8.1.1)
vite: 4.4.2
vite: 4.4.2(@types/node@20.6.0)
transitivePeerDependencies:
- supports-color
dev: true
@@ -8105,6 +8200,10 @@ packages:
resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
dev: true
/devalue@4.3.2:
resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==}
dev: false
/dicer@0.3.0:
resolution: {integrity: sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==}
engines: {node: '>=4.5.0'}
@@ -8657,6 +8756,7 @@ packages:
'@esbuild/win32-arm64': 0.18.11
'@esbuild/win32-ia32': 0.18.11
'@esbuild/win32-x64': 0.18.11
dev: true
/esbuild@0.8.57:
resolution: {integrity: sha512-j02SFrUwFTRUqiY0Kjplwjm1psuzO1d6AjaXKuOR9hrY0HuPsT6sV42B6myW34h1q4CRy+Y3g4RU/cGJeI/nNA==}
@@ -9557,6 +9657,7 @@ packages:
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
requiresBuild: true
dev: true
optional: true
/function-bind@1.1.1:
@@ -10799,6 +10900,15 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/isomorphic-fetch@3.0.0:
resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==}
dependencies:
node-fetch: 2.6.9
whatwg-fetch: 3.6.2
transitivePeerDependencies:
- encoding
dev: false
/isstream@0.1.2:
resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==}
dev: true
@@ -11265,7 +11375,7 @@ packages:
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
engines: {node: '>= 10.13.0'}
dependencies:
'@types/node': 18.14.0
'@types/node': 20.6.0
merge-stream: 2.0.0
supports-color: 8.1.1
dev: true
@@ -11847,7 +11957,7 @@ packages:
dev: true
/media-typer@0.3.0:
resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=}
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'}
/memfs@3.4.13:
@@ -11879,7 +11989,7 @@ packages:
dev: true
/merge-descriptors@1.0.1:
resolution: {integrity: sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=}
resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
/merge-source-map@1.1.0:
resolution: {integrity: sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==}
@@ -12222,7 +12332,7 @@ packages:
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
dependencies:
hosted-git-info: 2.8.9
resolve: 1.22.1
resolve: 1.22.2
semver: 5.7.1
validate-npm-package-license: 3.0.4
dev: true
@@ -14154,7 +14264,7 @@ packages:
hasBin: true
dependencies:
'@types/estree': 1.0.0
'@types/node': 18.14.0
'@types/node': 20.6.0
acorn: 7.4.1
dev: true
@@ -14172,6 +14282,7 @@ packages:
hasBin: true
optionalDependencies:
fsevents: 2.3.2
dev: true
/rsvp@4.8.5:
resolution: {integrity: sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==}
@@ -15700,7 +15811,7 @@ packages:
fsevents: 2.3.2
dev: true
/vite@4.4.2:
/vite@4.4.2(@types/node@20.6.0):
resolution: {integrity: sha512-zUcsJN+UvdSyHhYa277UHhiJ3iq4hUBwHavOpsNUGsTgjBeoBlK8eDt+iT09pBq0h9/knhG/SPrZiM7cGmg7NA==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
@@ -15728,11 +15839,13 @@ packages:
terser:
optional: true
dependencies:
'@types/node': 20.6.0
esbuild: 0.18.11
postcss: 8.4.25
rollup: 3.26.2
optionalDependencies:
fsevents: 2.3.2
dev: true
/vitepress@0.22.4:
resolution: {integrity: sha512-oZUnLO/SpYdThaBKefDeOiVlr0Rie4Ppx3FzMnMyLtJnI5GlBMNjqYqMy/4+umm/iC+ZDJfI+IlDKxv5fZnYzA==}
@@ -16239,7 +16352,6 @@ packages:
/whatwg-fetch@3.6.2:
resolution: {integrity: sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==}
dev: true
/whatwg-mimetype@2.3.0:
resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==}