From 654c93b0ce457cbb03b9b6d95c279737d5257635 Mon Sep 17 00:00:00 2001
From: tamaina <tamaina@hotmail.co.jp>
Date: Sat, 27 May 2023 19:17:29 +0000
Subject: [PATCH] wip

---
 .../src/core/entities/RoleEntityService.ts    |   9 +-
 packages/misskey-js/src/entities.ts           |   4 +
 packages/misskey-js/src/schemas.ts            |  11 +-
 packages/misskey-js/src/schemas/role.ts       | 276 ++++++++++++++++--
 packages/misskey-js/test-d/schemas.ts         |   7 +-
 pnpm-lock.yaml                                |  10 +-
 6 files changed, 273 insertions(+), 44 deletions(-)

diff --git a/packages/backend/src/core/entities/RoleEntityService.ts b/packages/backend/src/core/entities/RoleEntityService.ts
index 54818782dd..fde9f7d08e 100644
--- a/packages/backend/src/core/entities/RoleEntityService.ts
+++ b/packages/backend/src/core/entities/RoleEntityService.ts
@@ -8,6 +8,8 @@ import type { Role } from '@/models/entities/Role.js';
 import { bindThis } from '@/decorators.js';
 import { DEFAULT_POLICIES } from '@/core/RoleService.js';
 import { UserEntityService } from './UserEntityService.js';
+import { Packed } from 'misskey-js';
+import { Serialized } from 'schema-type';
 
 @Injectable()
 export class RoleEntityService {
@@ -26,7 +28,7 @@ export class RoleEntityService {
 	public async pack(
 		src: Role['id'] | Role,
 		me?: { id: User['id'] } | null | undefined,
-	) {
+	): Promise<Serialized<Packed<'Role'>>> {
 		const role = typeof src === 'object' ? src : await this.rolesRepository.findOneByOrFail({ id: src });
 
 		const assignedCount = await this.roleAssignmentsRepository.createQueryBuilder('assign')
@@ -37,7 +39,7 @@ export class RoleEntityService {
 			}))
 			.getCount();
 
-		const policies = { ...role.policies };
+		const policies: { [x: string]: Packed<'RolePolicy'> } = { ...role.policies };
 		for (const [k, v] of Object.entries(DEFAULT_POLICIES)) {
 			if (policies[k] == null) policies[k] = {
 				useDefault: true,
@@ -72,8 +74,7 @@ export class RoleEntityService {
 	public packMany(
 		roles: any[],
 		me: { id: User['id'] },
-	) {
+	): Promise<Serialized<Packed<'Role'>>[]> {
 		return Promise.all(roles.map(x => this.pack(x, me)));
 	}
 }
-
diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts
index 4f8a2fa6ec..1224d84990 100644
--- a/packages/misskey-js/src/entities.ts
+++ b/packages/misskey-js/src/entities.ts
@@ -39,6 +39,10 @@ export type Channel = Packed<'Channel'>;
 export type Following = Packed<'Following'>;
 export type Blocking = Packed<'Blocking'>;
 export type Relay = Packed<'Relay'>;
+export type Role = Packed<'Role'>;
+export type RoleAssign = Packed<'RoleAssign'>;
+export type RolePolicy = Packed<'RolePolicy'>;
+export type RoleCondFormula = Packed<'RoleCondFormula'>;
 
 export type LiteInstanceMetadata = {
 	maintainerName: string | null;
diff --git a/packages/misskey-js/src/schemas.ts b/packages/misskey-js/src/schemas.ts
index 5891b91ae2..f284ce59f5 100644
--- a/packages/misskey-js/src/schemas.ts
+++ b/packages/misskey-js/src/schemas.ts
@@ -36,7 +36,12 @@ import { packedFlashSchema } from './schemas/flash.js';
 import { packedAdSchema } from './schemas/ad.js';
 import { packedAnnouncementSchema } from './schemas/announcement.js';
 import { packedRelaySchema } from './schemas/relay.js';
-import { packedRoleAssignSchema } from './schemas/role.js';
+import {
+	packedRoleSchema,
+	packedRoleAssignSchema,
+	packedRolePolicySchema,
+	packedRoleCondFormulaSchema,
+} from './schemas/role.js';
 import { Error, ApiError } from './schemas/error.js';
 import type { JSONSchema7, JSONSchema7Definition, GetDef, GetRefs, GetKeys, UnionToArray } from 'schema-type';
 
@@ -78,8 +83,10 @@ export const refs = {
 	Ad: packedAdSchema,
 	Announcement: packedAnnouncementSchema,
 	Relay: packedRelaySchema,
-
+	Role: packedRoleSchema,
 	RoleAssign: packedRoleAssignSchema,
+	RolePolicy: packedRolePolicySchema,
+	RoleCondFormula: packedRoleCondFormulaSchema,
 
 	Error: Error,
 	ApiError: ApiError,
diff --git a/packages/misskey-js/src/schemas/role.ts b/packages/misskey-js/src/schemas/role.ts
index f9a6279fd8..9e64cf3bfb 100644
--- a/packages/misskey-js/src/schemas/role.ts
+++ b/packages/misskey-js/src/schemas/role.ts
@@ -14,31 +14,81 @@ export const packedRoleSchema = {
 			type: 'string',
 			format: 'date-time',
 		},
-        name: {
-            type: 'string',
-        },
-        description: {
-            type: 'string',
-        },
-        color: {
-            type: ['string', 'null'],
-        },
-        iconUrl: {
-            type: ['string', 'null'],
-        },
-        target: {
-            enum: [
-                'manual',
-                'conditional',
-            ],
-        }
+		name: {
+			type: 'string',
+		},
+		description: {
+			type: 'string',
+		},
+		color: {
+			type: ['string', 'null'],
+		},
+		iconUrl: {
+			type: ['string', 'null'],
+		},
+		target: {
+			enum: [
+				'manual',
+				'conditional',
+			],
+		},
+		condFormula: {
+			type: 'object',
+			// 循環参照なので難しい
+			//$ref: 'https://misskey-hub.net/api/schemas/RoleCondFormula',
+		},
+		isPublic: {
+			type: 'boolean',
+		},
+		isAdministrator: {
+			type: 'boolean',
+		},
+		isModerator: {
+			type: 'boolean',
+		},
+		isExplorable: {
+			type: 'boolean',
+		},
+		asBadge: {
+			type: 'boolean',
+		},
+		canEditMembersByModerator: {
+			type: 'boolean',
+		},
+		displayOrder: {
+			type: 'number',
+		},
+		policies: {
+			type: 'object',
+			additionalProperties: {
+				$ref: 'https://misskey-hub.net/api/schemas/RolePolicy',
+			},
+		},
+		usersCount: {
+			type: 'number',
+		},
 	},
 	required: [
 		'id',
 		'createdAt',
-        'updatedAt',
+		'updatedAt',
+		'name',
+		'description',
+		'color',
+		'iconUrl',
+		'target',
+		'condFormula',
+		'isPublic',
+		'isAdministrator',
+		'isModerator',
+		'isExplorable',
+		'asBadge',
+		'canEditMembersByModerator',
+		'displayOrder',
+		'policies',
+		'usersCount',
 	],
-}
+} as const satisfies JSONSchema7Definition;
 
 export const packedRoleAssignSchema = {
 	$id: 'https://misskey-hub.net/api/schemas/RoleAssign',
@@ -50,20 +100,184 @@ export const packedRoleAssignSchema = {
 			type: 'string',
 			format: 'date-time',
 		},
-        user: { $ref: 'https://misskey-hub.net/api/schemas/UserDetailed' },
-        expiresAt: {
-            oneOf: [{
-                type: 'string',
-                format: 'date-time',
-            }, {
-                type: 'null',
-            }],
-        },
+		user: { $ref: 'https://misskey-hub.net/api/schemas/UserDetailed' },
+		expiresAt: {
+			oneOf: [{
+				type: 'string',
+				format: 'date-time',
+			}, {
+				type: 'null',
+			}],
+		},
 	},
 	required: [
 		'id',
 		'createdAt',
-        'user',
-        'expiresAt',
+		'user',
+		'expiresAt',
 	],
 } as const satisfies JSONSchema7Definition;
+
+export const packedRolePolicySchema = {
+	$id: 'https://misskey-hub.net/api/schemas/RolePolicy',
+
+	type: 'object',
+	properties: {
+		useDefault: { type: 'boolean' },
+		priority: { type: 'number' },
+		value: { additionalProperties: true },
+	},
+	required: [
+		'useDefault',
+		'priority',
+		'value',
+	],
+} as const satisfies JSONSchema7Definition;
+
+export const packedRoleCondFormulaSchema = {
+	$id: 'https://misskey-hub.net/api/schemas/RoleCondFormula',
+
+	oneOf: [
+		{ $ref: '#/$defs/and' },
+		{ $ref: '#/$defs/or' },
+		{ $ref: '#/$defs/not' },
+		{ $ref: '#/$defs/isLocal' },
+		{ $ref: '#/$defs/isRemote' },
+		{ $ref: '#/$defs/createdLessThan' },
+		{ $ref: '#/$defs/createdMoreThan' },
+		{ $ref: '#/$defs/createdLessThanOrEq' },
+		{ $ref: '#/$defs/createdMoreThanOrEq' },
+		{ $ref: '#/$defs/followersLessThanOrEq' },
+		{ $ref: '#/$defs/followersMoreThanOrEq' },
+		{ $ref: '#/$defs/followingLessThanOrEq' },
+		{ $ref: '#/$defs/followingMoreThanOrEq' },
+		{ $ref: '#/$defs/notesLessThanOrEq' },
+		{ $ref: '#/$defs/notesMoreThanOrEq' },
+	],
+	$defs: {
+		and: {
+			type: 'object',
+			properties: {
+				type: { const: 'and' },
+				values: {
+					type: 'array',
+					items: { $ref: '#' },
+				},
+			},
+			required: ['type', 'values'],
+		},
+		or: {
+			type: 'object',
+			properties: {
+				type: { const: 'or' },
+				values: {
+					type: 'array',
+					items: { $ref: '#' },
+				},
+			},
+			required: ['type', 'values'],
+		},
+		not: {
+			type: 'object',
+			properties: {
+				type: { const: 'not' },
+				value: { $ref: '#' },
+			},
+			required: ['type', 'value'],
+		},
+		isLocal: {
+			type: 'object',
+			properties: {
+				type: { const: 'isLocal' },
+			},
+			required: ['type'],
+		},
+		isRemote: {
+			type: 'object',
+			properties: {
+				type: { const: 'isRemote' },
+			},
+			required: ['type'],
+		},
+		createdLessThan: {
+			type: 'object',
+			properties: {
+				type: { const: 'createdLessThan' },
+				value: { type: 'number' },
+			},
+			required: ['type', 'value'],
+		},
+		createdMoreThan: {
+			type: 'object',
+			properties: {
+				type: { const: 'createdMoreThan' },
+				value: { type: 'number' },
+			},
+			required: ['type', 'value'],
+		},
+		createdLessThanOrEq: {
+			type: 'object',
+			properties: {
+				type: { const: 'createdLessThanOrEq' },
+				value: { type: 'number' },
+			},
+			required: ['type', 'value'],
+		},
+		createdMoreThanOrEq: {
+			type: 'object',
+			properties: {
+				type: { const: 'createdMoreThanOrEq' },
+				value: { type: 'number' },
+			},
+			required: ['type', 'value'],
+		},
+		followersLessThanOrEq: {
+			type: 'object',
+			properties: {
+				type: { const: 'followersLessThanOrEq' },
+				value: { type: 'number' },
+			},
+			required: ['type', 'value'],
+		},
+		followersMoreThanOrEq: {
+			type: 'object',
+			properties: {
+				type: { const: 'followersMoreThanOrEq' },
+				value: { type: 'number' },
+			},
+			required: ['type', 'value'],
+		},
+		followingLessThanOrEq: {
+			type: 'object',
+			properties: {
+				type: { const: 'followingLessThanOrEq' },
+				value: { type: 'number' },
+			},
+			required: ['type', 'value'],
+		},
+		followingMoreThanOrEq: {
+			type: 'object',
+			properties: {
+				type: { const: 'followingMoreThanOrEq' },
+				value: { type: 'number' },
+			},
+			required: ['type', 'value'],
+		},
+		notesLessThanOrEq: {
+			type: 'object',
+			properties: {
+				type: { const: 'notesLessThanOrEq' },
+				value: { type: 'number' },
+			},
+			required: ['type', 'value'],
+		},
+		notesMoreThanOrEq: {
+			type: 'object',
+			properties: {
+				type: { const: 'notesMoreThanOrEq' },
+				value: { type: 'number' },
+			},
+			required: ['type', 'value'],
+		},
+	}
+} as const satisfies JSONSchema7Definition;
diff --git a/packages/misskey-js/test-d/schemas.ts b/packages/misskey-js/test-d/schemas.ts
index 0ba22fd92b..658d57caff 100644
--- a/packages/misskey-js/test-d/schemas.ts
+++ b/packages/misskey-js/test-d/schemas.ts
@@ -100,9 +100,12 @@ describe('schemas', () => {
     test('relay', () => {
         type Relay = Packed<'Relay'>;
     });
-    test('role': () => {
-
+    test('role', () => {
+        type Role = Packed<'Role'>;
+        type CF = Role['condFormula'];
         type RoleAssign = Packed<'RoleAssign'>;
+        type RolePolicy = Packed<'RolePolicy'>;
+        type RoleCondFormula = Packed<'RoleCondFormula'>;
     });
     test('error', () => {
         type Error = Packed<'Error'>;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0033267f3b..ecfc1a1efa 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -626,7 +626,7 @@ importers:
         version: 29.5.0
       schema-type:
         specifier: github:misskey-dev/schema-type
-        version: github.com/misskey-dev/schema-type/ecfe907fb71f89eb0e41ed4449246ccd8366a260(typescript@5.0.4)
+        version: github.com/misskey-dev/schema-type/04addbe29c488e9e749bb9fe09812407da132e11(typescript@5.0.4)
 
   packages/frontend:
     dependencies:
@@ -1026,7 +1026,7 @@ importers:
         version: 4.4.0
       schema-type:
         specifier: github:misskey-dev/schema-type
-        version: github.com/misskey-dev/schema-type/ecfe907fb71f89eb0e41ed4449246ccd8366a260(typescript@5.0.4)
+        version: github.com/misskey-dev/schema-type/04addbe29c488e9e749bb9fe09812407da132e11(typescript@5.0.4)
       ts-essentials:
         specifier: ^9.3.2
         version: 9.3.2(typescript@5.0.4)
@@ -20518,9 +20518,9 @@ packages:
     version: 0.0.0
     dev: false
 
-  github.com/misskey-dev/schema-type/ecfe907fb71f89eb0e41ed4449246ccd8366a260(typescript@5.0.4):
-    resolution: {tarball: https://codeload.github.com/misskey-dev/schema-type/tar.gz/ecfe907fb71f89eb0e41ed4449246ccd8366a260}
-    id: github.com/misskey-dev/schema-type/ecfe907fb71f89eb0e41ed4449246ccd8366a260
+  github.com/misskey-dev/schema-type/04addbe29c488e9e749bb9fe09812407da132e11(typescript@5.0.4):
+    resolution: {tarball: https://codeload.github.com/misskey-dev/schema-type/tar.gz/04addbe29c488e9e749bb9fe09812407da132e11}
+    id: github.com/misskey-dev/schema-type/04addbe29c488e9e749bb9fe09812407da132e11
     name: schema-type
     version: 1.0.0
     dependencies: