Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
257a43a136 chore(deps): bump js-yaml from 3.14.1 to 3.14.2
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.14.1 to 3.14.2.
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/3.14.1...3.14.2)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 3.14.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-17 19:48:21 +00:00
29 changed files with 143 additions and 394 deletions

View File

@@ -140,6 +140,5 @@
"src/**/*.{js,vue}": [
"eslint --fix"
]
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
}

View File

@@ -107,10 +107,6 @@ export default {
this.$emit('add', true)
}
}).catch(error => {
if (error?.response?.data?.code === 'no_valid_assets') {
this.$message.error(error?.response?.data?.detail)
return
}
this.iVisible = true
this.handleResult(null, error)
})

View File

@@ -62,7 +62,6 @@ import Dialog from '@/components/Dialog/index.vue'
import PasswordHistoryDialog from './PasswordHistoryDialog.vue'
import { SecretViewerFormatter } from '@/components/Table/TableFormatters'
import { encryptPassword } from '@/utils/secure'
import { mapGetters } from 'vuex'
export default {
name: 'ShowSecretInfo',
@@ -112,9 +111,6 @@ export default {
}
},
computed: {
...mapGetters({
publicSettings: 'publicSettings'
}),
secretTypeLabel() {
return this.account['secret_type'].label || 'Password'
},
@@ -150,11 +146,7 @@ export default {
})
},
showSecretDialog() {
if (!this.publicSettings.SECURITY_ACCOUNT_SECRET_READ) {
this.$message.warning(this.$tc('AccountSecretReadDisabled'))
return
}
return this.$axios.get(this.url).then((res) => {
return this.$axios.get(this.url, { disableFlashErrorMsg: true }).then((res) => {
this.secretInfo = res
this.sshKeyFingerprint = res?.spec_info?.ssh_key_fingerprint || '-'
this.showSecret = true
@@ -175,54 +167,54 @@ export default {
</script>
<style lang="scss" scoped>
.item-textarea ::v-deep .el-textarea__inner {
height: 110px;
}
.el-form-item {
border-bottom: 1px solid #EBEEF5;
padding: 5px 0;
margin-bottom: 0;
&:last-child {
border-bottom: none;
.item-textarea ::v-deep .el-textarea__inner {
height: 110px;
}
::v-deep .el-form-item__label {
display: flex;
align-items: center;
justify-content: flex-start;
padding-right: 20px;
line-height: 30px;
word-break: keep-all;
overflow-wrap: break-word;
white-space: normal;
}
.el-form-item {
border-bottom: 1px solid #EBEEF5;
padding: 5px 0;
margin-bottom: 0;
::v-deep .el-form-item__content {
line-height: 30px;
&:last-child {
border-bottom: none;
}
pre {
margin: 0;
::v-deep .el-form-item__label {
display: flex;
align-items: center;
justify-content: flex-start;
padding-right: 20px;
line-height: 30px;
word-break: keep-all;
overflow-wrap: break-word;
white-space: normal;
}
::v-deep .el-form-item__content {
line-height: 30px;
pre {
margin: 0;
}
}
}
}
ul {
margin: 0;
}
li {
display: block;
font-size: 13px;
margin-bottom: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.title {
color: #303133;
font-weight: 500;
ul {
margin: 0;
}
li {
display: block;
font-size: 13px;
margin-bottom: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.title {
color: #303133;
font-weight: 500;
}
}
}
</style>

View File

@@ -223,21 +223,9 @@ export default {
const mapped = {}
Object.entries(errors || {}).forEach(([k, v]) => {
let msg = v
console.log(k, v)
// v是数组并且数组都是字符串则拼接为字符串
if (Array.isArray(v) && v.every(item => typeof item === 'string')) msg = v.join('; ')
// 处理 [{"port":["请确保该值小于或者等于 65535。"]},{},{}] 这种情况
else if (Array.isArray(v) && v.every(item => _.isPlainObject(item))) {
const subMsg = []
v.forEach((subItem) => {
Object.values(subItem).forEach((subMsgArr) => {
if (Array.isArray(subMsgArr)) {
subMsg.push(...subMsgArr)
}
})
})
msg = subMsg.join(' ')
} else if (typeof v === 'object' && v !== null) msg = JSON.stringify(v)
else if (typeof v === 'object' && v !== null) msg = JSON.stringify(v)
mapped[k] = String(msg || '')
})
this.serverErrors = mapped

View File

@@ -4,11 +4,15 @@
<div class="panel-title">
<el-avatar :src="imageUrl" shape="square" />
<div class="title-display">
<p class="name" :title="object.name">{{ object.name }}</p>
<span class="name">{{ object.name }}</span>
<span class="comment">{{ object.provider.label }}</span>
</div>
</div>
<div v-if="iActions.length !== 0" class="panel-actions" @click="handleClick($event)">
<div
v-if="iActions.length !== 0"
class="panel-actions"
@click="handleClick($event)"
>
<el-dropdown>
<el-button size="mini">
<i class="el-icon-more el-icon--right" />
@@ -60,19 +64,21 @@ export default {
},
getImage: {
type: Function,
default: obj => ''
default: (obj) => ''
},
getInfos: {
type: Function,
default: obj => []
default: (obj) => []
},
handleUpdate: {
type: Function,
default: () => {}
default: () => {
}
},
onView: {
type: Function,
default: () => {}
default: () => {
}
}
},
data() {
@@ -146,13 +152,13 @@ export default {
</script>
<style lang="scss" scoped>
div.info-panel {
display: flex;
flex-direction: column;
padding: 10px;
gap: unset;
gap: 10px;
cursor: pointer;
height: initial !important;
.panel-header {
padding: 10px 20px;
@@ -169,22 +175,12 @@ div.info-panel {
.title-display {
display: flex;
flex-basis: 225px;
flex-direction: column;
justify-content: center;
align-items: start;
max-width: 225px;
min-width: 0;
overflow-x: hidden;
text-align: left;
.name {
font-size: 1.1em;
color: #555555;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
margin: unset;
}
.comment {

View File

@@ -38,7 +38,6 @@
<script>
import { copy, downloadText } from '@/utils/common/index'
import BaseFormatter from '@/components/Table/TableFormatters/base.vue'
import { mapGetters } from 'vuex'
export default {
name: 'SecretViewerFormatter',
@@ -70,9 +69,6 @@ export default {
}
},
computed: {
...mapGetters({
publicSettings: 'publicSettings'
}),
hasShow: function() {
return this.formatterArgs.hasShow
},
@@ -144,10 +140,6 @@ export default {
},
methods: {
async getAccountSecret() {
if (!this.publicSettings.SECURITY_ACCOUNT_SECRET_READ) {
this.$message.warning(this.$tc('AccountSecretReadDisabled'))
return
}
if (this.formatterArgs.secretFrom === 'cellValue' || this.getIt) {
return
}
@@ -186,48 +178,48 @@ export default {
}
</script>
<style lang="scss" scoped>
.content {
display: inline-block;
width: 100%;
overflow: hidden;
//white-space: nowrap;
text-overflow: ellipsis;
font-size: 13px;
.text {
flex: 1;
display: inline;
margin: 0;
padding: 0;
.content {
display: inline-block;
width: 100%;
overflow: hidden;
white-space: nowrap;
//white-space: nowrap;
text-overflow: ellipsis;
}
.action {
font-size: 13px;
cursor: pointer;
margin-left: 1px;
display: inline;
&.right {
float: right;
.text {
flex: 1;
display: inline;
margin: 0;
padding: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.fa {
margin-right: 5px;
.action {
font-size: 13px;
cursor: pointer;
margin-left: 1px;
display: inline;
&:hover {
color: var(--color-primary);
&.right {
float: right;
}
.fa {
margin-right: 5px;
&:hover {
color: var(--color-primary);
}
}
}
}
}
.edit-input ::v-deep input {
border-left: none;
border-right: none;
border-top: none;
height: 30px;
}
.edit-input ::v-deep input {
border-left: none;
border-right: none;
border-top: none;
height: 30px;
}
</style>

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free v5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M512 176.001C512 273.203 433.202 352 336 352c-11.22 0-22.19-1.062-32.827-3.069l-24.012 27.014A23.999 23.999 0 0 1 261.223 384H224v40c0 13.255-10.745 24-24 24h-40v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24v-78.059c0-6.365 2.529-12.47 7.029-16.971l161.802-161.802C163.108 213.814 160 195.271 160 176 160 78.798 238.797.001 335.999 0 433.488-.001 512 78.511 512 176.001zM336 128c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48-48 21.49-48 48z"/></svg>

Before

Width:  |  Height:  |  Size: 691 B

View File

@@ -65,17 +65,6 @@ export default {
'usingOrgs',
'currentViewRoute'
]),
currentOrgDisplayName() {
const currentOrgId = this.currentOrg?.id
if (!currentOrgId) {
return this.$tc('Select')
}
const matchedOrg = this.usingOrgs.find(item => item.id === currentOrgId)
if (matchedOrg?.name) {
return matchedOrg.name
}
return this.currentOrg.name || this.$tc('Select')
},
orgActionsGroup() {
const orgActions = {
label: this.$t('OrganizationList'),
@@ -121,8 +110,11 @@ export default {
}
},
watch: {
currentOrgDisplayName() {
this.updateWidth()
currentOrg: {
handler() {
this.updateWidth()
},
deep: true
}
},
mounted() {
@@ -141,9 +133,8 @@ export default {
tempSpan.style.fontWeight = 'normal'
tempSpan.style.letterSpacing = 'normal'
// 获取当前组织显示名称
const orgName = this.currentOrgDisplayName
// 获取当前组织名称
const orgName = this.currentOrg.name || this.$tc('Select')
tempSpan.textContent = orgName
document.body.appendChild(tempSpan)

View File

@@ -167,7 +167,8 @@ export default {
}
</script>
<style lang="scss" scoped>
<style lang='scss' scoped>
.page.no-title {
::v-deep {
.page-submenu .el-tabs__header {
@@ -198,14 +199,6 @@ export default {
opacity: 1;
}
}
&.is-disabled {
cursor: not-allowed;
&:hover {
color: #c0c4cc;
}
}
}
.el-tabs__nav-next {

View File

@@ -123,16 +123,6 @@ export default {
permissions: ['authentication.view_connectiontoken']
}
},
{
path: '/profile/access-token',
component: () => import('@/views/profile/AccessToken'),
name: 'AccessToken',
meta: {
title: i18n.t('AccessToken'),
icon: 'access-token',
permissions: ['oauth2_provider.view_accesstoken']
}
},
{
path: '/profile/preferences',
name: 'Preferences',

View File

@@ -149,11 +149,6 @@ export function getErrorResponseMsg(error) {
.join('; ')
} else if (typeof data === 'string') {
return data
} else if (_.isPlainObject(data)) {
return Object.values(data)
.map(item => getErrorResponseMsg(item))
.filter(i => i)
.join('; ')
} else {
msg = error.toString()
}

View File

@@ -137,8 +137,8 @@ export default {
getUrlQuery: true,
options: [
{
label: this.$t('ID'),
value: 'id'
label: this.$t('TaskID'),
value: 'automation_id'
},
{
label: this.$t('DisplayName'),

View File

@@ -43,9 +43,7 @@ export default {
asset: ''
},
treeSetting: {
showMenu: (node) => {
return node?.meta?.type === 'asset'
},
showMenu: true,
showRefresh: true,
showSearch: true,
showAssets: true,
@@ -57,8 +55,9 @@ export default {
menu: [
{
id: 'check',
name: this.$t('RiskDetection'),
name: this.$t('Check'),
icon: 'scan',
has: (node) => node?.meta?.type === 'asset',
callback: (node) => {
vm.detectDialog.asset = node.id
setTimeout(() => {

View File

@@ -6,6 +6,7 @@
class="risk-review-drawer"
destroy-on-close
direction="rtl"
style="z-index: 999"
>
<div class="drawer-container">
<div class="drawer-body">

View File

@@ -61,11 +61,8 @@ export default {
},
callbacks: {
change: function(val) {
const category = this.object.category.value
const normalizedCategory =
category === 'ds' ? 'directorie' : category
this.$axios.patch(
`/api/v1/assets/${normalizedCategory}s/${this.object.id}/`,
`/api/v1/assets/assets/${this.object.id}/`,
{ is_active: val }
).then(res => {
this.$message.success(this.$tc('UpdateSuccessMsg'))

View File

@@ -77,7 +77,7 @@ export default {
[this.$tc('Platform'), 'platform'],
[this.$tc('Node'), 'node'],
[this.$tc('Protocol'), 'protocols'],
[this.$tc('Region'), 'region_name']
[this.$tc('Region'), 'region_id']
],
data: []
},
@@ -124,7 +124,7 @@ export default {
this.ws.onmessage = e => {
const data = JSON.parse(e.data)
if (data.action === 'sync_region') {
this.addRegion(data.id, data.name)
this.addRegion(data.region_id)
} else if (data.action === 'import') {
data['@status'] = 'pending'
this.$refs.importTable.addTableItem(data)
@@ -140,10 +140,10 @@ export default {
}
}
},
addRegion(regionId, regionName) {
if (!this.alreadySync.includes(regionId)) {
this.alreadySync.push(regionId)
this.tip = `${this.$t('SyncRegion')}: ${regionName}`
addRegion(region) {
if (!this.alreadySync.includes(region)) {
this.alreadySync.push(region)
this.tip = `${this.$t('SyncRegion')}: ${this.alreadySync.at(-1)}`
}
},
showResult() {

View File

@@ -17,8 +17,6 @@ export const ucloud = 'ucloud'
export const volcengine = 'volcengine'
export const ctyun = 'ctyun'
export const qingcloud_private = 'qingcloud_private'
export const huaweicloud_private = 'huaweicloud_private'
export const ctyun_private = 'ctyun_private'
@@ -48,8 +46,7 @@ export const publicHostProviders = [
gcp,
ucloud,
volcengine,
smartx,
ctyun
smartx
]
export const publicDBProviders = [aliyun]
@@ -144,12 +141,6 @@ export const ACCOUNT_PROVIDER_ATTRS_MAP = {
attrs: ['access_key_id', 'access_key_secret'],
image: require('@/assets/img/cloud/volcengine.svg')
},
[ctyun]: {
name: ctyun,
title: i18n.t('CTYun'),
attrs: ['access_key_id', 'access_key_secret', 'project_id'],
image: require('@/assets/img/cloud/state.svg')
},
[vmware]: {
name: vmware,
title: 'VMware',

View File

@@ -408,6 +408,7 @@ export default {
createJob(data).then(res => {
this.progressLength = 0
this.executionInfo.timeCost = 0
this.showProgress = true
this.speedText = ''
const form = new FormData()
const start = Date.now()
@@ -435,7 +436,6 @@ export default {
}
}
}).then(res => {
this.showProgress = true
this.executionInfo.status = 'running'
this.currentTaskId = res.task_id
this.xtermConfig = { taskId: this.currentTaskId, type: 'shortcut_cmd' }

View File

@@ -8,6 +8,7 @@ export const UserAssetPermissionListPageSearchConfigOptions = [
{ label: i18n.t('UserGroups'), value: 'user_group' },
{ label: i18n.t('AssetName'), value: 'asset_name' },
{ label: i18n.t('AssetAddress'), value: 'address' },
{ label: i18n.t('Account'), value: 'accounts' },
{
label: i18n.t('Valid'),
value: 'is_valid',

View File

@@ -1,77 +0,0 @@
<template>
<GenericListPage
ref="GenericListTable"
:header-actions="headerActions"
:help-tip="helpMessage"
:table-config="tableConfig"
/>
</template>
<script>
import { GenericListPage } from '@/layout/components'
export default {
components: {
GenericListPage
},
data() {
const ajaxUrl = '/api/v1/authentication/access-tokens/'
return {
helpMessage: this.$t('AccessTokenTip'),
tableConfig: {
hasSelection: false,
url: ajaxUrl,
columns: [
'token_preview', 'scope', 'is_valid', 'expires', 'updated', 'created', 'actions'
],
columnsMeta: {
actions: {
prop: '',
formatterArgs: {
hasUpdate: false,
hasClone: false,
hasDelete: false,
extraActions: [
{
name: 'Revoke',
title: this.$t('Revoke'),
can: ({ row }) => this.$hasPerm('oauth2_provider.delete_accesstoken'),
type: 'info',
callback: function({ row }) {
this.$axios.delete(`${ajaxUrl}${row.id}/revoke/`,
).then(res => {
this.reloadTable()
this.$message.success(this.$tc('UpdateSuccessMsg'))
}).catch(error => {
this.$message.error(this.$tc('UpdateErrorMsg' + ' ' + error))
})
}.bind(this)
}
]
}
}
}
},
headerActions: {
hasLeftActions: false,
hasSearch: false,
hasRightActions: true,
hasRefresh: true,
hasExport: false,
hasImport: false,
hasBulkDelete: false,
hasCreate: false,
extraActions: []
}
}
},
methods: {
reloadTable() {
this.$refs.GenericListTable.reloadTable()
}
}
}
</script>
<style scoped>
</style>

View File

@@ -32,22 +32,6 @@ export default {
}
}
},
computed: {
passwordMenuDisabled() {
return this.$store.state.users.profile.source.value !== 'local'
}
},
watch: {
passwordMenuDisabled: {
immediate: true,
handler(disabled) {
this.config.submenu = this.getSubmenu()
if (disabled && this.config.activeMenu === 'Password') {
this.config.activeMenu = 'SSHKeyList'
}
}
}
},
methods: {
getSubmenu() {
return [

View File

@@ -96,6 +96,7 @@ export default {
{
title: this.$t('FacialFeatures'),
has: this.$store.getters.publicSettings.FACE_RECOGNITION_ENABLED &&
this.$store.getters.publicSettings.XPACK_LICENSE_EDITION_ULTIMATE &&
!store.getters.publicSettings['PRIVACY_MODE'],
attrs: {
type: 'primary',

View File

@@ -1,41 +1,36 @@
<template>
<TwoCol>
<template>
<Account :url="url" :columns-meta="columnsMeta" :object.sync="object" />
</template>
<template #right>
<QuickActions :actions="quickActions" type="primary" />
</template>
</TwoCol>
<Account
:url="url"
:columns-meta="columnsMeta"
:extra-quick-actions="quickActions"
:object.sync="object"
/>
</template>
<script>
import { QuickActions } from '@/components'
import Account from '@/views/assets/Asset/AssetDetail/Account'
import TwoCol from '@/layout/components/Page/TwoColPage.vue'
export default {
name: 'Accounts',
components: {
TwoCol,
Account,
QuickActions
Account
},
props: {
object: {
type: Object,
default: () => {}
default: () => {
}
}
},
data() {
return {
columnsMeta: {
name: {
formatter: row => <span>{row.name}</span>
formatter: (row) => <span>{row.name}</span>
},
asset: {
label: this.$t('Asset'),
formatter: row => <span>{row.asset.name}</span>
formatter: (row) => <span>{row.asset.name}</span>
}
},
quickActions: [

View File

@@ -29,7 +29,7 @@ export default {
'CAS_RENAME_ATTRIBUTES'
]],
[this.$t('Other'), [
'CAS_ORG_IDS', 'CAS_LOGOUT_COMPLETELY'
'CAS_ORG_IDS', 'CAS_CREATE_USER', 'CAS_LOGOUT_COMPLETELY'
]]
],
fieldsMeta: {

View File

@@ -53,9 +53,7 @@ export default {
'GPT_BASE_URL',
'GPT_API_KEY',
'GPT_PROXY',
'GPT_MODEL',
'CUSTOM_GPT_MODEL',
'CUSTOM_DEEPSEEK_MODEL'
'GPT_MODEL'
],
fieldsMeta: {
CHAT_AI_TYPE: {
@@ -117,16 +115,6 @@ export default {
},
CHAT_AI_EMBED_URL: {
hidden: (formValue) => formValue.CHAT_AI_METHOD !== 'embed'
},
CUSTOM_GPT_MODEL: {
hidden: (formValue) => {
return formValue.CHAT_AI_METHOD !== 'api' || formValue.CHAT_AI_TYPE !== 'gpt' || formValue.GPT_MODEL !== 'custom'
}
},
CUSTOM_DEEPSEEK_MODEL: {
hidden: (formValue) => {
return formValue.CHAT_AI_METHOD !== 'api' || formValue.CHAT_AI_TYPE !== 'deep-seek' || formValue.DEEPSEEK_MODEL !== 'custom'
}
}
},
submitMethod() {

View File

@@ -6,7 +6,6 @@
:create-drawer="createDrawer"
:detail-drawer="detailDrawer"
:header-actions="iTicketAction"
:quick-filters="quickFilters"
:table-config="ticketTableConfig"
/>
</template>
@@ -42,72 +41,6 @@ export default {
loading: true,
getDrawerTitle: () => ' ',
createDrawer: () => import('@/views/tickets/RequestAssetPerm/CreateUpdate'),
quickFilters: [
{
label: this.$t('Type'),
options: [
{
label: this.$t('ApplyAsset'),
filter: {
type: 'apply_asset'
}
},
{
label: this.$t('LoginConfirm'),
filter: {
type: 'login_confirm'
}
},
{
label: this.$t('CommandConfirm'),
filter: {
type: 'command_confirm'
}
},
{
label: this.$t('LoginAssetConfirm'),
filter: {
type: 'login_asset_confirm'
}
}
]
},
{
label: this.$t('Action'),
options: [
{
label: this.$t('All'),
filter: {
state: 'all'
}
},
{
label: this.$t('Open'),
filter: {
state: 'pending'
}
},
{
label: this.$t('Cancel'),
filter: {
state: 'closed'
}
},
{
label: this.$t('Approved'),
filter: {
state: 'approved'
}
},
{
label: this.$t('Rejected'),
filter: {
state: 'rejected'
}
}
]
}
],
detailDrawer: null,
ticketTableConfig: {
url: this.url,
@@ -209,7 +142,7 @@ export default {
}
},
defaultTicketActions: {
hasImport: false,
hasExport: false,
hasMoreActions: false,
hasLeftActions: true,
canCreate: this.$hasPerm('tickets.view_ticket'),
@@ -256,6 +189,10 @@ export default {
value: 'relevant_asset',
label: this.$t('RelevantAsset')
},
{
value: 'relevant_system_user',
label: this.$t('RelevantCommand')
},
{
value: 'relevant_command',
label: this.$t('ApplyRunCommand')

View File

@@ -147,7 +147,7 @@ export default {
this.loading = true
const url = `/api/v1/tickets/comments/?ticket_id=${this.object.id}`
this.$axios.get(url).then(res => {
this.comments = res
this.comments = res.results
}).catch(err => {
this.$message.error(err)
}).finally(() => {

View File

@@ -161,7 +161,8 @@ module.exports = {
target: process.env.VUE_APP_CORE_HOST || 'http://127.0.0.1:8080',
changeOrigin: true
}
}
},
after: require('./mock/mock-server.js')
},
css: {},
configureWebpack: {

View File

@@ -8570,9 +8570,9 @@ js-tokens@^3.0.2:
integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==
js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.14.0, js-yaml@^3.7.0, js-yaml@^3.9.1:
version "3.14.1"
resolved "https://registry.npmmirror.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
version "3.14.2"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.2.tgz#77485ce1dd7f33c061fd1b16ecea23b55fcb04b0"
integrity sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"