Plugin/request (#439)

* feat: introduce useRequest

* chore: add some description

* fix: export statment for generator

* fix: make @ice/types dev dep

* fix: remove I prefix for interface

* fix: lint

* fix: update pnpm

* feat: add use case for app config

* fix: using export request config

* fix: review for code

* fix: dev dependency
This commit is contained in:
ZeroLing 2022-09-06 17:33:06 +08:00 committed by ClarkXia
parent d0bb41ffec
commit ec42015d34
26 changed files with 768 additions and 17 deletions

View File

@ -1,6 +1,6 @@
import { Meta, Title, Links, Main, Scripts } from 'ice';
function Document(props) {
function Document() {
return (
<html>
<head>

View File

@ -1,4 +1,4 @@
export default function home() {
export default function Home() {
return (
<>
<h2>Home Page</h2>

View File

@ -0,0 +1 @@
chrome 55

View File

@ -0,0 +1,8 @@
import { defineConfig } from '@ice/app';
import request from '@ice/plugin-request';
export default defineConfig({
plugins: [
request(),
],
});

View File

@ -0,0 +1,22 @@
{
"name": "with-plugin-request",
"version": "1.0.0",
"scripts": {
"start": "ice start",
"build": "ice build"
},
"description": "ICE example with plugin-request",
"author": "ICE Team",
"license": "MIT",
"dependencies": {
"@ice/app": "workspace:*",
"@ice/plugin-request": "workspace:*",
"@ice/runtime": "workspace:*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6"
}
}

View File

@ -0,0 +1,59 @@
import { defineRequestConfig } from '@ice/plugin-request/esm/types';
const requestConfig = {
// 可选的,全局设置 request 是否返回 response 对象,默认为 false
withFullResponse: false,
baseURL: '/api',
headers: {},
// 其它 RequestConfig 参数
// 拦截器
interceptors: {
request: {
onConfig: (config) => {
// 发送请求前:可以对 RequestConfig 做一些统一处理
config.headers = { a: 1 };
return config;
},
onError: (error) => {
return Promise.reject(error);
},
},
response: {
onConfig: (response) => {
console.log(response);
// 请求成功:可以做全局的 toast 展示,或者对 response 做一些格式化
if (response.data.status === 1) {
alert('请求失败');
}
return response;
},
onError: (error) => {
// MOCK DATA for `/api/user`
if (error.config.url === '/api/user') {
return new Promise((resolve) => {
setTimeout(() => {
error.response.data = {
name: 'ICE',
age: 26,
};
resolve(error.response);
}, 1000);
});
}
// 请求出错:服务端返回错误状态码
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
return Promise.reject(error);
},
},
},
};
export default {
app: {
rootId: 'app',
},
};
export const request = defineRequestConfig(() => requestConfig);

View File

@ -0,0 +1,22 @@
import { Meta, Title, Links, Main, Scripts } from 'ice';
function Document() {
return (
<html>
<head>
<meta charSet="utf-8" />
<meta name="description" content="ICE 3 Example for plugin request." />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Title />
<Links />
</head>
<body>
<Main />
<Scripts />
</body>
</html>
);
}
export default Document;

View File

@ -0,0 +1,30 @@
import { useEffect } from 'react';
import { useRequest } from 'ice';
import service from '../service';
import styles from './index.module.css';
export default function Home() {
const { data, error, loading, request } = useRequest(service.getUser);
useEffect(() => {
request();
}, []);
if (error) {
return <div>failed to load</div>;
}
if (!data || loading) {
return <div>loading...</div>;
}
return (
<>
<h2 className={styles.title}>Name: {data.name} Age: {data.age}</h2>
</>
);
}
export function getConfig() {
return {
title: 'Home',
};
}

View File

@ -0,0 +1,4 @@
.title {
color: red;
margin-left: 10rpx;
}

View File

@ -0,0 +1,32 @@
import { Outlet } from 'ice';
export default () => {
return (
<div>
<h1>ICE 3.0 Layout</h1>
<Outlet />
</div>
);
};
export function getConfig() {
return {
title: 'Layout',
meta: [
{
name: 'layout-color',
content: '#f00',
},
],
};
}
export function getData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve({
layout: true,
});
}, 1 * 100);
});
}

View File

@ -0,0 +1,27 @@
import { request } from 'ice';
const service = {
async getUser() {
return await request('/api/user');
},
async getRepo(id) {
return await request(`/api/repo/${id}`);
},
async getDetail(params) {
const data = await request({
url: '/api/detail',
params,
});
return data.map(item => {
return {
...item,
price: item.oldPrice,
text: item.status === '1' ? '确定' : '取消',
};
});
},
};
export default service;

View File

@ -0,0 +1,14 @@
declare module '*.module.less' {
const classes: { [key: string]: string };
export default classes;
}
declare module '*.module.css' {
const classes: { [key: string]: string };
export default classes;
}
declare module '*.module.scss' {
const classes: { [key: string]: string };
export default classes;
}

View File

@ -0,0 +1,32 @@
{
"compileOnSave": false,
"buildOnSave": false,
"compilerOptions": {
"baseUrl": ".",
"outDir": "build",
"module": "esnext",
"target": "es6",
"jsx": "react-jsx",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"lib": ["es6", "dom"],
"sourceMap": true,
"allowJs": true,
"rootDir": "./",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": false,
"importHelpers": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"skipLibCheck": true,
"paths": {
"@/*": ["./src/*"],
"ice": [".ice"]
}
},
"include": ["src", ".ice", "ice.config.*"],
"exclude": ["node_modules", "build", "public"]
}

View File

@ -82,8 +82,8 @@
"@types/sass": "^1.43.1",
"@types/temp": "^0.9.1",
"chokidar": "^3.5.3",
"react": "^18.0.0",
"unplugin": "^0.9.5",
"react": "^18.2.0",
"unplugin": "^0.8.0",
"webpack": "^5.73.0",
"webpack-dev-server": "^4.7.4"
},

View File

@ -44,11 +44,11 @@ export function generateExports(exportList: ExportData[]) {
const specifiers = isDefaultImport ? [specifier] : specifier;
const symbol = type ? ';' : ',';
importStatements.push(`import ${type ? 'type ' : ''}${isDefaultImport ? specifier : `{ ${specifier.join(', ')} }`} from '${source}';`);
exportStatements = specifiers.map((specifierStr) => {
specifiers.forEach((specifierStr) => {
if (exportAlias && exportAlias[specifierStr]) {
return `${exportAlias[specifierStr]}: ${specifierStr}${symbol}`;
exportStatements.push(`${exportAlias[specifierStr]}: ${specifierStr}${symbol}`);
} else {
return `${specifierStr}${symbol}`;
exportStatements.push(`${specifierStr}${symbol}`);
}
});
});

View File

@ -0,0 +1,5 @@
# CHANGELOG
## 1.0.0
- The initial version of the plugin.

View File

@ -0,0 +1,66 @@
# ICE Request Plugin
## Usage
Install from npm.
```bash
$ npm i @ice/plugin-request -S
```
Add plugin.
```js title="ice.config.mts"
import { defineConfig } from '@ice/app';
import request from '@ice/plugin-request';
export default defineConfig({
plugins: [
request(),
],
});
```
## API
### request
```js title="service.ts"
import { request } from 'ice';
export async function getUser(id) {
return await request(`/api/user/${id}`);
}
```
### useRequest
```js title="home.tsx"
import { useEffect } from 'react';
import { useRequest } from 'ice';
export default function Home() {
const {
data,
error,
loading,
request
} = useRequest(service.getUser);
useEffect(() => {
request();
}, []);
if (error) {
return <div>failed to load</div>;
}
if (!data || loading) {
return <div>loading...</div>;
}
return (
<h2 className={styles.title}>
Name: {data.name} Age: {data.age}
</h2>
);
}
```

View File

@ -0,0 +1,72 @@
{
"name": "@ice/plugin-request",
"version": "1.0.0",
"description": "Request plugin for ice.",
"license": "MIT",
"type": "module",
"exports": {
".": {
"types": "./esm/index.d.ts",
"import": "./esm/index.js",
"default": "./esm/index.js"
},
"./runtime": {
"types": "./esm/runtime.d.ts",
"import": "./esm/runtime.js",
"default": "./esm/runtime.js"
},
"./hooks": {
"types": "./esm/hooks.d.ts",
"import": "./esm/hooks.js",
"default": "./esm/hooks.js"
},
"./request": {
"types": "./esm/request.d.ts",
"import": "./esm/request.js",
"default": "./esm/request.js"
},
"./types": {
"types": "./esm/types.d.ts",
"import": "./esm/types.js",
"default": "./esm/types.js"
},
"./esm/types": {
"types": "./esm/types.d.ts",
"import": "./esm/types.js",
"default": "./esm/types.js"
},
"./esm/runtime": {
"types": "./esm/runtime.d.ts",
"import": "./esm/runtime.js",
"default": "./esm/runtime.js"
}
},
"main": "./esm/index.js",
"types": "./esm/index.d.ts",
"files": [
"esm",
"!esm/**/*.map"
],
"dependencies": {
"ahooks": "^3.0.0",
"axios": "^0.27.2"
},
"devDependencies": {
"@ice/types": "^1.0.0",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"regenerator-runtime": "^0.13.9"
},
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"repository": {
"type": "http",
"url": "https://github.com/ice-lab/ice-next/tree/master/packages/plugin-request"
},
"scripts": {
"watch": "tsc -w",
"build": "tsc"
}
}

View File

@ -0,0 +1,42 @@
import { useRequest as useAhooksRequest } from 'ahooks';
import type { Options, Result, Service, Plugin } from 'ahooks/lib/useRequest/src/types';
import type { AxiosRequestConfig } from 'axios';
import request from './request.js';
interface RequestResult<R, P extends any[]> extends Result<R, P> {
request: (...args: P) => Promise<R>;
}
function useRequest<TData, TParams extends any[]>(
service: AxiosRequestConfig | Service<TData, TParams>,
options?: Options<TData, TParams>,
plugins?: Plugin<TData, TParams>[]) {
let s: Service<TData, TParams>;
if (isFunction(service)) {
s = service as Service<TData, TParams>;
} else {
const options = service as AxiosRequestConfig;
s = async (...extraOptions: TParams) => {
const response = await request({ ...options, ...extraOptions });
return response.data as TData;
};
}
const req = useAhooksRequest(s, {
// Note
// ahooks/useRequest manual default to true.
// ICE3/useRequest Default to manual request.
manual: true,
...options,
}, plugins);
return {
...req,
// Modify ahooks' useRequest `run` as `request`
request: req.run,
} as RequestResult<TData, TParams>;
}
export default useRequest;
function isFunction(fn: any): fn is Function {
return typeof fn === 'function';
}

View File

@ -0,0 +1,36 @@
import { fileURLToPath } from 'url';
import path from 'path';
import type { Plugin } from '@ice/types';
import type { Request, Interceptors, InterceptorRequest, InterceptorResponse } from './types';
// @ts-ignore
interface PluginRequestOptions {}
const plugin: Plugin<PluginRequestOptions | void> = () => ({
name: 'plugin-request',
setup: ({ generator }) => {
// Add useRequest export for 'ice'.
// import { useRequest } from 'ice';
generator.addExport({
specifier: 'useRequest',
source: '@ice/plugin-request/hooks',
type: false,
});
// import { request } from 'ice';
generator.addExport({
specifier: 'request',
source: '@ice/plugin-request/request',
type: false,
});
},
runtime: path.join(path.dirname(fileURLToPath(import.meta.url)), 'runtime.js'),
});
export type {
Request,
Interceptors,
InterceptorRequest,
InterceptorResponse,
PluginRequestOptions,
};
export default plugin;

View File

@ -0,0 +1,124 @@
import type { AxiosRequestConfig, CancelTokenStatic, CancelStatic } from 'axios';
import axios from 'axios';
// https://github.com/axios/axios#request-config
const DEFAULT_CONFIG = {};
const axiosInstances = {
default: axios.create(DEFAULT_CONFIG),
};
/**
* Create an axios instance.
* @param instanceName
*/
export function createAxiosInstance(instanceName?: string) {
if (instanceName) {
if (axiosInstances[instanceName]) {
return axiosInstances;
}
axiosInstances[instanceName] = axios.create(DEFAULT_CONFIG);
}
return axiosInstances;
}
export function setAxiosInstance(requestConfig, axiosInstance) {
const { interceptors = {}, ...requestOptions } = requestConfig;
Object.keys(requestOptions).forEach(key => {
axiosInstance.defaults[key] = requestOptions[key];
});
function isExist(handlers, [fulfilled, rejected]) {
return handlers.some(item => item.fulfilled === fulfilled && item.rejected === rejected);
}
// Add request interceptor.
if (interceptors.request) {
const [fulfilled, rejected] = [
interceptors.request.onConfig || function (config) { return config; },
interceptors.request.onError || function (error) { return Promise.reject(error); },
];
if (isExist(axiosInstance.interceptors.request.handlers, [fulfilled, rejected])) return;
axiosInstance.interceptors.request.use(fulfilled, rejected);
}
// Add response interceptor.
if (interceptors.response) {
const [fulfilled, rejected] = [
interceptors.response.onConfig || function (response) { return response; },
interceptors.response.onError || function (error) { return Promise.reject(error); },
];
if (isExist(axiosInstance.interceptors.response.handlers, [fulfilled, rejected])) return;
axiosInstance.interceptors.response.use(fulfilled, rejected);
}
}
interface RequestConfig extends AxiosRequestConfig {
instanceName?: string;
withFullResponse?: boolean;
}
export interface RequestProps {
get: <T = any>(url: string, config?: RequestConfig) => Promise<T>;
delete: <T = any>(url: string, config?: RequestConfig) => Promise<T>;
head: <T = any>(url: string, config?: RequestConfig) => Promise<T>;
options: <T = any>(url: string, config?: RequestConfig) => Promise<T>;
post: <T = any>(url: string, data?: any, config?: RequestConfig) => Promise<T>;
put: <T = any>(url: string, data?: any, config?: RequestConfig) => Promise<T>;
patch: <T = any>(url: string, data?: any, config?: RequestConfig) => Promise<T>;
}
interface Request extends RequestProps {
<T = any>(options: RequestConfig): Promise<T>;
<T = any>(url: string, config?: RequestConfig): Promise<T>;
Cancel: CancelStatic;
CancelToken: CancelTokenStatic;
isCancel: (value: any) => boolean;
}
/**
* Request, return response.data | response
* @param options Reference: https://github.com/axios/axios#request-config
*/
const request = async function <T = any>(options): Promise<T> {
try {
const instanceName = options.instanceName ? options.instanceName : 'default';
const axiosInstance = createAxiosInstance()[instanceName];
if (!(typeof axiosInstance === 'function')) {
throw new Error(`unknown ${instanceName} in request method`);
}
const response = await axiosInstance(options);
if (axiosInstance.defaults.withFullResponse || options.withFullResponse) {
return response;
}
return response.data;
} catch (error) {
console.error(error);
throw error;
}
};
// Provide aliases for supported request methods
['delete', 'get', 'head', 'options'].forEach((method) => {
request[method] = function <T = any>(url, config) {
return request<T>(Object.assign(config || {}, {
method,
url,
}));
};
});
['post', 'put', 'patch'].forEach((method) => {
request[method] = function <T = any>(url, data, config) {
return request<T>(Object.assign(config || {}, {
method,
url,
data,
}));
};
});
request.CancelToken = axios.CancelToken;
request.isCancel = axios.isCancel;
export default request as Request;

View File

@ -0,0 +1,24 @@
import type { RuntimePlugin } from '@ice/types';
import { createAxiosInstance, setAxiosInstance } from './request.js';
import type { RequestConfig } from './types';
const runtime: RuntimePlugin = async ({ appContext }) => {
const { appExport } = appContext;
const requestConfig: RequestConfig = (typeof appExport.request === 'function' ? await appExport.request() : appExport.request) || {};
// Support multi configs.
if (Array.isArray(requestConfig)) {
requestConfig.forEach(requestItem => {
const instanceName = requestItem.instanceName ? requestItem.instanceName : 'default';
if (instanceName) {
const axiosInstance = createAxiosInstance(instanceName)[instanceName];
setAxiosInstance(requestItem, axiosInstance);
}
});
} else {
const axiosInstance = createAxiosInstance().default;
setAxiosInstance(requestConfig, axiosInstance);
}
};
export default runtime;

View File

@ -0,0 +1,32 @@
import type { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
export interface InterceptorRequest<T = AxiosRequestConfig> {
onConfig?: (config: T) => T | Promise<T>;
onError?: (error: AxiosError) => Promise<void>;
}
export interface InterceptorResponse<K = AxiosResponse> {
onConfig?: (response: K) => K | Promise<K>;
onError?: (error: AxiosError) => Promise<void>;
}
export interface Interceptors {
request?: InterceptorRequest<AxiosRequestConfig>;
response?: InterceptorResponse<AxiosResponse>;
}
interface CustomRequest extends AxiosRequestConfig {
instanceName?: string;
withFullResponse?: boolean;
interceptors?: Interceptors;
}
export type Request = CustomRequest | CustomRequest[];
export type RequestConfig = Request | object;
export function defineRequestConfig(configOrDefineConfig: RequestConfig | (() => RequestConfig)): RequestConfig {
if (typeof configOrDefineConfig === 'function') {
return configOrDefineConfig();
}
return configOrDefineConfig;
}

View File

@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"baseUrl": "./",
"rootDir": "src",
"outDir": "esm",
"jsx": "react"
},
"include": ["src"]
}

View File

@ -114,7 +114,6 @@ async function render({ history, runtime, Document }: RenderOptions) {
const RouteWrappers = runtime.getWrappers();
const AppRouter = runtime.getAppRouter();
render(
document.getElementById(appConfig.app.rootId),
<BrowserEntry

View File

@ -302,6 +302,25 @@ importers:
'@types/react-dom': 18.0.3
webpack: 5.74.0
examples/with-plugin-request:
specifiers:
'@ice/app': workspace:*
'@ice/plugin-request': workspace:*
'@ice/runtime': workspace:*
'@types/react': ^18.0.17
'@types/react-dom': ^18.0.6
react: ^18.2.0
react-dom: ^18.2.0
dependencies:
'@ice/app': link:../../packages/ice
'@ice/plugin-request': link:../../packages/plugin-request
'@ice/runtime': link:../../packages/runtime
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
devDependencies:
'@types/react': 18.0.17
'@types/react-dom': 18.0.6
examples/with-store:
specifiers:
'@ice/app': workspace:*
@ -512,7 +531,7 @@ importers:
multer: ^1.4.5-lts.1
open: ^8.4.0
path-to-regexp: ^6.2.0
react: ^18.0.0
react: ^18.2.0
react-router: ^6.3.0
regenerator-runtime: ^0.13.9
resolve.exports: ^1.1.0
@ -520,7 +539,7 @@ importers:
semver: ^7.3.5
temp: ^0.9.4
trusted-cert: ^1.1.3
unplugin: ^0.9.5
unplugin: ^0.8.0
webpack: ^5.73.0
webpack-dev-server: ^4.7.4
dependencies:
@ -577,7 +596,7 @@ importers:
'@types/temp': 0.9.1
chokidar: 3.5.3
react: 18.2.0
unplugin: 0.9.5_3qmdnfoccgmcaqi5n264fyeyfi
unplugin: 0.8.1_3qmdnfoccgmcaqi5n264fyeyfi
webpack: 5.74.0_esbuild@0.14.54
webpack-dev-server: 4.8.1_webpack@5.74.0
@ -672,6 +691,23 @@ importers:
'@ice/types': link:../types
'@types/webpack': 5.28.0
packages/plugin-request:
specifiers:
'@ice/types': ^1.0.0
'@types/react': ^18.0.0
'@types/react-dom': ^18.0.0
ahooks: ^3.0.0
axios: ^0.27.2
regenerator-runtime: ^0.13.9
dependencies:
ahooks: 3.4.1
axios: 0.27.2
devDependencies:
'@ice/types': link:../types
'@types/react': 18.0.17
'@types/react-dom': 18.0.6
regenerator-runtime: 0.13.9
packages/plugin-store:
specifiers:
'@ice/store': ^2.0.1
@ -5526,6 +5562,7 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
requiresBuild: true
dev: false
optional: true
@ -5535,6 +5572,7 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
libc: [musl]
requiresBuild: true
dev: false
optional: true
@ -5544,6 +5582,7 @@ packages:
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [glibc]
requiresBuild: true
dev: false
optional: true
@ -5553,6 +5592,7 @@ packages:
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
libc: [musl]
requiresBuild: true
dev: false
optional: true
@ -6233,6 +6273,7 @@ packages:
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
libc: [glibc]
requiresBuild: true
optional: true
@ -6241,6 +6282,7 @@ packages:
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
libc: [musl]
requiresBuild: true
optional: true
@ -6249,6 +6291,7 @@ packages:
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
libc: [glibc]
requiresBuild: true
optional: true
@ -6257,6 +6300,7 @@ packages:
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
libc: [musl]
requiresBuild: true
optional: true
@ -7182,6 +7226,22 @@ packages:
screenfull: 5.2.0
dev: false
/ahooks/3.4.1:
resolution: {integrity: sha512-PMxCDO6JsFdNrAyN3cW1J/2qt/vy2EJ/9KhxGOxj41hJhQddjgaBJjZKf/FrrnZmL+3yGPioZtbC4C7q7ru3yA==}
engines: {node: '>=8.0.0'}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
dependencies:
'@types/js-cookie': 2.2.7
ahooks-v3-count: 1.0.0
dayjs: 1.11.2
intersection-observer: 0.12.0
js-cookie: 2.2.1
lodash: 4.17.21
resize-observer-polyfill: 1.5.1
screenfull: 5.2.0
dev: false
/ahooks/3.4.1_react@18.2.0:
resolution: {integrity: sha512-PMxCDO6JsFdNrAyN3cW1J/2qt/vy2EJ/9KhxGOxj41hJhQddjgaBJjZKf/FrrnZmL+3yGPioZtbC4C7q7ru3yA==}
engines: {node: '>=8.0.0'}
@ -7559,7 +7619,6 @@ packages:
/asynckit/0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
dev: true
/at-least-node/1.0.0:
resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
@ -7651,6 +7710,15 @@ packages:
- debug
dev: false
/axios/0.27.2:
resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
dependencies:
follow-redirects: 1.15.1
form-data: 4.0.0
transitivePeerDependencies:
- debug
dev: false
/axobject-query/2.2.0:
resolution: {integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==}
dev: true
@ -8356,7 +8424,6 @@ packages:
engines: {node: '>= 0.8'}
dependencies:
delayed-stream: 1.0.0
dev: true
/comma-separated-tokens/1.0.8:
resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==}
@ -9253,7 +9320,6 @@ packages:
/delayed-stream/1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
dev: true
/delegates/1.0.0:
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
@ -10916,7 +10982,6 @@ packages:
asynckit: 0.4.0
combined-stream: 1.0.8
mime-types: 2.1.35
dev: true
/forwarded/0.2.0:
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
@ -18193,6 +18258,31 @@ packages:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'}
/unplugin/0.8.1_3qmdnfoccgmcaqi5n264fyeyfi:
resolution: {integrity: sha512-o7rUZoPLG1fH4LKinWgb77gDtTE6mw/iry0Pq0Z5UPvZ9+HZ1/4+7fic7t58s8/CGkPrDpGq+RltO+DmswcR4g==}
peerDependencies:
esbuild: '>=0.13'
rollup: ^2.50.0
vite: ^2.3.0 || ^3.0.0-0
webpack: 4 || 5
peerDependenciesMeta:
esbuild:
optional: true
rollup:
optional: true
vite:
optional: true
webpack:
optional: true
dependencies:
acorn: 8.8.0
chokidar: 3.5.3
esbuild: 0.14.54
webpack: 5.74.0_esbuild@0.14.54
webpack-sources: 3.2.3
webpack-virtual-modules: 0.4.4
dev: true
/unplugin/0.9.5_3qmdnfoccgmcaqi5n264fyeyfi:
resolution: {integrity: sha512-luraheyfxwtvkvHpsOvMNv7IjLdORTWKZp0gWYNHGLi2ImON3iIZOj464qEyyEwLA/EMt12fC415HW9zRpOfTg==}
peerDependencies: