1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-06-17 18:44:47 +02:00

Compare commits

...

8 Commits

Author SHA1 Message Date
github-actions[bot]
f46450d857 Bump version to 2026.6.0-alpha.2 2026-06-14 08:26:32 +00:00
Caleb Gates
b125ce1eb2 fix(backend): route fastify listen/ready/close errors through logger instead of unhandled rejection (#17401)
* fix(backend): route fastify listen/ready/close errors through logger instead of unhandled rejection

* Update CHANGELOG.md

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-06-14 16:54:29 +09:00
renovate[bot]
dc96c35296 fix(deps): update dependency esbuild to v0.28.1 [security] [ci skip] (#17566)
* fix(deps): update dependency esbuild to v0.28.1 [security]

* update

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2026-06-13 18:11:56 +09:00
かっこかり
8468a25488 Update CHANGELOG.md 2026-06-13 17:49:44 +09:00
github-actions[bot]
6c7375924c Bump version to 2026.6.0-alpha.1 2026-06-12 11:52:52 +00:00
Copilot
ec6b1cc6a8 Enhance ActivityPub image attachments with width/height metadata (#17563)
* Initial plan

* enhance(backend): include image dimensions in AP attachments

* fix(backend): guard AP attachment dimension properties

* fix(changelog): move AP dimensions note to 2026.6.0

* Update CHANGELOG.md

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-06-12 20:47:12 +09:00
おさむのひと
e093b32aa9 fix(backend): MemoryKVCacheのキャッシュGC処理においてキャッシュが期限切れにならないことがある問題を修正 (#17512)
* fix(backend): MemoryKVCacheのキャッシュGC処理においてキャッシュが期限切れにならないことがある問題を修正

* おためし

* fix

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-06-11 20:03:38 +09:00
かっこかり
0b4764c68b enhance: estree-walkerをoxc-walkerに変更 (#17556)
* enhance: estree-walkerをoxc-walkerに変更

* fix lint [ci skip]
2026-06-09 12:10:15 +09:00
21 changed files with 545 additions and 233 deletions

View File

@@ -3,8 +3,8 @@
### General
- Feat: ジョブキュー管理画面からキューの一時停止/再開ができるように
- Feat: アンテナのタイムラインから個別のノートを削除できるように
- Fix: コンパネからrootユーザーのパスワードをリセットしようとした際にエラーが通知されない問題を修正
- Feat: ノート検索で投稿日時の期間を条件に加えられるように(#16035)
- Fix: コンパネからrootユーザーのパスワードをリセットしようとした際にエラーが通知されない問題を修正
### Client
- Enhance: ユーザーページのファイルタブでスクロール位置が保持されるように
@@ -21,10 +21,14 @@
### Server
- Enhance: リモートノートクリーニングジョブのスキップ処理のパフォーマンス改善
- Fix: PerUserDriveChart がシステム所有ファイル (userId が null) の更新で `"group"` の非NULL制約違反によりクラッシュする問題を修正 (#17498)
- Enhance: リモートノートクリーニングジョブの削除対象検索処理のパフォーマンス改善
- Enhance: ActivityPub の画像添付に width/height を含めるように
- Fix: backend バンドルで `@tensorflow/tfjs-node` を external に含めず、起動時に `@mapbox/node-pre-gyp``find()` が backend の package.json を誤検出して `is not node-pre-gyp ready` エラーを永続的に吐く問題を修正
- Fix: MemoryKVCacheのキャッシュGC処理において、更新されたキャッシュが期限切れにならないことがある問題を修正
- Fix: PerUserDriveChart がシステム所有ファイル (userId が null) の更新で `"group"` の非NULL制約違反によりクラッシュする問題を修正 (#17498)
- Fix: センシティブメディア自動検出周りの依存関係・ファイルの解決に失敗する問題を修正
- Fix: フォロワー限定投稿を指名投稿で引用した際に、引用した投稿の公開範囲が意図せず変更される問題を修正
- Fix: Startup and shutdown failures (port-in-use, socket permission denied, plugin timeouts, leaked WebSocket connections) are now reported through the misskey logger instead of an UnhandledPromiseRejectionWarning stack trace
## 2026.5.4

View File

@@ -1,6 +1,6 @@
{
"name": "misskey",
"version": "2026.6.0-alpha.0",
"version": "2026.6.0-alpha.2",
"codename": "nasubi",
"repository": {
"type": "git",
@@ -54,7 +54,7 @@
},
"dependencies": {
"cssnano": "8.0.1",
"esbuild": "0.28.0",
"esbuild": "0.28.1",
"execa": "9.6.1",
"ignore-walk": "8.0.0",
"js-yaml": "4.1.1",

View File

@@ -172,6 +172,8 @@ export class ApRendererService {
mediaType: file.webpublicType ?? file.type,
url: this.driveFileEntityService.getPublicUrl(file),
name: file.comment,
width: file.properties?.width,
height: file.properties?.height,
sensitive: file.isSensitive,
};
}

View File

@@ -34,6 +34,8 @@ export interface IObject {
href?: string;
tag?: IObject | IObject[];
sensitive?: boolean;
width?: number;
height?: number;
}
/**

View File

@@ -299,12 +299,8 @@ export class MemoryKVCache<T> {
const now = Date.now();
for (const [key, { date }] of this.cache.entries()) {
// The map is ordered from oldest to youngest.
// We can stop once we find an entry that's still active, because all following entries must *also* be active.
const age = now - date;
if (age < this.lifetime) break;
this.cache.delete(key);
if (age >= this.lifetime) this.cache.delete(key);
}
}

View File

@@ -242,16 +242,16 @@ export class ServerService implements OnApplicationShutdown {
this.streamingApiServerService.attach(fastify.server);
fastify.server.on('error', err => {
switch ((err as any).code) {
const handleListenError = (err: unknown): void => {
switch ((err as NodeJS.ErrnoException).code) {
case 'EACCES':
this.logger.error(`You do not have permission to listen on port ${this.config.port}.`);
this.logger.error(`You do not have permission to listen on ${this.config.socket ?? `port ${this.config.port}`}.`);
break;
case 'EADDRINUSE':
this.logger.error(`Port ${this.config.port} is already in use by another process.`);
this.logger.error(`${this.config.socket ?? `Port ${this.config.port}`} is already in use by another process.`);
break;
default:
this.logger.error(err);
this.logger.error(err as Error);
break;
}
@@ -261,28 +261,39 @@ export class ServerService implements OnApplicationShutdown {
// disableClustering
process.exit(1);
}
});
};
if (this.config.socket) {
if (fs.existsSync(this.config.socket)) {
fs.unlinkSync(this.config.socket);
}
fastify.listen({ path: this.config.socket }, (err, address) => {
if (this.config.chmodSocket) {
fs.chmodSync(this.config.socket!, this.config.chmodSocket);
try {
if (this.config.socket) {
if (fs.existsSync(this.config.socket)) {
fs.unlinkSync(this.config.socket);
}
});
} else {
fastify.listen({ port: this.config.port, host: '0.0.0.0' });
await fastify.listen({ path: this.config.socket });
if (this.config.chmodSocket) {
fs.chmodSync(this.config.socket, this.config.chmodSocket);
}
} else {
await fastify.listen({ port: this.config.port, host: '0.0.0.0' });
}
await fastify.ready();
} catch (err) {
handleListenError(err);
return;
}
await fastify.ready();
}
@bindThis
public async dispose(): Promise<void> {
await this.streamingApiServerService.detach();
await this.#fastify.close();
// fastify@5 close() waits for upgraded WebSocket connections to drain.
// streamingApiServerService.attach() adds raw ws.Server upgrades that
// fastify does not track in its connection registry, so close() can hang
// forever during OnApplicationShutdown. Cap at 5s so PM2/systemd/k8s
// shutdown timeouts aren't held hostage.
await Promise.race([
this.#fastify.close(),
new Promise<void>(resolve => setTimeout(resolve, 5_000)),
]).catch(err => this.logger.error('fastify.close() failed', err as Error));
}
/**

View File

@@ -15,6 +15,7 @@ import { Test } from '@nestjs/testing';
import { MockResolver } from '../misc/mock-resolver.js';
import type { IActor, IApDocument, ICollection, IObject, IPost } from '@/core/activitypub/type.js';
import type { MiRemoteUser } from '@/models/User.js';
import type { MiDriveFile } from '@/models/DriveFile.js';
import { ApImageService } from '@/core/activitypub/models/ApImageService.js';
import { ApNoteService } from '@/core/activitypub/models/ApNoteService.js';
import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js';
@@ -399,6 +400,28 @@ describe('ActivityPub', () => {
});
describe('Images', () => {
test('Render image document with dimensions', () => {
const rendered = rendererService.renderDocument({
id: genAidx(Date.now()),
type: 'image/png',
webpublicType: null,
url: 'https://example.test/files/image.png',
webpublicUrl: null,
comment: null,
isSensitive: false,
properties: { width: 3600, height: 1890 },
uri: null,
userHost: null,
isLink: false,
webpublicAccessKey: null,
} as MiDriveFile);
assert.strictEqual(rendered.type, 'Document');
assert.strictEqual(rendered.mediaType, 'image/png');
assert.strictEqual(rendered.width, 3600);
assert.strictEqual(rendered.height, 1890);
});
test('Create images', async () => {
const imageObject: IApDocument = {
type: 'Document',

View File

@@ -0,0 +1,234 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
import { MemoryKVCache, MemorySingleCache } from '@/misc/cache.js';
describe('misc:MemoryKVCache', () => {
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
test('set and get returns the value within lifetime', () => {
const cache = new MemoryKVCache<string>(1000);
cache.set('key', 'value');
expect(cache.get('key')).toBe('value');
cache.dispose();
});
test('get returns undefined after lifetime expires', () => {
const cache = new MemoryKVCache<string>(1000);
cache.set('key', 'value');
vi.advanceTimersByTime(1001);
expect(cache.get('key')).toBeUndefined();
cache.dispose();
});
test('delete removes the entry', () => {
const cache = new MemoryKVCache<string>(1000);
cache.set('key', 'value');
cache.delete('key');
expect(cache.get('key')).toBeUndefined();
cache.dispose();
});
describe('gc()', () => {
test('removes expired entries', () => {
const cache = new MemoryKVCache<string>(1000);
cache.set('a', '1');
cache.set('b', '2');
vi.advanceTimersByTime(1001);
cache.gc();
expect(cache.get('a')).toBeUndefined();
expect(cache.get('b')).toBeUndefined();
cache.dispose();
});
test('retains entries that have not yet expired', () => {
const cache = new MemoryKVCache<string>(2000);
cache.set('a', '1');
vi.advanceTimersByTime(1001);
cache.gc();
expect(cache.get('a')).toBe('1');
cache.dispose();
});
test('removes only expired entries when mixed with live entries', () => {
const cache = new MemoryKVCache<string>(2000);
cache.set('old', 'oldValue');
vi.advanceTimersByTime(2001);
cache.set('new', 'newValue');
cache.gc();
expect(cache.get('old')).toBeUndefined();
expect(cache.get('new')).toBe('newValue');
cache.dispose();
});
// Regression test for https://github.com/misskey-dev/misskey/issues/15500
// Updated keys keep their original insertion position in Map. gc() must not
// assume that entries are ordered from oldest to youngest, otherwise it can
// stop early at an updated key and leave later, truly-expired keys alive.
// The key observable symptom is that gc() fails to *remove* the expired entry
// from the Map — get() has its own expiry check so it returns undefined either
// way, but the stale entry keeps consuming memory.
test('correctly expires old entries after a key is updated (issue #15500)', () => {
const lifetime = 1000;
const cache = new MemoryKVCache<string>(lifetime);
// Insert 'a' and 'b' at t=0
cache.set('a', 'v1');
cache.set('b', 'v1');
// Advance time and update 'a'. It stays at position 0 in the Map, so a
// gc() implementation that stops at the first fresh entry would leave 'b'
// in the Map even though get() would hide it as expired.
vi.advanceTimersByTime(500);
cache.set('a', 'v2'); // refresh 'a'; 'b' is still at t=0
// 'b' is now expired, 'a' has 400ms left
vi.advanceTimersByTime(600); // total 1100ms
cache.gc();
// Verify the entry is actually removed from the Map, not just hidden by get().
// get() always checks expiry itself, so it returns undefined even without gc() —
// the real bug is memory not being freed.
const entries = [...cache.entries];
expect(entries.find(([k]) => k === 'b')).toBeUndefined(); // 'b' must be gone from Map
expect(entries.find(([k]) => k === 'a')?.[1].value).toBe('v2'); // 'a' still in Map
cache.dispose();
});
test('gc does not break when cache is empty', () => {
const cache = new MemoryKVCache<string>(1000);
expect(() => cache.gc()).not.toThrow();
cache.dispose();
});
});
test('set does not cause active entries iteration to revisit the same key', () => {
const cache = new MemoryKVCache<{ id: string }>(1000);
cache.set('key', { id: 'user-1' });
let iterations = 0;
for (const [key, { value }] of cache.entries) {
iterations++;
if (value.id === 'user-1') {
cache.set(key, value);
}
expect(iterations).toBeLessThan(3);
}
expect(iterations).toBe(1);
cache.dispose();
});
describe('fetch()', () => {
test('calls fetcher on cache miss', async () => {
const cache = new MemoryKVCache<string>(1000);
const fetcher = vi.fn().mockResolvedValue('fetched');
const result = await cache.fetch('key', fetcher);
expect(fetcher).toHaveBeenCalledOnce();
expect(result).toBe('fetched');
cache.dispose();
});
test('does not call fetcher on cache hit', async () => {
const cache = new MemoryKVCache<string>(1000);
cache.set('key', 'cached');
const fetcher = vi.fn().mockResolvedValue('fetched');
const result = await cache.fetch('key', fetcher);
expect(fetcher).not.toHaveBeenCalled();
expect(result).toBe('cached');
cache.dispose();
});
test('respects validator and bypasses cache when validator returns false', async () => {
const cache = new MemoryKVCache<string>(1000);
cache.set('key', 'cached');
const fetcher = vi.fn().mockResolvedValue('fetched');
const result = await cache.fetch('key', fetcher, () => false);
expect(fetcher).toHaveBeenCalledOnce();
expect(result).toBe('fetched');
cache.dispose();
});
});
describe('fetchMaybe()', () => {
test('does not cache undefined returned by fetcher', async () => {
const cache = new MemoryKVCache<string>(1000);
const fetcher = vi.fn().mockResolvedValue(undefined);
const result = await cache.fetchMaybe('key', fetcher);
expect(result).toBeUndefined();
// A second call should invoke the fetcher again because undefined was not cached
await cache.fetchMaybe('key', fetcher);
expect(fetcher).toHaveBeenCalledTimes(2);
cache.dispose();
});
});
});
describe('misc:MemorySingleCache', () => {
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
test('set and get returns the value within lifetime', () => {
const cache = new MemorySingleCache<string>(1000);
cache.set('value');
expect(cache.get()).toBe('value');
});
test('get returns undefined after lifetime expires', () => {
const cache = new MemorySingleCache<string>(1000);
cache.set('value');
vi.advanceTimersByTime(1001);
expect(cache.get()).toBeUndefined();
});
test('delete removes the cached value', () => {
const cache = new MemorySingleCache<string>(1000);
cache.set('value');
cache.delete();
expect(cache.get()).toBeUndefined();
});
describe('fetch()', () => {
test('calls fetcher on cache miss', async () => {
const cache = new MemorySingleCache<string>(1000);
const fetcher = vi.fn().mockResolvedValue('fetched');
const result = await cache.fetch(fetcher);
expect(fetcher).toHaveBeenCalledOnce();
expect(result).toBe('fetched');
});
test('does not call fetcher on cache hit', async () => {
const cache = new MemorySingleCache<string>(1000);
cache.set('cached');
const fetcher = vi.fn().mockResolvedValue('fetched');
const result = await cache.fetch(fetcher);
expect(fetcher).not.toHaveBeenCalled();
expect(result).toBe('cached');
});
test('respects validator and bypasses cache when validator returns false', async () => {
const cache = new MemorySingleCache<string>(1000);
cache.set('cached');
const fetcher = vi.fn().mockResolvedValue('fetched');
const result = await cache.fetch(fetcher, () => false);
expect(fetcher).toHaveBeenCalledOnce();
expect(result).toBe('fetched');
});
});
});

View File

@@ -4,23 +4,12 @@
*/
import { parseAst } from 'rolldown/parseAst';
import * as estreeWalker from 'estree-walker';
import { walk } from 'oxc-walker';
import { assertNever } from '../utils.js';
import type { ESTree } from 'rolldown/utils';
import type { LocaleInliner, TextModification } from '../locale-inliner.js';
import type { Logger } from '../logger.js';
// WalkerContext is not exported from estree-walker, so we define it here
interface WalkerContext {
skip: () => void;
}
const walk = estreeWalker.walk as {
(node: ESTree.Node, callback: {
enter?: (this: WalkerContext, node: ESTree.Node, parent: ESTree.Node | null, property: string | number | symbol | null | undefined) => void;
}): void;
};
export function collectModifications(sourceCode: string, fileName: string, fileLogger: Logger, inliner: LocaleInliner): TextModification[] {
if (sourceCode === '') return [];
let programNode: ESTree.Program;
@@ -42,7 +31,7 @@ export function collectModifications(sourceCode: string, fileName: string, fileL
// 2) replace all `localStorage.getItem("lang")` with `localeName` variable
// 3) replace all `await window.fetch(`/assets/locales/${d}.${x}.json`).then(u=>u.json())` with `localeJson` variable
walk(programNode, {
enter(this: WalkerContext, node: ESTree.Node) {
enter(this, node) {
if (node.type === 'Literal' && typeof node.value === 'string' && node.raw) {
if (node.raw.substring(1).startsWith(inliner.scriptsDir)) {
// we find `scripts/\w+\.js` literal and replace 'scripts' part with locale code
@@ -130,13 +119,15 @@ export function collectModifications(sourceCode: string, fileName: string, fileL
const toSkip = new Set();
toSkip.add(i18nImport);
walk(programNode, {
enter(this: WalkerContext, node, parent, property) {
enter(this, node, parent, ctx) {
if (toSkip.has(node)) {
// This is the import specifier, skip processing it
this.skip();
return;
}
const property = ctx.key;
// We don't care original name part of the import declaration
if (node.type === 'ImportDeclaration') this.skip();

View File

@@ -17,9 +17,9 @@
"rollup": "4.60.4"
},
"dependencies": {
"estree-walker": "3.0.3",
"i18n": "workspace:*",
"magic-string": "0.30.21",
"oxc-walker": "1.0.0",
"rolldown": "1.0.3",
"vite": "8.0.14"
}

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import * as estreeWalker from 'estree-walker';
import { walk } from 'oxc-walker';
import { RolldownMagicString } from 'rolldown';
import { assertType } from './utils.js';
import type { ESTree } from 'rolldown/utils';
@@ -27,8 +27,7 @@ export function pluginRemoveUnrefI18n(
if (!code.includes('unref(i18n)')) return null;
const ast = this.parse(code);
const magicString = meta.magicString ?? new RolldownMagicString(code);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(estreeWalker.walk as any)(ast, {
walk(ast, {
enter(node: ESTree.Node) {
if (node.type === 'CallExpression' && node.callee.type === 'Identifier' && node.callee.name === 'unref'
&& node.arguments.length === 1) {

View File

@@ -14,7 +14,6 @@
"@rollup/pluginutils": "5.4.0",
"@vitejs/plugin-vue": "6.0.7",
"buraha": "0.0.1",
"estree-walker": "3.0.3",
"frontend-shared": "workspace:*",
"i18n": "workspace:*",
"icons-subsetter": "workspace:*",

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import * as estreeWalker from 'estree-walker';
import { walk } from 'oxc-walker';
import type { Plugin } from 'vite';
import type { ESTree } from 'rolldown/utils';
import { RolldownMagicString } from 'rolldown';
@@ -185,7 +185,7 @@ function isClassProperty(node: ESTree.Node | null): node is Extract<ESTree.Node,
}
export function unwindCssModuleClassName(ast: ESTree.Node, magicString: RolldownMagicString): void {
(estreeWalker.walk as any)(ast, {
walk(ast, {
enter(node: ESTree.Node, parent: ESTree.Node | null): void {
//#region
if (parent?.type !== 'Program') return;
@@ -267,7 +267,7 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
*/
//#endregion
//#region
(estreeWalker.walk as any)(render.body, {
walk(render.body, {
enter(childNode: ESTree.Node) {
if (!isCssModuleReference(childNode, ctx.name, key)) return;
const actualKey = getMemberPropertyName(childNode.property, childNode.computed);
@@ -278,6 +278,9 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
this.replace({
type: 'Literal',
value: actualValue,
raw: JSON.stringify(actualValue),
start: childNode.start,
end: childNode.end,
});
},
});
@@ -314,7 +317,7 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
*/
//#endregion
//#region
(estreeWalker.walk as any)(render.body, {
walk(render.body, {
enter(childNode: ESTree.Node) {
if (!isCssModuleReference(childNode, ctx.name, key)) return;
const actualKey = getMemberPropertyName(childNode.property, childNode.computed);
@@ -357,7 +360,7 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
*/
//#endregion
//#region
(estreeWalker.walk as any)(render.body, {
walk(render.body, {
enter(childNode: ESTree.Node, childParent: ESTree.Node | null) {
if (childNode.type !== 'CallExpression') return;
if (childNode.arguments.length !== 1) return;
@@ -404,7 +407,7 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
}
const hasRemainingCssModuleReference = Array.from(moduleForest.keys()).some((key) => {
let found = false;
(estreeWalker.walk as any)(render.body, {
walk(render.body, {
enter(childNode: ESTree.Node) {
if (!isCssModuleAccess(childNode, ctx.name, key)) return;
found = true;
@@ -417,7 +420,7 @@ export function unwindCssModuleClassName(ast: ESTree.Node, magicString: Rolldown
//#region
if (node.declarations[0].init.arguments[1].elements.length === 1) {
if (componentNode.type === 'Identifier') {
(estreeWalker.walk as any)(ast, {
walk(ast, {
enter(childNode: ESTree.Node) {
if (childNode.type !== 'Identifier') return;
if (childNode.name !== componentNode.name) return;

View File

@@ -116,7 +116,6 @@
"cypress": "15.16.0",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-vue": "10.9.1",
"estree-walker": "3.0.3",
"happy-dom": "20.9.0",
"intersection-observer": "0.12.2",
"lightningcss": "1.32.0",
@@ -125,6 +124,7 @@
"msw": "2.14.6",
"msw-storybook-addon": "2.0.7",
"nodemon": "3.1.14",
"oxc-walker": "1.0.0",
"prettier": "3.8.3",
"react": "19.2.6",
"react-dom": "19.2.6",

View File

@@ -33,7 +33,7 @@
"@typescript-eslint/eslint-plugin": "8.60.0",
"@typescript-eslint/parser": "8.60.0",
"chokidar": "5.0.0",
"esbuild": "0.28.0",
"esbuild": "0.28.1",
"execa": "9.6.1",
"nodemon": "3.1.14",
"tsx": "4.22.3"

View File

@@ -29,7 +29,7 @@
"@types/seedrandom": "3.0.8",
"@typescript-eslint/eslint-plugin": "8.60.0",
"@typescript-eslint/parser": "8.60.0",
"esbuild": "0.28.0",
"esbuild": "0.28.1",
"execa": "9.6.1",
"nodemon": "3.1.14"
},

View File

@@ -1,7 +1,7 @@
{
"type": "module",
"name": "misskey-js",
"version": "2026.6.0-alpha.0",
"version": "2026.6.0-alpha.2",
"description": "Misskey SDK for JavaScript",
"license": "MIT",
"main": "./built/index.js",
@@ -42,7 +42,7 @@
"@typescript-eslint/eslint-plugin": "8.60.0",
"@typescript-eslint/parser": "8.60.0",
"@vitest/coverage-v8": "4.1.7",
"esbuild": "0.28.0",
"esbuild": "0.28.1",
"execa": "9.6.1",
"ncp": "2.0.0",
"nodemon": "3.1.14",

View File

@@ -27,7 +27,7 @@
"@types/node": "24.12.4",
"@typescript-eslint/eslint-plugin": "8.60.0",
"@typescript-eslint/parser": "8.60.0",
"esbuild": "0.28.0",
"esbuild": "0.28.1",
"execa": "9.6.1",
"nodemon": "3.1.14"
},

View File

@@ -10,7 +10,7 @@
},
"dependencies": {
"i18n": "workspace:*",
"esbuild": "0.28.0",
"esbuild": "0.28.1",
"idb-keyval": "6.2.4",
"misskey-js": "workspace:*"
},

390
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -54,6 +54,8 @@ minimumReleaseAgeExclude:
- '@typescript/native-preview*'
- pnpm
- '@types/archiver' # そのうち消す
- esbuild # 脆弱性対応。そのうち消す
- '@esbuild/*' # 脆弱性対応。そのうち消す
overrides:
'@aiscript-dev/aiscript-languageserver': '-'
chokidar: 5.0.0