summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/backend/src/misc/json-schema.ts2
-rw-r--r--packages/backend/src/models/json-schema/signin.ts26
-rw-r--r--packages/backend/src/server/api/endpoints/i/signin-history.ts11
-rw-r--r--packages/misskey-js/etc/misskey-js.api.md180
-rw-r--r--packages/misskey-js/src/autogen/endpoint.ts4
-rw-r--r--packages/misskey-js/src/autogen/entities.ts4
-rw-r--r--packages/misskey-js/src/autogen/models.ts5
-rw-r--r--packages/misskey-js/src/autogen/types.ts42
-rw-r--r--packages/misskey-js/src/entities.ts56
-rw-r--r--packages/misskey-js/src/streaming.types.ts140
10 files changed, 414 insertions, 56 deletions
diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts
index 80c1041c62..7e7fc447c3 100644
--- a/packages/backend/src/misc/json-schema.ts
+++ b/packages/backend/src/misc/json-schema.ts
@@ -36,6 +36,7 @@ import { packedGalleryPostSchema } from '@/models/json-schema/gallery-post.js';
import { packedEmojiDetailedSchema, packedEmojiSimpleSchema } from '@/models/json-schema/emoji.js';
import { packedFlashSchema } from '@/models/json-schema/flash.js';
import { packedAnnouncementSchema } from '@/models/json-schema/announcement.js';
+import { packedSigninSchema } from '@/models/json-schema/signin.js';
export const refs = {
UserLite: packedUserLiteSchema,
@@ -71,6 +72,7 @@ export const refs = {
EmojiSimple: packedEmojiSimpleSchema,
EmojiDetailed: packedEmojiDetailedSchema,
Flash: packedFlashSchema,
+ Signin: packedSigninSchema,
};
export type Packed<x extends keyof typeof refs> = SchemaType<typeof refs[x]>;
diff --git a/packages/backend/src/models/json-schema/signin.ts b/packages/backend/src/models/json-schema/signin.ts
new file mode 100644
index 0000000000..d27d2490c5
--- /dev/null
+++ b/packages/backend/src/models/json-schema/signin.ts
@@ -0,0 +1,26 @@
+export const packedSigninSchema = {
+ type: 'object',
+ properties: {
+ id: {
+ type: 'string',
+ optional: false, nullable: false,
+ },
+ createdAt: {
+ type: 'string',
+ optional: false, nullable: false,
+ format: 'date-time',
+ },
+ ip: {
+ type: 'string',
+ optional: false, nullable: false,
+ },
+ headers: {
+ type: 'object',
+ optional: false, nullable: false,
+ },
+ success: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
+ },
+} as const;
diff --git a/packages/backend/src/server/api/endpoints/i/signin-history.ts b/packages/backend/src/server/api/endpoints/i/signin-history.ts
index 139bede7bc..f82e3f9b28 100644
--- a/packages/backend/src/server/api/endpoints/i/signin-history.ts
+++ b/packages/backend/src/server/api/endpoints/i/signin-history.ts
@@ -12,8 +12,17 @@ import { DI } from '@/di-symbols.js';
export const meta = {
requireCredential: true,
-
secure: true,
+
+ res: {
+ type: 'array',
+ optional: false, nullable: false,
+ items: {
+ type: 'object',
+ optional: false, nullable: false,
+ ref: 'Signin',
+ },
+ },
} as const;
export const paramDef = {
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index 4e6e2adc02..e2e3349c08 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -293,6 +293,11 @@ type AdminUpdateUserNoteRequest = operations['admin/update-user-note']['requestB
type Announcement = components['schemas']['Announcement'];
// @public (undocumented)
+type AnnouncementCreated = {
+ announcement: Announcement;
+};
+
+// @public (undocumented)
type AnnouncementsRequest = operations['announcements']['requestBody']['content']['application/json'];
// @public (undocumented)
@@ -488,9 +493,7 @@ export type Channels = {
unreadAntenna: (payload: Antenna) => void;
readAllAnnouncements: () => void;
myTokenRegenerated: () => void;
- reversiNoInvites: () => void;
- reversiInvited: (payload: FIXME) => void;
- signin: (payload: FIXME) => void;
+ signin: (payload: Signin) => void;
registryUpdated: (payload: {
scope?: string[];
key: string;
@@ -498,41 +501,116 @@ export type Channels = {
}) => void;
driveFileCreated: (payload: DriveFile) => void;
readAntenna: (payload: Antenna) => void;
+ receiveFollowRequest: (payload: User) => void;
+ announcementCreated: (payload: AnnouncementCreated) => void;
};
receives: null;
};
homeTimeline: {
- params: null;
+ params: {
+ withRenotes?: boolean;
+ withFiles?: boolean;
+ };
events: {
note: (payload: Note) => void;
};
receives: null;
};
localTimeline: {
- params: null;
+ params: {
+ withRenotes?: boolean;
+ withReplies?: boolean;
+ withFiles?: boolean;
+ };
events: {
note: (payload: Note) => void;
};
receives: null;
};
hybridTimeline: {
- params: null;
+ params: {
+ withRenotes?: boolean;
+ withReplies?: boolean;
+ withFiles?: boolean;
+ };
events: {
note: (payload: Note) => void;
};
receives: null;
};
globalTimeline: {
- params: null;
+ params: {
+ withRenotes?: boolean;
+ withFiles?: boolean;
+ };
+ events: {
+ note: (payload: Note) => void;
+ };
+ receives: null;
+ };
+ userList: {
+ params: {
+ listId: string;
+ withFiles?: boolean;
+ };
+ events: {
+ note: (payload: Note) => void;
+ };
+ receives: null;
+ };
+ hashtag: {
+ params: {
+ q?: string;
+ };
+ events: {
+ note: (payload: Note) => void;
+ };
+ receives: null;
+ };
+ roleTimeline: {
+ params: {
+ roleId: string;
+ };
+ events: {
+ note: (payload: Note) => void;
+ };
+ receives: null;
+ };
+ antenna: {
+ params: {
+ antennaId: string;
+ };
+ events: {
+ note: (payload: Note) => void;
+ };
+ receives: null;
+ };
+ channel: {
+ params: {
+ channelId: string;
+ };
events: {
note: (payload: Note) => void;
};
receives: null;
};
+ drive: {
+ params: null;
+ events: {
+ fileCreated: (payload: DriveFile) => void;
+ fileDeleted: (payload: DriveFile['id']) => void;
+ fileUpdated: (payload: DriveFile) => void;
+ folderCreated: (payload: DriveFolder) => void;
+ folderDeleted: (payload: DriveFolder['id']) => void;
+ folderUpdated: (payload: DriveFile) => void;
+ };
+ receives: null;
+ };
serverStats: {
params: null;
events: {
- stats: (payload: FIXME) => void;
+ stats: (payload: ServerStats) => void;
+ statsLog: (payload: ServerStatsLog) => void;
};
receives: {
requestLog: {
@@ -544,7 +622,8 @@ export type Channels = {
queueStats: {
params: null;
events: {
- stats: (payload: FIXME) => void;
+ stats: (payload: QueueStats) => void;
+ statsLog: (payload: QueueStatsLog) => void;
};
receives: {
requestLog: {
@@ -553,6 +632,18 @@ export type Channels = {
};
};
};
+ admin: {
+ params: null;
+ events: {
+ newAbuseUserReport: {
+ id: string;
+ targetUserId: string;
+ reporterId: string;
+ comment: string;
+ };
+ };
+ receives: null;
+ };
};
// @public (undocumented)
@@ -847,6 +938,16 @@ type EmailAddressAvailableRequest = operations['email-address/available']['reque
type EmailAddressAvailableResponse = operations['email-address/available']['responses']['200']['content']['application/json'];
// @public (undocumented)
+type EmojiAdded = {
+ emoji: EmojiDetailed;
+};
+
+// @public (undocumented)
+type EmojiDeleted = {
+ emojis: EmojiDetailed[];
+};
+
+// @public (undocumented)
type EmojiDetailed = components['schemas']['EmojiDetailed'];
// @public (undocumented)
@@ -862,6 +963,11 @@ type EmojiSimple = components['schemas']['EmojiSimple'];
type EmojisResponse = operations['emojis']['responses']['200']['content']['application/json'];
// @public (undocumented)
+type EmojiUpdated = {
+ emojis: EmojiDetailed[];
+};
+
+// @public (undocumented)
type EmptyRequest = Record<string, unknown> | undefined;
// @public (undocumented)
@@ -902,6 +1008,14 @@ declare namespace entities {
DateString,
PageEvent,
ModerationLog,
+ ServerStats,
+ ServerStatsLog,
+ QueueStats,
+ QueueStatsLog,
+ EmojiAdded,
+ EmojiUpdated,
+ EmojiDeleted,
+ AnnouncementCreated,
EmptyRequest,
EmptyResponse,
AdminMetaResponse,
@@ -1404,7 +1518,8 @@ declare namespace entities {
GalleryPost,
EmojiSimple,
EmojiDetailed,
- Flash
+ Flash,
+ Signin
}
}
export { entities }
@@ -2155,6 +2270,25 @@ type PromoReadRequest = operations['promo/read']['requestBody']['content']['appl
type QueueCount = components['schemas']['QueueCount'];
// @public (undocumented)
+type QueueStats = {
+ deliver: {
+ activeSincePrevTick: number;
+ active: number;
+ waiting: number;
+ delayed: number;
+ };
+ inbox: {
+ activeSincePrevTick: number;
+ active: number;
+ waiting: number;
+ delayed: number;
+ };
+};
+
+// @public (undocumented)
+type QueueStatsLog = string[];
+
+// @public (undocumented)
type RenoteMuteCreateRequest = operations['renote-mute/create']['requestBody']['content']['application/json'];
// @public (undocumented)
@@ -2191,6 +2325,29 @@ type RolesShowRequest = operations['roles/show']['requestBody']['content']['appl
type RolesUsersRequest = operations['roles/users']['requestBody']['content']['application/json'];
// @public (undocumented)
+type ServerStats = {
+ cpu: number;
+ mem: {
+ used: number;
+ active: number;
+ };
+ net: {
+ rx: number;
+ tx: number;
+ };
+ fs: {
+ r: number;
+ w: number;
+ };
+};
+
+// @public (undocumented)
+type ServerStatsLog = string[];
+
+// @public (undocumented)
+type Signin = components['schemas']['Signin'];
+
+// @public (undocumented)
type StatsResponse = operations['stats']['responses']['200']['content']['application/json'];
// Warning: (ae-forgotten-export) The symbol "StreamEvents" needs to be exported by the entry point index.d.ts
@@ -2448,8 +2605,7 @@ type UsersUpdateMemoRequest = operations['users/update-memo']['requestBody']['co
// Warnings were encountered during analysis:
//
-// src/entities.ts:24:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts
-// src/streaming.types.ts:31:4 - (ae-forgotten-export) The symbol "FIXME" needs to be exported by the entry point index.d.ts
+// src/entities.ts:25:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts
// (No @packageDocumentation comment for this package)
diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts
index 64739a65d0..b46e69f691 100644
--- a/packages/misskey-js/src/autogen/endpoint.ts
+++ b/packages/misskey-js/src/autogen/endpoint.ts
@@ -1,6 +1,6 @@
/*
- * version: 2023.11.1
- * generatedAt: 2023-11-27T02:24:45.113Z
+ * version: 2023.12.0-beta.1
+ * generatedAt: 2023-12-03T02:04:45.058Z
*/
import type {
diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts
index 133a30b4ca..a51ee037d0 100644
--- a/packages/misskey-js/src/autogen/entities.ts
+++ b/packages/misskey-js/src/autogen/entities.ts
@@ -1,6 +1,6 @@
/*
- * version: 2023.11.1
- * generatedAt: 2023-11-27T02:24:45.111Z
+ * version: 2023.12.0-beta.1
+ * generatedAt: 2023-12-03T02:04:45.053Z
*/
import { operations } from './types.js';
diff --git a/packages/misskey-js/src/autogen/models.ts b/packages/misskey-js/src/autogen/models.ts
index bc7ab1f3b9..c2b27b2c58 100644
--- a/packages/misskey-js/src/autogen/models.ts
+++ b/packages/misskey-js/src/autogen/models.ts
@@ -1,6 +1,6 @@
/*
- * version: 2023.11.1
- * generatedAt: 2023-11-27T02:24:45.109Z
+ * version: 2023.12.0-beta.1
+ * generatedAt: 2023-12-03T02:04:45.051Z
*/
import { components } from './types.js';
@@ -37,3 +37,4 @@ export type GalleryPost = components['schemas']['GalleryPost'];
export type EmojiSimple = components['schemas']['EmojiSimple'];
export type EmojiDetailed = components['schemas']['EmojiDetailed'];
export type Flash = components['schemas']['Flash'];
+export type Signin = components['schemas']['Signin'];
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index c7f5c6c82d..44ed4dbaa8 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -2,8 +2,8 @@
/* eslint @typescript-eslint/no-explicit-any: 0 */
/*
- * version: 2023.11.1
- * generatedAt: 2023-11-27T02:24:44.994Z
+ * version: 2023.12.0-beta.1
+ * generatedAt: 2023-12-03T02:04:44.864Z
*/
/**
@@ -3388,6 +3388,7 @@ export type components = {
uri?: string;
url?: string;
reactionAndUserPairCache?: string[];
+ clippedCount?: number;
myReaction?: Record<string, unknown> | null;
};
NoteReaction: {
@@ -3786,6 +3787,14 @@ export type components = {
likedCount: number | null;
isLiked?: boolean;
};
+ Signin: {
+ id: string;
+ /** Format: date-time */
+ createdAt: string;
+ ip: string;
+ headers: Record<string, never>;
+ success: boolean;
+ };
};
responses: never;
parameters: never;
@@ -6405,10 +6414,7 @@ export type operations = {
/** @description OK (with results) */
200: {
content: {
- 'application/json': {
- /** @example GR6S02ERUA5VR */
- code: string;
- }[];
+ 'application/json': components['schemas']['InviteCode'][];
};
};
/** @description Client error */
@@ -6471,7 +6477,7 @@ export type operations = {
/** @description OK (with results) */
200: {
content: {
- 'application/json': Record<string, never>[];
+ 'application/json': components['schemas']['InviteCode'][];
};
};
/** @description Client error */
@@ -9600,6 +9606,8 @@ export type operations = {
untilId?: string;
sinceDate?: number;
untilDate?: number;
+ /** @default false */
+ allowPartial?: boolean;
};
};
};
@@ -15893,10 +15901,7 @@ export type operations = {
/** @description OK (with results) */
200: {
content: {
- 'application/json': {
- /** @example GR6S02ERUA5VR */
- code: string;
- };
+ 'application/json': components['schemas']['InviteCode'];
};
};
/** @description Client error */
@@ -17349,6 +17354,8 @@ export type operations = {
untilId?: string;
sinceDate?: number;
untilDate?: number;
+ /** @default false */
+ allowPartial?: boolean;
/** @default true */
includeMyRenotes?: boolean;
/** @default true */
@@ -17419,14 +17426,14 @@ export type operations = {
withRenotes?: boolean;
/** @default false */
withReplies?: boolean;
- /** @default false */
- excludeNsfw?: boolean;
/** @default 10 */
limit?: number;
/** Format: misskey:id */
sinceId?: string;
/** Format: misskey:id */
untilId?: string;
+ /** @default false */
+ allowPartial?: boolean;
sinceDate?: number;
untilDate?: number;
};
@@ -18317,6 +18324,8 @@ export type operations = {
untilId?: string;
sinceDate?: number;
untilDate?: number;
+ /** @default false */
+ allowPartial?: boolean;
/** @default true */
includeMyRenotes?: boolean;
/** @default true */
@@ -18502,6 +18511,8 @@ export type operations = {
untilId?: string;
sinceDate?: number;
untilDate?: number;
+ /** @default false */
+ allowPartial?: boolean;
/** @default true */
includeMyRenotes?: boolean;
/** @default true */
@@ -20799,6 +20810,7 @@ export type operations = {
username?: string;
/** @description The local host is represented with `null`. */
host?: string | null;
+ birthday?: string | null;
};
};
};
@@ -21704,9 +21716,9 @@ export type operations = {
sinceDate?: number;
untilDate?: number;
/** @default false */
- withFiles?: boolean;
+ allowPartial?: boolean;
/** @default false */
- excludeNsfw?: boolean;
+ withFiles?: boolean;
};
};
};
diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts
index b1d6b5c10f..99f433cc02 100644
--- a/packages/misskey-js/src/entities.ts
+++ b/packages/misskey-js/src/entities.ts
@@ -1,5 +1,6 @@
-import { ModerationLogPayloads, notificationTypes } from './consts.js';
-import { Page, User, UserDetailed } from './autogen/models';
+import { ModerationLogPayloads } from './consts.js';
+import { Announcement, EmojiDetailed, Page, User, UserDetailed } from './autogen/models';
+
export * from './autogen/entities';
export * from './autogen/models';
@@ -131,3 +132,54 @@ export type ModerationLog = {
type: 'unsetUserBanner';
info: ModerationLogPayloads['unsetUserBanner'];
});
+
+export type ServerStats = {
+ cpu: number;
+ mem: {
+ used: number;
+ active: number;
+ };
+ net: {
+ rx: number;
+ tx: number;
+ };
+ fs: {
+ r: number;
+ w: number;
+ }
+};
+
+export type ServerStatsLog = string[];
+
+export type QueueStats = {
+ deliver: {
+ activeSincePrevTick: number;
+ active: number;
+ waiting: number;
+ delayed: number;
+ };
+ inbox: {
+ activeSincePrevTick: number;
+ active: number;
+ waiting: number;
+ delayed: number;
+ };
+};
+
+export type QueueStatsLog = string[];
+
+export type EmojiAdded = {
+ emoji: EmojiDetailed
+};
+
+export type EmojiUpdated = {
+ emojis: EmojiDetailed[]
+};
+
+export type EmojiDeleted = {
+ emojis: EmojiDetailed[]
+};
+
+export type AnnouncementCreated = {
+ announcement: Announcement;
+};
diff --git a/packages/misskey-js/src/streaming.types.ts b/packages/misskey-js/src/streaming.types.ts
index 7981c280f6..6f575ce585 100644
--- a/packages/misskey-js/src/streaming.types.ts
+++ b/packages/misskey-js/src/streaming.types.ts
@@ -1,7 +1,23 @@
-import { Antenna, DriveFile, EmojiDetailed, MeDetailed, Note, User, Notification } from './autogen/models.js';
-import { PageEvent } from './entities.js';
-
-type FIXME = any;
+import {
+ Antenna,
+ DriveFile,
+ DriveFolder,
+ MeDetailed,
+ Note,
+ Notification,
+ Signin,
+ User,
+} from './autogen/models.js';
+import {
+ AnnouncementCreated,
+ EmojiAdded, EmojiDeleted,
+ EmojiUpdated,
+ PageEvent,
+ QueueStats,
+ QueueStatsLog,
+ ServerStats,
+ ServerStatsLog,
+} from './entities.js';
export type Channels = {
main: {
@@ -27,9 +43,7 @@ export type Channels = {
unreadAntenna: (payload: Antenna) => void;
readAllAnnouncements: () => void;
myTokenRegenerated: () => void;
- reversiNoInvites: () => void;
- reversiInvited: (payload: FIXME) => void;
- signin: (payload: FIXME) => void;
+ signin: (payload: Signin) => void;
registryUpdated: (payload: {
scope?: string[];
key: string;
@@ -37,41 +51,116 @@ export type Channels = {
}) => void;
driveFileCreated: (payload: DriveFile) => void;
readAntenna: (payload: Antenna) => void;
+ receiveFollowRequest: (payload: User) => void;
+ announcementCreated: (payload: AnnouncementCreated) => void;
};
receives: null;
};
homeTimeline: {
- params: null;
+ params: {
+ withRenotes?: boolean;
+ withFiles?: boolean;
+ };
events: {
note: (payload: Note) => void;
};
receives: null;
};
localTimeline: {
- params: null;
+ params: {
+ withRenotes?: boolean;
+ withReplies?: boolean;
+ withFiles?: boolean;
+ };
events: {
note: (payload: Note) => void;
};
receives: null;
};
hybridTimeline: {
- params: null;
+ params: {
+ withRenotes?: boolean;
+ withReplies?: boolean;
+ withFiles?: boolean;
+ };
events: {
note: (payload: Note) => void;
};
receives: null;
};
globalTimeline: {
- params: null;
+ params: {
+ withRenotes?: boolean;
+ withFiles?: boolean;
+ };
+ events: {
+ note: (payload: Note) => void;
+ };
+ receives: null;
+ };
+ userList: {
+ params: {
+ listId: string;
+ withFiles?: boolean;
+ };
+ events: {
+ note: (payload: Note) => void;
+ };
+ receives: null;
+ };
+ hashtag: {
+ params: {
+ q?: string;
+ };
+ events: {
+ note: (payload: Note) => void;
+ };
+ receives: null;
+ };
+ roleTimeline: {
+ params: {
+ roleId: string;
+ };
+ events: {
+ note: (payload: Note) => void;
+ };
+ receives: null;
+ };
+ antenna: {
+ params: {
+ antennaId: string;
+ };
+ events: {
+ note: (payload: Note) => void;
+ };
+ receives: null;
+ };
+ channel: {
+ params: {
+ channelId: string;
+ };
events: {
note: (payload: Note) => void;
};
receives: null;
};
+ drive: {
+ params: null;
+ events: {
+ fileCreated: (payload: DriveFile) => void;
+ fileDeleted: (payload: DriveFile['id']) => void;
+ fileUpdated: (payload: DriveFile) => void;
+ folderCreated: (payload: DriveFolder) => void;
+ folderDeleted: (payload: DriveFolder['id']) => void;
+ folderUpdated: (payload: DriveFile) => void;
+ };
+ receives: null;
+ };
serverStats: {
params: null;
events: {
- stats: (payload: FIXME) => void;
+ stats: (payload: ServerStats) => void;
+ statsLog: (payload: ServerStatsLog) => void;
};
receives: {
requestLog: {
@@ -83,7 +172,8 @@ export type Channels = {
queueStats: {
params: null;
events: {
- stats: (payload: FIXME) => void;
+ stats: (payload: QueueStats) => void;
+ statsLog: (payload: QueueStatsLog) => void;
};
receives: {
requestLog: {
@@ -92,30 +182,39 @@ export type Channels = {
};
};
};
+ admin: {
+ params: null;
+ events: {
+ newAbuseUserReport: {
+ id: string;
+ targetUserId: string;
+ reporterId: string;
+ comment: string;
+ }
+ };
+ receives: null;
+ }
};
export type NoteUpdatedEvent = {
- id: Note['id'];
type: 'reacted';
body: {
reaction: string;
+ emoji: string | null;
userId: User['id'];
};
} | {
- id: Note['id'];
type: 'unreacted';
body: {
reaction: string;
userId: User['id'];
};
} | {
- id: Note['id'];
type: 'deleted';
body: {
deletedAt: string;
};
} | {
- id: Note['id'];
type: 'pollVoted';
body: {
choice: number;
@@ -125,7 +224,8 @@ export type NoteUpdatedEvent = {
export type BroadcastEvents = {
noteUpdated: (payload: NoteUpdatedEvent) => void;
- emojiAdded: (payload: {
- emoji: EmojiDetailed;
- }) => void;
+ emojiAdded: (payload: EmojiAdded) => void;
+ emojiUpdated: (payload: EmojiUpdated) => void;
+ emojiDeleted: (payload: EmojiDeleted) => void;
+ announcementCreated: (payload: AnnouncementCreated) => void;
};