diff --git a/packages/backend/src/misc/schema.ts b/packages/backend/src/misc/schema.ts index fdecc278d4..7aeb65f296 100644 --- a/packages/backend/src/misc/schema.ts +++ b/packages/backend/src/misc/schema.ts @@ -132,11 +132,27 @@ type NullOrUndefined
=
// https://stackoverflow.com/questions/54938141/typescript-convert-union-to-intersection
// Get intersection from union
type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
+type PartialIntersection =
+ p['ref'] extends keyof typeof refs ? Packed :
+ p['properties'] extends NonNullable [number]> & UnionObjectSchemaType & PartialIntersection [number]>
+ :
+ p['anyOf'] extends ReadonlyArray & PartialIntersection = NullOrUndefined >;
export type SchemaTypeDef =
p['type'] extends 'null' ? null :
@@ -149,13 +165,7 @@ export type SchemaTypeDef =
string
) :
p['type'] extends 'boolean' ? boolean :
- p['type'] extends 'object' ? (
- p['ref'] extends keyof typeof refs ? Packed :
- p['properties'] extends NonNullable [number]> :
- p['anyOf'] extends ReadonlyArray & Partial :
p['type'] extends 'array' ? (
p['items'] extends OfSchema ? (
p['items']['anyOf'] extends ReadonlyArray =
p['items'] extends NonNullable [] :
any[]
) :
+ p['anyOf'] extends ReadonlyArray & PartialIntersection :
any;
diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts
index 92bc8a7595..a709ab2f7a 100644
--- a/packages/backend/src/server/api/endpoints/notes/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/create.ts
@@ -90,48 +90,13 @@ export const paramDef = {
visibleUserIds: { type: 'array', uniqueItems: true, items: {
type: 'string', format: 'misskey:id',
} },
- text: { type: 'string', maxLength: MAX_NOTE_TEXT_LENGTH, nullable: true },
cw: { type: 'string', nullable: true, maxLength: 100 },
localOnly: { type: 'boolean', default: false },
noExtractMentions: { type: 'boolean', default: false },
noExtractHashtags: { type: 'boolean', default: false },
noExtractEmojis: { type: 'boolean', default: false },
- fileIds: {
- type: 'array',
- uniqueItems: true,
- minItems: 1,
- maxItems: 16,
- items: { type: 'string', format: 'misskey:id' },
- },
- mediaIds: {
- deprecated: true,
- description: 'Use `fileIds` instead. If both are specified, this property is discarded.',
- type: 'array',
- uniqueItems: true,
- minItems: 1,
- maxItems: 16,
- items: { type: 'string', format: 'misskey:id' },
- },
replyId: { type: 'string', format: 'misskey:id', nullable: true },
- renoteId: { type: 'string', format: 'misskey:id', nullable: true },
channelId: { type: 'string', format: 'misskey:id', nullable: true },
- poll: {
- type: 'object',
- nullable: true,
- properties: {
- choices: {
- type: 'array',
- uniqueItems: true,
- minItems: 2,
- maxItems: 10,
- items: { type: 'string', minLength: 1, maxLength: 50 },
- },
- multiple: { type: 'boolean', default: false },
- expiresAt: { type: 'integer', nullable: true },
- expiredAfter: { type: 'integer', nullable: true, minimum: 1 },
- },
- required: ['choices'],
- },
},
anyOf: [
{
@@ -143,21 +108,60 @@ export const paramDef = {
},
{
// (re)note with files, text and poll are optional
+ properties: {
+ fileIds: {
+ type: 'array',
+ uniqueItems: true,
+ minItems: 1,
+ maxItems: 16,
+ items: { type: 'string', format: 'misskey:id' },
+ },
+ },
required: ['fileIds'],
},
{
// (re)note with files, text and poll are optional
+ properties: {
+ mediaIds: {
+ deprecated: true,
+ description: 'Use `fileIds` instead. If both are specified, this property is discarded.',
+ type: 'array',
+ uniqueItems: true,
+ minItems: 1,
+ maxItems: 16,
+ items: { type: 'string', format: 'misskey:id' },
+ },
+ },
required: ['mediaIds'],
},
{
// (re)note with poll, text and files are optional
properties: {
- poll: { type: 'object', nullable: false },
+ poll: {
+ type: 'object',
+ nullable: true,
+ properties: {
+ choices: {
+ type: 'array',
+ uniqueItems: true,
+ minItems: 2,
+ maxItems: 10,
+ items: { type: 'string', minLength: 1, maxLength: 50 },
+ },
+ multiple: { type: 'boolean' },
+ expiresAt: { type: 'integer', nullable: true },
+ expiredAfter: { type: 'integer', nullable: true, minimum: 1 },
+ },
+ required: ['choices'],
+ },
},
required: ['poll'],
},
{
// pure renote
+ properties: {
+ renoteId: { type: 'string', format: 'misskey:id', nullable: true },
+ },
required: ['renoteId'],
},
],
diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
index 95491211bc..b176e6c65d 100644
--- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
+++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
@@ -29,14 +29,22 @@ export const meta = {
export const paramDef = {
type: 'object',
properties: {
- username: { type: 'string', nullable: true },
- host: { type: 'string', nullable: true },
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
detail: { type: 'boolean', default: true },
},
anyOf: [
- { required: ['username'] },
- { required: ['host'] },
+ {
+ properties: {
+ username: { type: 'string', nullable: true },
+ },
+ required: ['username']
+ },
+ {
+ properties: {
+ host: { type: 'string', nullable: true },
+ },
+ required: ['host']
+ },
],
} as const;