Compare commits

...

24 Commits

Author SHA1 Message Date
かっこかり 351d7d1444
Merge b3a1833e4f into d2154214ba 2026-01-29 19:11:46 +09:00
renovate[bot] d2154214ba
fix(deps): update dependency tar to v7.5.7 [security] (#17104)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-29 18:18:34 +09:00
renovate[bot] 97312b97f8
chore(deps): update pnpm to v10.28.2 [security] (#17133)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-29 10:53:08 +09:00
かっこかり b3a1833e4f
Merge branch 'develop' into fix-signout 2026-01-13 16:07:18 +09:00
kakkokari-gtyih 659bde85d1 fix types 2026-01-11 15:16:11 +09:00
kakkokari-gtyih cea634b45c Merge remote-tracking branch 'msky/develop' into fix-signout 2026-01-11 15:15:08 +09:00
かっこかり 3e62dbc7ea
Merge branch 'develop' into fix-signout 2026-01-09 23:49:30 +09:00
かっこかり cf76064ec1
Merge branch 'develop' into fix-signout 2026-01-09 16:23:00 +09:00
かっこかり 208681de4b
Merge branch 'develop' into fix-signout 2026-01-07 22:08:57 +09:00
かっこかり 40ea7ec8c9
Merge branch 'develop' into fix-signout 2026-01-02 22:07:35 +09:00
かっこかり 4475cf4151
Merge branch 'develop' into fix-signout 2026-01-01 10:58:41 +09:00
かっこかり 89cf12d4b4
Merge branch 'develop' into fix-signout 2025-12-31 22:35:12 +09:00
かっこかり 2bf40acc79
Merge branch 'develop' into fix-signout 2025-12-30 16:00:00 +09:00
かっこかり 1fa0c176f9
Merge branch 'develop' into fix-signout 2025-12-28 21:37:29 +09:00
かっこかり 55c296e3b5
Merge branch 'develop' into fix-signout 2025-12-28 20:00:51 +09:00
kakkokari-gtyih 727e84bd59 fix 2025-12-27 15:46:14 +09:00
kakkokari-gtyih 821d23855c fix: replace individual delete calls with delMany for improved efficiency 2025-12-27 15:43:08 +09:00
kakkokari-gtyih a2250a2733 fix: simplify state removal logic 2025-12-27 15:40:30 +09:00
kakkokari-gtyih 527ecdb926 Update Changelog 2025-12-27 15:34:41 +09:00
kakkokari-gtyih 8d90e9a556 rename 2025-12-27 15:31:51 +09:00
kakkokari-gtyih e2920db7d4 fix: アカウント削除の際にもそのアカウント関連の設定値を削除するように 2025-12-27 15:29:54 +09:00
kakkokari-gtyih 4afcb58a64 enhance: implement refresh accounts 2025-12-27 15:13:55 +09:00
kakkokari-gtyih a2e05c6bff Update Changelog 2025-12-27 15:09:42 +09:00
kakkokari-gtyih d2ce24dcc6 fix(frontend): ログアウトするとすべてのアカウントからログアウトされる問題を修正 2025-12-27 15:09:16 +09:00
14 changed files with 278 additions and 69 deletions

View File

@ -14,10 +14,13 @@
- Enhance: ウィジェットの表示設定をプレビューを見ながら行えるように
- Enhance: ウィジェットの設定項目のラベルの多言語対応
- Enhance: 画面幅が広いときにメディアを横並びで表示できるようにするオプションを追加
- Enhance: アカウント管理ページで、全てのアカウントから一括でログアウトできるように
- Enhance: パフォーマンスの向上
- Fix: ドライブクリーナーでファイルを削除しても画面に反映されない問題を修正 #16061
- Fix: 非ログイン時にログインを求めるダイアログが表示された後にダイアログのぼかしが解除されず操作不能になることがある問題を修正
- Fix: ドライブのソートが「登録日(昇順)」の場合に正しく動作しない問題を修正
- Fix: ログアウトボタンを押下するとすべてのアカウントからログアウトする問題を修正
- Fix: アカウント管理ページで、アカウントの追加・削除を行ってもリストに反映されない問題を修正
- Fix: 高度なMFMのピッカーを使用する際の挙動を改善
- Fix: 管理画面でアーカイブ済のお知らせを表示した際にアクティブなお知らせが多い旨の警告が出る問題を修正
- Fix: ファイルタブのセンシティブメディアを開く際に確認ダイアログを出す設定が適用されない問題を修正

View File

@ -34,6 +34,7 @@ noAccountDescription: "自己紹介はありません"
login: "ログイン"
loggingIn: "ログイン中"
logout: "ログアウト"
logoutFromAll: "すべてのアカウントからログアウト"
signup: "新規登録"
uploading: "アップロード中"
save: "保存"
@ -992,6 +993,7 @@ numberOfPageCache: "ページキャッシュ数"
numberOfPageCacheDescription: "多くすると利便性が向上しますが、負荷とメモリ使用量が増えます。"
logoutConfirm: "ログアウトしますか?"
logoutWillClearClientData: "ログアウトするとクライアントの設定情報がブラウザから消去されます。再ログイン時に設定情報を復元できるようにするためには、設定の自動バックアップを有効にしてください。"
logoutFromOtherAccountConfirm: "{username}からログアウトしますか?"
lastActiveDate: "最終利用日時"
statusbar: "ステータスバー"
pleaseSelect: "選択してください"

View File

@ -6,7 +6,7 @@
"type": "git",
"url": "https://github.com/misskey-dev/misskey.git"
},
"packageManager": "pnpm@10.28.0",
"packageManager": "pnpm@10.28.2",
"workspaces": [
"packages/misskey-js",
"packages/i18n",
@ -59,7 +59,7 @@
"ignore-walk": "8.0.0",
"js-yaml": "4.1.1",
"postcss": "8.5.6",
"tar": "7.5.6",
"tar": "7.5.7",
"terser": "5.46.0"
},
"devDependencies": {
@ -75,7 +75,7 @@
"eslint": "9.39.2",
"globals": "16.5.0",
"ncp": "2.0.0",
"pnpm": "10.28.0",
"pnpm": "10.28.2",
"typescript": "5.9.3",
"start-server-and-test": "2.1.3"
},

View File

@ -19,13 +19,15 @@ import { signout } from '@/signout.js';
type AccountWithToken = Misskey.entities.MeDetailed & { token: string };
export async function getAccounts(): Promise<{
export type AccountData = {
host: string;
id: Misskey.entities.User['id'];
username: Misskey.entities.User['username'];
user?: Misskey.entities.MeDetailed | null;
token: string | null;
}[]> {
};
export async function getAccounts(): Promise<AccountData[]> {
const tokens = store.s.accountTokens;
const accountInfos = store.s.accountInfos;
const accounts = prefer.s.accounts;
@ -33,8 +35,8 @@ export async function getAccounts(): Promise<{
host,
id: user.id,
username: user.username,
user: accountInfos[host + '/' + user.id],
token: tokens[host + '/' + user.id] ?? null,
user: accountInfos[`${host}/${user.id}`],
token: tokens[`${host}/${user.id}`] ?? null,
}));
}
@ -53,10 +55,15 @@ export async function removeAccount(host: string, id: AccountWithToken['id']) {
const accountInfos = JSON.parse(JSON.stringify(store.s.accountInfos));
delete accountInfos[host + '/' + id];
store.set('accountInfos', accountInfos);
prefer.commit('accounts', prefer.s.accounts.filter(x => x[0] !== host || x[1].id !== id));
}
export async function removeAccountAssociatedData(host: string, id: AccountWithToken['id']) {
// 設定・状態を削除
prefer.clearAccountSettingsFromDevice(host, id);
await store.clearAccountDataFromDevice(id);
}
const isAccountDeleted = Symbol('isAccountDeleted');
function fetchAccount(token: string, id?: string, forceShowDialog?: boolean): Promise<Misskey.entities.MeDetailed> {
@ -162,14 +169,36 @@ export async function refreshCurrentAccount() {
});
}
export async function login(token: AccountWithToken['token'], redirect?: string) {
export async function refreshAccounts() {
const accounts = await getAccounts();
for (const account of accounts) {
if (account.host === host && account.id === $i?.id) {
await refreshCurrentAccount();
} else if (account.token) {
try {
const user = await fetchAccount(account.token, account.id);
store.set('accountInfos', { ...store.s.accountInfos, [account.host + '/' + account.id]: user });
} catch (e) {
if (e === isAccountDeleted) {
await removeAccount(account.host, account.id);
await removeAccountAssociatedData(account.host, account.id);
}
}
}
}
}
export async function login(token: AccountWithToken['token'], redirect?: string, showWaiting = true) {
const showing = ref(true);
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), {
success: false,
showing: showing,
}, {
closed: () => dispose(),
});
if (showWaiting) {
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), {
success: false,
showing: showing,
}, {
closed: () => dispose(),
});
}
const me = await fetchAccount(token, undefined, true).catch(reason => {
showing.value = false;
@ -195,7 +224,7 @@ export async function login(token: AccountWithToken['token'], redirect?: string)
}
export async function switchAccount(host: string, id: string) {
const token = store.s.accountTokens[host + '/' + id];
const token = store.s.accountTokens[`${host}/${id}`];
if (token) {
login(token);
} else {

View File

@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-adaptive-bg :class="[$style.root]">
<MkAvatar :class="$style.avatar" :user="user" indicator/>
<div :class="$style.body">
<span :class="$style.name"><MkUserName :user="user"/></span>
<span :class="$style.name"><MkUserName :user="user"/><slot name="nameSuffix"></slot></span>
<span :class="$style.sub"><slot name="sub"><span class="_monospace">@{{ acct(user) }}</span></slot></span>
</div>
<MkMiniChart v-if="chartValues" :class="$style.chart" :src="chartValues"/>

View File

@ -12,7 +12,7 @@ import { BroadcastChannel } from 'broadcast-channel';
import type { Ref } from 'vue';
import { $i } from '@/i.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { get, set } from '@/utility/idb-proxy.js';
import { get, set, delMany } from '@/utility/idb-proxy.js';
import { store } from '@/store.js';
import { deepClone } from '@/utility/clone.js';
import { deepMerge } from '@/utility/merge.js';
@ -222,6 +222,18 @@ export class Pizzax<T extends StateDef> {
return this.def[key].default;
}
/** 現在のアカウントに紐づくデータをデバイスから削除します */
public async clearAccountDataFromDevice(id = $i?.id) {
if (id == null) return;
const deviceAccountStateKey = `pizzax::${this.key}::${id}` satisfies typeof this.deviceAccountStateKeyName;
const registryCacheKey = `pizzax::${this.key}::cache::${id}` satisfies typeof this.registryCacheKeyName;
await this.addIdbSetJob(async () => {
await delMany([deviceAccountStateKey, registryCacheKey]);
});
}
/**
* computed refを作ります
* vue上で設定コントロールのmodelとして使う用

View File

@ -8,11 +8,23 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_gaps">
<div class="_buttons">
<MkButton primary @click="addAccount"><i class="ti ti-plus"></i> {{ i18n.ts.addAccount }}</MkButton>
<!--<MkButton @click="refreshAllAccounts"><i class="ti ti-refresh"></i></MkButton>-->
<MkButton @click="refreshAllAccounts"><i class="ti ti-refresh"></i> {{ i18n.ts.reloadAccountsList }}</MkButton>
<MkButton danger @click="logoutFromAll"><i class="ti ti-power"></i> {{ i18n.ts.logoutFromAll }}</MkButton>
</div>
<template v-for="x in accounts" :key="x.host + x.id">
<MkUserCardMini v-if="x.user" :user="x.user" :class="$style.user" @click.prevent="showMenu(x.host, x.id, $event)"/>
<MkUserCardMini v-if="x.user" :user="x.user" :class="$style.user" @click.prevent="showMenu(x, $event)">
<template #nameSuffix>
<span v-if="x.id === $i?.id" :class="$style.currentAccountTag">{{ i18n.ts.loggingIn }}</span>
</template>
</MkUserCardMini>
<button v-else v-panel class="_button" :class="$style.unknownUser" @click="showMenu(x, $event)">
<div :class="$style.unknownUserAvatarMock"><i class="ti ti-user-question"></i></div>
<div>
<div :class="$style.unknownUserTitle">{{ i18n.ts.unknown }}<span v-if="x.id === $i?.id" :class="$style.currentAccountTag">{{ i18n.ts.loggingIn }}</span></div>
<div :class="$style.unknownUserSub">ID: <span class="_monospace">{{ x.id }}</span></div>
</div>
</button>
</template>
</div>
</SearchMarker>
@ -20,36 +32,73 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { ref, computed } from 'vue';
import * as Misskey from 'misskey-js';
import { host as local } from '@@/js/config.js';
import type { MenuItem } from '@/types/menu.js';
import MkButton from '@/components/MkButton.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { $i } from '@/i.js';
import { switchAccount, removeAccount, login, getAccountWithSigninDialog, getAccountWithSignupDialog, getAccounts } from '@/accounts.js';
import { switchAccount, removeAccount, removeAccountAssociatedData, getAccountWithSigninDialog, getAccountWithSignupDialog, getAccounts, refreshAccounts } from '@/accounts.js';
import type { AccountData } from '@/accounts.js';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import MkUserCardMini from '@/components/MkUserCardMini.vue';
import { prefer } from '@/preferences.js';
import { signout } from '@/signout.js';
const accounts = await getAccounts();
const accounts = ref<AccountData[]>([]);
getAccounts().then((res) => {
accounts.value = res;
});
function refreshAllAccounts() {
// TODO
os.promiseDialog((async () => {
await refreshAccounts();
accounts.value = await getAccounts();
})());
}
function showMenu(host: string, id: string, ev: PointerEvent) {
let menu: MenuItem[];
function showMenu(a: AccountData, ev: PointerEvent) {
const menu: MenuItem[] = [];
menu = [{
text: i18n.ts.switch,
icon: 'ti ti-switch-horizontal',
action: () => switchAccount(host, id),
}, {
text: i18n.ts.remove,
icon: 'ti ti-trash',
action: () => removeAccount(host, id),
}];
if ($i != null && $i.id === a.id && ($i.host ?? local) === a.host) {
menu.push({
text: i18n.ts.logout,
icon: 'ti ti-power',
danger: true,
action: async () => {
const { canceled } = await os.confirm({
type: 'warning',
title: i18n.ts.logoutConfirm,
text: i18n.ts.logoutWillClearClientData,
});
if (canceled) return;
signout();
},
});
} else {
menu.push({
text: i18n.ts.switch,
icon: 'ti ti-switch-horizontal',
action: () => switchAccount(a.host, a.id),
}, {
text: i18n.ts.logout,
icon: 'ti ti-power',
danger: true,
action: async () => {
const { canceled } = await os.confirm({
type: 'warning',
title: i18n.tsx.logoutFromOtherAccountConfirm({ username: `<plain>@${a.username}</plain>` }),
text: i18n.ts.logoutWillClearClientData,
});
if (canceled) return;
await os.promiseDialog((async () => {
await removeAccount(a.host, a.id);
await removeAccountAssociatedData(a.host, a.id);
accounts.value = await getAccounts();
})());
},
});
}
os.popupMenu(menu, ev.currentTarget ?? ev.target);
}
@ -64,20 +113,30 @@ function addAccount(ev: PointerEvent) {
}], ev.currentTarget ?? ev.target);
}
function addExistingAccount() {
getAccountWithSigninDialog().then((res) => {
if (res != null) {
os.success();
}
});
async function addExistingAccount() {
const res = await getAccountWithSigninDialog();
if (res != null) {
os.success();
}
accounts.value = await getAccounts();
}
function createAccount() {
getAccountWithSignupDialog().then((res) => {
if (res != null) {
login(res.token);
}
async function createAccount() {
const res = await getAccountWithSignupDialog();
if (res != null) {
os.success();
}
accounts.value = await getAccounts();
}
async function logoutFromAll() {
const { canceled } = await os.confirm({
type: 'warning',
title: i18n.ts.logoutConfirm,
text: i18n.ts.logoutWillClearClientData,
});
if (canceled) return;
signout(true);
}
const headerActions = computed(() => []);
@ -95,6 +154,16 @@ definePage(() => ({
cursor: pointer;
}
.currentAccountTag {
display: inline-block;
margin-left: 8px;
padding: 0 6px;
font-size: 0.8em;
background: var(--MI_THEME-accentedBg);
color: var(--MI_THEME-accent);
border-radius: calc(var(--MI-radius) / 2);
}
.unknownUser {
display: flex;
align-items: center;

View File

@ -94,7 +94,9 @@ export type StorageProvider = {
type PreferencesDefinitionRecord<Default, T = Default extends (...args: any) => infer R ? R : Default> = {
default: Default;
/** アカウントごとに異なる設定値をもたせるかどうか */
accountDependent?: boolean;
/** サーバーごとに異なる設定値をもたせるかどうか(他のサーバーを同一クライアントから操作できるようになった際に使用) */
serverDependent?: boolean;
mergeStrategy?: (a: T, b: T) => T;
};
@ -451,6 +453,33 @@ export class PreferencesManager extends EventEmitter<PreferencesManagerEvents> {
this.save();
}
/** 現在の操作アカウントに紐づく設定値をデバイスから削除します(ログアウト時などに使用) */
public clearAccountSettingsFromDevice(targetHost = host, id = this.currentAccount?.id) {
if (id == null) return;
let changed = false;
for (const _key in PREF_DEF) {
const key = _key as keyof PREF;
const records = this.profile.preferences[key];
const index = records.findIndex((record: PrefRecord<typeof key>) => {
const scope = parseScope(record[0]);
return scope.server === targetHost && scope.account === id;
});
if (index === -1) continue;
records.splice(index, 1);
changed = true;
this.rewriteRawState(key, this.getMatchedRecordOf(key)[1]);
}
if (changed) {
this.save();
}
}
public isSyncEnabled<K extends keyof PREF>(key: K): boolean {
return this.getMatchedRecordOf(key)[2].sync ?? false;
}

View File

@ -5,20 +5,18 @@
import { apiUrl } from '@@/js/config.js';
import { cloudBackup } from '@/preferences/utility.js';
import { removeAccount, login } from '@/accounts.js';
import { host } from '@@/js/config.js';
import { store } from '@/store.js';
import { prefer } from '@/preferences.js';
import { waiting } from '@/os.js';
import { unisonReload } from '@/utility/unison-reload.js';
import { clear } from '@/utility/idb-proxy.js';
import { $i } from '@/i.js';
export async function signout() {
if (!$i) return;
waiting();
if (store.s.enablePreferencesAutoCloudBackup) {
await cloudBackup();
}
/** クライアントに保存しているすべてのデータを削除します。 */
async function removeAllData() {
if ($i == null) return;
localStorage.clear();
@ -74,6 +72,54 @@ export async function signout() {
// nothing
}
//#endregion
}
/** 現在のアカウントに関連するデータを削除します。 */
async function removeCurrentAccountData() {
if ($i == null) return;
// 設定・状態を削除
prefer.clearAccountSettingsFromDevice();
await store.clearAccountDataFromDevice();
}
export async function signout(all = false) {
if (!$i) return;
const currentAccountId = $i.id;
waiting();
if (store.s.enablePreferencesAutoCloudBackup) {
await cloudBackup();
}
if (prefer.s.accounts.length <= 1 || all) {
// 最後のアカウントを削除する場合・全てのアカウントからログアウトする場合は全データ削除
await removeAllData();
} else {
// 複数アカウントある場合は現在のアカウントのデータのみ削除
await removeCurrentAccountData();
// 現在のアカウント情報を削除
await removeAccount(host, $i.id);
// アカウント切り替え
const nextAccountToken = Object.entries(store.s.accountTokens).find(([key, _]) => {
const [accountHost, userId] = key.split('/');
return accountHost === host && userId !== currentAccountId;
})?.[1];
if (nextAccountToken != null) {
// ログインの際の遷移の挙動はlogin関数内で行うのでここではunisonReloadを呼ばず終了
await login(nextAccountToken, undefined, false);
return;
} else {
// 現時点では外部ホストのアカウントをログインさせることはできないので、
// 通常の全アカウントからのログアウトと同様に扱う(全データ削除)
await removeAllData();
}
}
unisonReload('/');
}

View File

@ -99,11 +99,11 @@ export const store = markRaw(new Pizzax('base', {
},
accountTokens: {
where: 'device',
default: {} as Record<string, string>, // host/userId, token
default: {} as Record<`${string}/${string}`, string>, // host/userId, token
},
accountInfos: {
where: 'device',
default: {} as Record<string, Misskey.entities.MeDetailed>, // host/userId, user
default: {} as Record<`${string}/${string}`, Misskey.entities.MeDetailed>, // host/userId, user
},
enablePreferencesAutoCloudBackup: {

View File

@ -9,6 +9,7 @@ import {
get as iget,
set as iset,
del as idel,
delMany as idelMany,
clear as iclear,
} from 'idb-keyval';
import { miLocalStorage } from '@/local-storage.js';
@ -53,6 +54,13 @@ export async function del(key: string) {
return miLocalStorage.removeItem(`${PREFIX}${key}`);
}
export async function delMany(keys: string[]) {
if (idbAvailable) return idelMany(keys);
for (const key of keys) {
miLocalStorage.removeItem(`${PREFIX}${key}`);
}
}
export async function clear() {
if (idbAvailable) return iclear();
}

View File

@ -148,6 +148,10 @@ export interface Locale extends ILocale {
*
*/
"logout": string;
/**
*
*/
"logoutFromAll": string;
/**
*
*/
@ -3980,6 +3984,10 @@ export interface Locale extends ILocale {
*
*/
"logoutWillClearClientData": string;
/**
* {username}
*/
"logoutFromOtherAccountConfirm": ParameterizedString<"username">;
/**
*
*/

View File

@ -32,8 +32,8 @@ importers:
specifier: 8.5.6
version: 8.5.6
tar:
specifier: 7.5.6
version: 7.5.6
specifier: 7.5.7
version: 7.5.7
terser:
specifier: 5.46.0
version: 5.46.0
@ -75,8 +75,8 @@ importers:
specifier: 2.0.0
version: 2.0.0
pnpm:
specifier: 10.28.0
version: 10.28.0
specifier: 10.28.2
version: 10.28.2
start-server-and-test:
specifier: 2.1.3
version: 2.1.3
@ -8927,8 +8927,8 @@ packages:
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
engines: {node: '>=10.13.0'}
pnpm@10.28.0:
resolution: {integrity: sha512-Bd9x0UIfITmeBT/eVnzqNNRG+gLHZXFEG/wceVbpjjYwiJgtlARl/TRIDU2QoGaLwSNi+KqIAApk6D0LDke+SA==}
pnpm@10.28.2:
resolution: {integrity: sha512-QYcvA3rSL3NI47Heu69+hnz9RI8nJtnPdMCPGVB8MdLI56EVJbmD/rwt9kC1Q43uYCPrsfhO1DzC1lTSvDJiZA==}
engines: {node: '>=18.12'}
hasBin: true
@ -10178,9 +10178,10 @@ packages:
engines: {node: '>=10'}
deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me
tar@7.5.6:
resolution: {integrity: sha512-xqUeu2JAIJpXyvskvU3uvQW8PAmHrtXp2KDuMJwQqW8Sqq0CaZBAQ+dKS3RBXVhU4wC5NjAdKrmh84241gO9cA==}
tar@7.5.7:
resolution: {integrity: sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==}
engines: {node: '>=18'}
deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me
taskkill@5.0.0:
resolution: {integrity: sha512-+HRtZ40Vc+6YfCDWCeAsixwxJgMbPY4HHuTgzPYH3JXvqHWUlsCfy+ylXlAKhFNcuLp4xVeWeFBUhDk+7KYUvQ==}
@ -20125,7 +20126,7 @@ snapshots:
nopt: 9.0.0
proc-log: 6.1.0
semver: 7.7.3
tar: 7.5.6
tar: 7.5.7
tinyglobby: 0.2.15
which: 6.0.0
transitivePeerDependencies:
@ -20559,7 +20560,7 @@ snapshots:
pngjs@5.0.0: {}
pnpm@10.28.0: {}
pnpm@10.28.2: {}
polished@4.3.1:
dependencies:
@ -21991,7 +21992,7 @@ snapshots:
yallist: 4.0.0
optional: true
tar@7.5.6:
tar@7.5.7:
dependencies:
'@isaacs/fs-minipass': 4.0.1
chownr: 3.0.0

View File

@ -38,3 +38,5 @@ minimumReleaseAgeExclude:
- '@fastify/express' # 脆弱性対応。そのうち消すこと
- 'lodash' # 脆弱性対応。そのうち消すこと
- 'tar' # 脆弱性対応。そのうち消すこと
# Renovate security update: pnpm@10.28.2
- pnpm@10.28.2