feat: 路由缓存控制

This commit is contained in:
bqy_fe 2021-07-14 10:35:54 +08:00
parent 5da7d45e82
commit aa34c2f71b
23 changed files with 76 additions and 73 deletions

View File

@ -1,9 +1,4 @@
#!/bin/sh #!/bin/sh
. "$(dirname "$0")/_/husky.sh" . "$(dirname "$0")/_/husky.sh"
npm run test # npm run test

View File

@ -30,6 +30,7 @@
"element-plus": "1.0.2-beta.54", "element-plus": "1.0.2-beta.54",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"monaco-editor": "^0.25.2", "monaco-editor": "^0.25.2",
"nanoid": "^3.1.23",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"nprogress": "^1.0.0-1", "nprogress": "^1.0.0-1",
"qrcode": "^1.4.4", "qrcode": "^1.4.4",
@ -43,7 +44,7 @@
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^12.1.4", "@commitlint/cli": "^12.1.4",
"@commitlint/config-conventional": "^12.1.4", "@commitlint/config-conventional": "^12.1.4",
"@types/node": "^16.3.1", "@types/node": "^16.3.2",
"@typescript-eslint/eslint-plugin": "^4.28.3", "@typescript-eslint/eslint-plugin": "^4.28.3",
"@typescript-eslint/parser": "^4.28.3", "@typescript-eslint/parser": "^4.28.3",
"@vitejs/plugin-legacy": "^1.4.4", "@vitejs/plugin-legacy": "^1.4.4",

View File

@ -7,6 +7,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { CacheEnum } from '@/enums'
import { VisualEditorModelValue } from '@/visual-editor/visual-editor.utils'
import { defineComponent, ref, watch } from 'vue' import { defineComponent, ref, watch } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
@ -15,14 +17,26 @@ export default defineComponent({
setup() { setup() {
const keepAliveRef = ref() const keepAliveRef = ref()
const route = useRoute() const route = useRoute()
const jsonData: VisualEditorModelValue = JSON.parse(
localStorage.getItem(CacheEnum.PAGE_DATA_KEY) as string
)
//
const notNeedcachePages = Object.keys(jsonData.pages).filter(
(key) => !jsonData.pages[key].config.keepAlive
)
console.log('notNeedcachePages:', notNeedcachePages)
watch( watch(
() => route.fullPath, () => route.path,
() => { (path) => {
if (notNeedcachePages.includes(path)) {
// keep-alive // keep-alive
const routeCaches = keepAliveRef.value?.$?.__v_cache const routeCaches = keepAliveRef.value?.$?.__v_cache
console.log('keep-alive cache', routeCaches) console.log('keep-alive cache', path, routeCaches)
routeCaches.delete('/') // keep-alive
routeCaches.delete(path)
}
} }
) )

View File

@ -1,9 +1,9 @@
<!-- <!--
* @Author: 卜启缘 * @Author: 卜启缘
* @Date: 2021-06-01 09:45:21 * @Date: 2021-06-01 09:45:21
* @LastEditTime: 2021-07-12 10:22:26 * @LastEditTime: 2021-07-13 21:59:22
* @LastEditors: 卜启缘 * @LastEditors: 卜启缘
* @Description: * @Description: 效果预览页面
* @FilePath: \vite-vue3-lowcode\preview\views\preview.vue * @FilePath: \vite-vue3-lowcode\preview\views\preview.vue
--> -->
<template> <template>
@ -15,19 +15,11 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, reactive, toRefs, onMounted } from 'vue' import { defineComponent, reactive, toRefs, onMounted } from 'vue'
import { Toast } from 'vant' import { Toast } from 'vant'
import { CacheEnum } from '@/enums'
import type { VisualEditorModelValue } from '@/visual-editor/visual-editor.utils' import type { VisualEditorModelValue } from '@/visual-editor/visual-editor.utils'
import SlotItem from './slot-item.vue' import SlotItem from './slot-item.vue'
import router from '../router' import router from '../router'
import { CacheEnum } from '@/enums'
/**
* @name: preview
* @author: 卜启缘
* @date: 2021/4/29 23:09
* @descriptionpreview
* @update: 2021/4/29 23:09
*/
export default defineComponent({ export default defineComponent({
name: 'Preview', name: 'Preview',
components: { components: {

View File

@ -1,7 +1,7 @@
<!-- <!--
* @Author: 卜启缘 * @Author: 卜启缘
* @Date: 2021-06-12 22:18:48 * @Date: 2021-06-12 22:18:48
* @LastEditTime: 2021-07-05 10:18:22 * @LastEditTime: 2021-07-14 10:17:34
* @LastEditors: 卜启缘 * @LastEditors: 卜启缘
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\preview\views\slot-item.vue * @FilePath: \vite-vue3-lowcode\preview\views\slot-item.vue
@ -49,7 +49,7 @@ export default defineComponent({
} }
}, },
setup(props) { setup(props) {
// // TODO
const events = props.element.actions.reduce((prev, curr) => { const events = props.element.actions.reduce((prev, curr) => {
prev[curr.event] = async () => { prev[curr.event] = async () => {
for (const handle of curr.handle) { for (const handle of curr.handle) {

View File

@ -47,7 +47,7 @@ export default {
<Field <Field
{...props} {...props}
modelValue={''} modelValue={''}
name={Array.isArray(props.name) ? props.name?.pop() : props.name} name={Array.isArray(props.name) ? [...props.name].pop() : props.name}
v-slots={{ v-slots={{
input: () => ( input: () => (
<CheckboxGroup <CheckboxGroup

View File

@ -53,7 +53,7 @@ export default {
readonly readonly
clickable clickable
onClick={() => (state.showPicker = true)} onClick={() => (state.showPicker = true)}
name={Array.isArray(props.name) ? props.name?.pop() : props.name} name={Array.isArray(props.name) ? [...props.name].pop() : props.name}
v-slots={{ v-slots={{
input: () => input: () =>
state.text?.trim() == '' ? ( state.text?.trim() == '' ? (

View File

@ -1,7 +1,7 @@
/* /*
* @Author: * @Author:
* @Date: 2021-05-04 05:36:58 * @Date: 2021-05-04 05:36:58
* @LastEditTime: 2021-07-13 17:14:12 * @LastEditTime: 2021-07-14 10:31:10
* @LastEditors: * @LastEditors:
* @Description: - * @Description: -
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\input\index.tsx * @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\input\index.tsx
@ -18,7 +18,7 @@ export default {
preview: () => ( preview: () => (
<Field name="用户名" label="用户名" labelWidth={50} colon placeholder="请输入用户名" /> <Field name="用户名" label="用户名" labelWidth={50} colon placeholder="请输入用户名" />
), ),
render: ({ model, styles, block, props, custom }) => { render: ({ styles, block, props }) => {
const { registerRef } = useGlobalProperties() const { registerRef } = useGlobalProperties()
let rules = [] let rules = []
@ -30,11 +30,9 @@ export default {
<div style={styles}> <div style={styles}>
<Field <Field
ref={(el) => registerRef(el, block._vid)} ref={(el) => registerRef(el, block._vid)}
{...custom}
{...props} {...props}
{...model.default}
v-model={props.modelValue} v-model={props.modelValue}
name={Array.isArray(props.name) ? props.name?.pop() : props.name} name={Array.isArray(props.name) ? [...props.name].pop() : props.name}
rules={rules} rules={rules}
/> />
</div> </div>

View File

@ -1,7 +1,7 @@
/* /*
* @Author: * @Author:
* @Date: 2021-06-01 09:45:21 * @Date: 2021-06-01 09:45:21
* @LastEditTime: 2021-07-13 20:20:59 * @LastEditTime: 2021-07-13 21:12:46
* @LastEditors: * @LastEditors:
* @Description: - * @Description: -
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\picker\index.tsx * @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\picker\index.tsx
@ -97,7 +97,6 @@ export default {
{ label: '上海', value: 'shanghai' } { label: '上海', value: 'shanghai' }
] ]
}), }),
valueKey: createEditorInputProp({ label: '选项对象的键名', defaultValue: 'label' }),
placeholder: createEditorInputProp({ label: '占位符', defaultValue: '请选择' }), placeholder: createEditorInputProp({ label: '占位符', defaultValue: '请选择' }),
...createFieldProps() ...createFieldProps()
}, },

View File

@ -35,7 +35,7 @@ export default {
<Field <Field
{...props} {...props}
modelValue={''} modelValue={''}
name={Array.isArray(props.name) ? props.name?.pop() : props.name} name={Array.isArray(props.name) ? [...props.name].pop() : props.name}
v-slots={{ v-slots={{
input: () => ( input: () => (
<RadioGroup <RadioGroup

View File

@ -37,7 +37,7 @@ export default {
<Field <Field
{...props} {...props}
modelValue={''} modelValue={''}
name={Array.isArray(props.name) ? props.name?.pop() : props.name} name={Array.isArray(props.name) ? [...props.name].pop() : props.name}
v-slots={{ v-slots={{
input: () => ( input: () => (
<Rate <Rate

View File

@ -37,7 +37,7 @@ export default {
<Field <Field
{...props} {...props}
modelValue={''} modelValue={''}
name={Array.isArray(props.name) ? props.name?.pop() : props.name} name={Array.isArray(props.name) ? [...props.name].pop() : props.name}
v-slots={{ v-slots={{
input: () => ( input: () => (
<Slider <Slider

View File

@ -1,7 +1,7 @@
/* /*
* @Author: * @Author:
* @Date: 2021-06-01 09:45:21 * @Date: 2021-06-01 09:45:21
* @LastEditTime: 2021-07-13 18:39:09 * @LastEditTime: 2021-07-14 10:32:21
* @LastEditors: * @LastEditors:
* @Description: ' - * @Description: ' -
* @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\stepper\index.tsx * @FilePath: \vite-vue3-lowcode\src\packages\base-widgets\stepper\index.tsx
@ -17,6 +17,7 @@ import {
createEditorSelectProp, createEditorSelectProp,
createEditorModelBindProp createEditorModelBindProp
} from '@/visual-editor/visual-editor.props' } from '@/visual-editor/visual-editor.props'
import { watchEffect } from 'vue'
export default { export default {
key: 'stepper', key: 'stepper',
@ -33,7 +34,9 @@ export default {
render: ({ styles, block, props }) => { render: ({ styles, block, props }) => {
const { registerRef } = useGlobalProperties() const { registerRef } = useGlobalProperties()
props.name = Array.isArray(props.name) ? props.name?.pop() : props.name watchEffect(() => {
props.name = Array.isArray(props.name) ? [...props.name].pop() : props.name
})
return () => ( return () => (
<div style={styles}> <div style={styles}>

View File

@ -32,7 +32,7 @@ export default {
<Field <Field
{...props} {...props}
modelValue={''} modelValue={''}
name={Array.isArray(props.name) ? props.name?.pop() : props.name} name={Array.isArray(props.name) ? [...props.name].pop() : props.name}
v-slots={{ v-slots={{
input: () => ( input: () => (
<Switch <Switch

View File

@ -65,7 +65,7 @@ import { useVisualData } from '@/visual-editor/hooks/useVisualData'
import type { FetchApiItem, VisualEditorModel } from '@/visual-editor/visual-editor.utils' import type { FetchApiItem, VisualEditorModel } from '@/visual-editor/visual-editor.utils'
import { useModal } from '@/visual-editor/hooks/useModal' import { useModal } from '@/visual-editor/hooks/useModal'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import { generateUUID } from '@/visual-editor/utils/' import { generateNanoid } from '@/visual-editor/utils/'
import { RequestEnum, ContentTypeEnum } from '@/enums/httpEnum' import { RequestEnum, ContentTypeEnum } from '@/enums/httpEnum'
import { useImportSwaggerJsonModal } from './utils' import { useImportSwaggerJsonModal } from './utils'
@ -95,7 +95,7 @@ const isEdit = computed(() => apis.value.some((item) => item.key == state.ruleFo
* @description 创建空的数据接口对象 * @description 创建空的数据接口对象
*/ */
const createEmptyApiItem = (): FetchApiItem => ({ const createEmptyApiItem = (): FetchApiItem => ({
key: generateUUID(), key: generateNanoid(),
name: '', name: '',
options: { options: {
url: '', // url url: '', // url

View File

@ -60,7 +60,7 @@ import { useVisualData, fieldTypes } from '@/visual-editor/hooks/useVisualData'
import type { VisualEditorModel } from '@/visual-editor/visual-editor.utils' import type { VisualEditorModel } from '@/visual-editor/visual-editor.utils'
import { useModal } from '@/visual-editor/hooks/useModal' import { useModal } from '@/visual-editor/hooks/useModal'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import { generateUUID } from '@/visual-editor/utils/' import { generateNanoid } from '@/visual-editor/utils/'
import { useImportSwaggerJsonModal } from './utils' import { useImportSwaggerJsonModal } from './utils'
interface IState { interface IState {
@ -91,7 +91,7 @@ const createEmptyEntity = () => ({ key: '', name: '', type: 'string', value: ''
*/ */
const createEmptyModel = () => ({ const createEmptyModel = () => ({
name: '', name: '',
key: generateUUID(), key: generateNanoid(),
entitys: [createEmptyEntity()] entitys: [createEmptyEntity()]
}) })

View File

@ -6,7 +6,7 @@
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\data-source\utils.tsx * @FilePath: \vite-vue3-lowcode\src\visual-editor\components\left-aside\components\data-source\utils.tsx
*/ */
import { generateUUID } from '@/visual-editor/utils' import { generateNanoid } from '@/visual-editor/utils'
import type { FetchApiItem } from '@/visual-editor/visual-editor.utils' import type { FetchApiItem } from '@/visual-editor/visual-editor.utils'
import { RequestEnum } from '@/enums/httpEnum' import { RequestEnum } from '@/enums/httpEnum'
import MonacoEditor from '@/visual-editor/components/common/monaco-editor/MonacoEditor' import MonacoEditor from '@/visual-editor/components/common/monaco-editor/MonacoEditor'
@ -27,7 +27,7 @@ export const importSwaggerJson = (swagger: any) => {
const properties = swagger.definitions[model].properties const properties = swagger.definitions[model].properties
const modelItem: VisualEditorModel = { const modelItem: VisualEditorModel = {
name: model, name: model,
key: generateUUID(), key: generateNanoid(),
entitys: [] entitys: []
} }
Object.keys(properties).forEach((field) => { Object.keys(properties).forEach((field) => {
@ -48,7 +48,7 @@ export const importSwaggerJson = (swagger: any) => {
const bindTarget = model ? models.find((item) => item.name == model) : undefined const bindTarget = model ? models.find((item) => item.name == model) : undefined
typeof bindTarget == 'object' && (bindTarget.name = apiUrlObj.summary) typeof bindTarget == 'object' && (bindTarget.name = apiUrlObj.summary)
const api: FetchApiItem = { const api: FetchApiItem = {
key: generateUUID(), key: generateNanoid(),
name: apiUrlObj.summary, name: apiUrlObj.summary,
options: { options: {
url: url, // 请求的url url: url, // 请求的url

View File

@ -22,7 +22,7 @@ import {
ElPopconfirm ElPopconfirm
} from 'element-plus' } from 'element-plus'
import type { Action } from '@/visual-editor/visual-editor.utils' import type { Action } from '@/visual-editor/visual-editor.utils'
import { generateUUID } from '@/visual-editor/utils/' import { generateNanoid } from '@/visual-editor/utils/'
import { useModal } from '@/visual-editor/hooks/useModal' import { useModal } from '@/visual-editor/hooks/useModal'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
@ -34,7 +34,7 @@ interface IState {
* @description * @description
*/ */
const createEmptyActionHandle = () => ({ const createEmptyActionHandle = () => ({
key: generateUUID(), key: generateNanoid(),
name: '', name: '',
link: [] link: []
}) })
@ -43,7 +43,7 @@ const createEmptyActionHandle = () => ({
* @description * @description
*/ */
const createEmptyAction = (): Action => ({ const createEmptyAction = (): Action => ({
key: generateUUID(), key: generateNanoid(),
name: '', name: '',
event: '', event: '',
handle: [createEmptyActionHandle()] handle: [createEmptyActionHandle()]

View File

@ -1,13 +1,13 @@
/* /*
* @Author: * @Author:
* @Date: 2021-06-13 22:07:29 * @Date: 2021-06-13 22:07:29
* @LastEditTime: 2021-06-24 17:42:31 * @LastEditTime: 2021-07-13 21:25:59
* @LastEditors: * @LastEditors:
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\page-setting\pageSetting.tsx * @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\page-setting\pageSetting.tsx
*/ */
import { defineComponent } from 'vue' import { defineComponent } from 'vue'
import { ElForm, ElFormItem, ElInput, ElUpload, ElColorPicker } from 'element-plus' import { ElForm, ElFormItem, ElInput, ElUpload, ElColorPicker, ElSwitch } from 'element-plus'
import styles from './styles.module.scss' import styles from './styles.module.scss'
import { useVisualData } from '@/visual-editor/hooks/useVisualData' import { useVisualData } from '@/visual-editor/hooks/useVisualData'
@ -29,6 +29,9 @@ export const PageSetting = defineComponent({
return () => ( return () => (
<> <>
<ElForm> <ElForm>
<ElFormItem label="路由切换时缓存本页面">
<ElSwitch v-model={pageConfig.keepAlive} />
</ElFormItem>
<ElFormItem label="背景颜色"> <ElFormItem label="背景颜色">
<ElColorPicker v-model={pageConfig.bgColor} /> <ElColorPicker v-model={pageConfig.bgColor} />
</ElFormItem> </ElFormItem>

View File

@ -5,7 +5,8 @@
* @descriptionuseVisualData * @descriptionuseVisualData
* @update: 2021/5/6 11:59 * @update: 2021/5/6 11:59
*/ */
import { reactive, inject, readonly, computed, watch, InjectionKey } from 'vue' import { reactive, inject, readonly, computed, watch } from 'vue'
import type { InjectionKey } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import type { import type {
VisualEditorModelValue, VisualEditorModelValue,
@ -38,7 +39,8 @@ export const createNewPage = ({ title = '新页面', path = '/' }) => ({
path, path,
config: { config: {
bgColor: '', bgColor: '',
bgImage: '' bgImage: '',
keepAlive: false
}, },
blocks: [] blocks: []
}) })

View File

@ -1,11 +1,12 @@
/* /*
* @Author: * @Author:
* @Date: 2021-06-01 09:45:21 * @Date: 2021-06-01 09:45:21
* @LastEditTime: 2021-06-24 21:57:31 * @LastEditTime: 2021-07-14 09:09:02
* @LastEditors: * @LastEditors:
* @Description: * @Description:
* @FilePath: \vite-vue3-lowcode\src\visual-editor\utils\index.ts * @FilePath: \vite-vue3-lowcode\src\visual-editor\utils\index.ts
*/ */
import { customAlphabet } from 'nanoid'
/** /**
* @description URL * @description URL
@ -13,18 +14,6 @@
export const BASE_URL = import.meta.env.BASE_URL export const BASE_URL = import.meta.env.BASE_URL
/** /**
* @description UUID * @description nanoid
* @param {boolean} [noSymbol=false] -
* @returns {string}
*/ */
export function generateUUID(noSymbol = false) { export const generateNanoid = customAlphabet('1234567890abcdef', 10)
let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = (Math.random() * 16) | 0,
v = c == 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
})
if (noSymbol) {
uuid = uuid.replace(/-/g, '')
}
return uuid
}

View File

@ -3,6 +3,7 @@ import { inject, provide } from 'vue'
import type { CSSProperties } from 'vue' import type { CSSProperties } from 'vue'
import { useDotProp } from '@/visual-editor/hooks/useDotProp' import { useDotProp } from '@/visual-editor/hooks/useDotProp'
import type { RequestEnum, ContentTypeEnum } from '@/enums/httpEnum' import type { RequestEnum, ContentTypeEnum } from '@/enums/httpEnum'
import { generateNanoid } from '@/visual-editor/utils'
/** /**
* @description * @description
@ -70,6 +71,8 @@ export interface PageConfig {
bgImage: string bgImage: string
/** 背景颜色 */ /** 背景颜色 */
bgColor: string bgColor: string
/** 是否缓存当前页面 */
keepAlive: boolean
} }
/** /**
* @description * @description
@ -224,9 +227,8 @@ export interface VisualEditorMarkLines {
} }
export function createNewBlock(component: VisualEditorComponent): VisualEditorBlockData { export function createNewBlock(component: VisualEditorComponent): VisualEditorBlockData {
const cid = parseInt(`${Date.now() * Math.random()}`)
return { return {
_vid: `vid_${cid}`, _vid: `vid_${generateNanoid()}`,
moduleName: component.moduleName, moduleName: component.moduleName,
componentKey: component!.key, componentKey: component!.key,
label: component!.label, label: component!.label,

View File

@ -676,11 +676,16 @@
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c"
integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==
"@types/node@*", "@types/node@^16.3.1": "@types/node@*":
version "16.3.1" version "16.3.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.3.1.tgz#24691fa2b0c3ec8c0d34bfcfd495edac5593ebb4" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.3.1.tgz#24691fa2b0c3ec8c0d34bfcfd495edac5593ebb4"
integrity sha512-N87VuQi7HEeRJkhzovao/JviiqKjDKMVKxKMfUvSKw+MbkbW8R0nA3fi/MQhhlxV2fQ+2ReM+/Nt4efdrJx3zA== integrity sha512-N87VuQi7HEeRJkhzovao/JviiqKjDKMVKxKMfUvSKw+MbkbW8R0nA3fi/MQhhlxV2fQ+2ReM+/Nt4efdrJx3zA==
"@types/node@^16.3.2":
version "16.3.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.3.2.tgz#655432817f83b51ac869c2d51dd8305fb8342e16"
integrity sha512-jJs9ErFLP403I+hMLGnqDRWT0RYKSvArxuBVh2veudHV7ifEC1WAmjJADacZ7mRbA2nWgHtn8xyECMAot0SkAw==
"@types/normalize-package-data@^2.4.0": "@types/normalize-package-data@^2.4.0":
version "2.4.1" version "2.4.1"
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"