wip
This commit is contained in:
parent
fd223a8538
commit
9530cb01b9
|
@ -1,17 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'activeUsers';
|
import * as _ from 'misskey-js/built/schemas/charts/active-users.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'readWrite': { intersection: ['read', 'write'] },
|
|
||||||
'read': { uniqueIncrement: true },
|
|
||||||
'write': { uniqueIncrement: true },
|
|
||||||
'registeredWithinWeek': { uniqueIncrement: true },
|
|
||||||
'registeredWithinMonth': { uniqueIncrement: true },
|
|
||||||
'registeredWithinYear': { uniqueIncrement: true },
|
|
||||||
'registeredOutsideWeek': { uniqueIncrement: true },
|
|
||||||
'registeredOutsideMonth': { uniqueIncrement: true },
|
|
||||||
'registeredOutsideYear': { uniqueIncrement: true },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
export const entity = Chart.schemaToEntity(name, schema);
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'apRequest';
|
import * as _ from 'misskey-js/built/schemas/charts/ap-request.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'deliverFailed': { },
|
|
||||||
'deliverSucceeded': { },
|
|
||||||
'inboxReceived': { },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
export const entity = Chart.schemaToEntity(name, schema);
|
||||||
|
|
|
@ -1,16 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'drive';
|
import * as _ from 'misskey-js/built/schemas/charts/drive.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'local.incCount': {},
|
|
||||||
'local.incSize': {}, // in kilobyte
|
|
||||||
'local.decCount': {},
|
|
||||||
'local.decSize': {}, // in kilobyte
|
|
||||||
'remote.incCount': {},
|
|
||||||
'remote.incSize': {}, // in kilobyte
|
|
||||||
'remote.decCount': {},
|
|
||||||
'remote.decSize': {}, // in kilobyte
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
export const entity = Chart.schemaToEntity(name, schema);
|
||||||
|
|
|
@ -1,16 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'federation';
|
import * as _ from 'misskey-js/built/schemas/charts/federation.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'deliveredInstances': { uniqueIncrement: true, range: 'small' },
|
|
||||||
'inboxInstances': { uniqueIncrement: true, range: 'small' },
|
|
||||||
'stalled': { uniqueIncrement: true, range: 'small' },
|
|
||||||
'sub': { accumulate: true, range: 'small' },
|
|
||||||
'pub': { accumulate: true, range: 'small' },
|
|
||||||
'pubsub': { accumulate: true, range: 'small' },
|
|
||||||
'subActive': { accumulate: true, range: 'small' },
|
|
||||||
'pubActive': { accumulate: true, range: 'small' },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
export const entity = Chart.schemaToEntity(name, schema);
|
||||||
|
|
|
@ -1,32 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'instance';
|
import * as _ from 'misskey-js/built/schemas/charts/instance.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'requests.failed': { range: 'small' },
|
|
||||||
'requests.succeeded': { range: 'small' },
|
|
||||||
'requests.received': { range: 'small' },
|
|
||||||
'notes.total': { accumulate: true },
|
|
||||||
'notes.inc': {},
|
|
||||||
'notes.dec': {},
|
|
||||||
'notes.diffs.normal': {},
|
|
||||||
'notes.diffs.reply': {},
|
|
||||||
'notes.diffs.renote': {},
|
|
||||||
'notes.diffs.withFile': {},
|
|
||||||
'users.total': { accumulate: true },
|
|
||||||
'users.inc': { range: 'small' },
|
|
||||||
'users.dec': { range: 'small' },
|
|
||||||
'following.total': { accumulate: true },
|
|
||||||
'following.inc': { range: 'small' },
|
|
||||||
'following.dec': { range: 'small' },
|
|
||||||
'followers.total': { accumulate: true },
|
|
||||||
'followers.inc': { range: 'small' },
|
|
||||||
'followers.dec': { range: 'small' },
|
|
||||||
'drive.totalFiles': { accumulate: true },
|
|
||||||
'drive.incFiles': {},
|
|
||||||
'drive.decFiles': {},
|
|
||||||
'drive.incUsage': {}, // in kilobyte
|
|
||||||
'drive.decUsage': {}, // in kilobyte
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||||
|
|
|
@ -1,22 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'notes';
|
import * as _ from 'misskey-js/built/schemas/charts/notes.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'local.total': { accumulate: true },
|
|
||||||
'local.inc': {},
|
|
||||||
'local.dec': {},
|
|
||||||
'local.diffs.normal': {},
|
|
||||||
'local.diffs.reply': {},
|
|
||||||
'local.diffs.renote': {},
|
|
||||||
'local.diffs.withFile': {},
|
|
||||||
'remote.total': { accumulate: true },
|
|
||||||
'remote.inc': {},
|
|
||||||
'remote.dec': {},
|
|
||||||
'remote.diffs.normal': {},
|
|
||||||
'remote.diffs.reply': {},
|
|
||||||
'remote.diffs.renote': {},
|
|
||||||
'remote.diffs.withFile': {},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
export const entity = Chart.schemaToEntity(name, schema);
|
||||||
|
|
|
@ -1,14 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'perUserDrive';
|
import * as _ from 'misskey-js/built/schemas/charts/per-user-drive.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'totalCount': { accumulate: true },
|
|
||||||
'totalSize': { accumulate: true }, // in kilobyte
|
|
||||||
'incCount': { range: 'small' },
|
|
||||||
'incSize': {}, // in kilobyte
|
|
||||||
'decCount': { range: 'small' },
|
|
||||||
'decSize': {}, // in kilobyte
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||||
|
|
|
@ -1,20 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'perUserFollowing';
|
import * as _ from 'misskey-js/built/schemas/charts/per-user-following.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'local.followings.total': { accumulate: true },
|
|
||||||
'local.followings.inc': { range: 'small' },
|
|
||||||
'local.followings.dec': { range: 'small' },
|
|
||||||
'local.followers.total': { accumulate: true },
|
|
||||||
'local.followers.inc': { range: 'small' },
|
|
||||||
'local.followers.dec': { range: 'small' },
|
|
||||||
'remote.followings.total': { accumulate: true },
|
|
||||||
'remote.followings.inc': { range: 'small' },
|
|
||||||
'remote.followings.dec': { range: 'small' },
|
|
||||||
'remote.followers.total': { accumulate: true },
|
|
||||||
'remote.followers.inc': { range: 'small' },
|
|
||||||
'remote.followers.dec': { range: 'small' },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||||
|
|
|
@ -1,15 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'perUserNotes';
|
import * as _ from 'misskey-js/built/schemas/charts/per-user-notes.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'total': { accumulate: true },
|
|
||||||
'inc': { range: 'small' },
|
|
||||||
'dec': { range: 'small' },
|
|
||||||
'diffs.normal': { range: 'small' },
|
|
||||||
'diffs.reply': { range: 'small' },
|
|
||||||
'diffs.renote': { range: 'small' },
|
|
||||||
'diffs.withFile': { range: 'small' },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'perUserPv';
|
import * as _ from 'misskey-js/built/schemas/charts/per-user-pv.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'upv.user': { uniqueIncrement: true, range: 'small' },
|
|
||||||
'pv.user': { range: 'small' },
|
|
||||||
'upv.visitor': { uniqueIncrement: true, range: 'small' },
|
|
||||||
'pv.visitor': { range: 'small' },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'perUserReaction';
|
import * as _ from 'misskey-js/built/schemas/charts/per-user-reactions.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'local.count': { range: 'small' },
|
|
||||||
'remote.count': { range: 'small' },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'testGrouped';
|
import * as _ from 'misskey-js/built/schemas/charts/test-grouped.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'foo.total': { accumulate: true },
|
|
||||||
'foo.inc': {},
|
|
||||||
'foo.dec': {},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema, true);
|
export const entity = Chart.schemaToEntity(name, schema, true);
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'testIntersection';
|
import * as _ from 'misskey-js/built/schemas/charts/test-intersection.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'a': { uniqueIncrement: true },
|
|
||||||
'b': { uniqueIncrement: true },
|
|
||||||
'aAndB': { intersection: ['a', 'b'] },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
export const entity = Chart.schemaToEntity(name, schema);
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'testUnique';
|
import * as _ from 'misskey-js/built/schemas/charts/test-unique.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'foo': { uniqueIncrement: true },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
export const entity = Chart.schemaToEntity(name, schema);
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'test';
|
import * as _ from 'misskey-js/built/schemas/charts/test.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'foo.total': { accumulate: true },
|
|
||||||
'foo.inc': {},
|
|
||||||
'foo.dec': {},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
export const entity = Chart.schemaToEntity(name, schema);
|
||||||
|
|
|
@ -1,14 +1,7 @@
|
||||||
import Chart from '../../core.js';
|
import Chart from '../../core.js';
|
||||||
|
|
||||||
export const name = 'users';
|
import * as _ from 'misskey-js/built/schemas/charts/users.js';
|
||||||
|
export const name = _.name;
|
||||||
export const schema = {
|
export const schema = _.schema;
|
||||||
'local.total': { accumulate: true },
|
|
||||||
'local.inc': { range: 'small' },
|
|
||||||
'local.dec': { range: 'small' },
|
|
||||||
'remote.total': { accumulate: true },
|
|
||||||
'remote.inc': { range: 'small' },
|
|
||||||
'remote.dec': { range: 'small' },
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const entity = Chart.schemaToEntity(name, schema);
|
export const entity = Chart.schemaToEntity(name, schema);
|
||||||
|
|
|
@ -10,22 +10,12 @@ import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '@/misc
|
||||||
import type Logger from '@/logger.js';
|
import type Logger from '@/logger.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import type { Repository, DataSource } from 'typeorm';
|
import type { Repository, DataSource } from 'typeorm';
|
||||||
|
import type { ChartSchema as Schema, ChartResult, Unflatten } from 'misskey-js/built/schemas';
|
||||||
|
|
||||||
const COLUMN_PREFIX = '___' as const;
|
const COLUMN_PREFIX = '___' as const;
|
||||||
const UNIQUE_TEMP_COLUMN_PREFIX = 'unique_temp___' as const;
|
const UNIQUE_TEMP_COLUMN_PREFIX = 'unique_temp___' as const;
|
||||||
const COLUMN_DELIMITER = '_' as const;
|
const COLUMN_DELIMITER = '_' as const;
|
||||||
|
|
||||||
type Schema = Record<string, {
|
|
||||||
uniqueIncrement?: boolean;
|
|
||||||
|
|
||||||
intersection?: string[] | ReadonlyArray<string>;
|
|
||||||
|
|
||||||
range?: 'big' | 'small' | 'medium';
|
|
||||||
|
|
||||||
// previousな値を引き継ぐかどうか
|
|
||||||
accumulate?: boolean;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
type KeyToColumnName<T extends string> = T extends `${infer R1}.${infer R2}` ? `${R1}${typeof COLUMN_DELIMITER}${KeyToColumnName<R2>}` : T;
|
type KeyToColumnName<T extends string> = T extends `${infer R1}.${infer R2}` ? `${R1}${typeof COLUMN_DELIMITER}${KeyToColumnName<R2>}` : T;
|
||||||
|
|
||||||
type Columns<S extends Schema> = {
|
type Columns<S extends Schema> = {
|
||||||
|
@ -64,47 +54,6 @@ export type KVs<S extends Schema> = {
|
||||||
[K in keyof S]: number;
|
[K in keyof S]: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ChartResult<T extends Schema> = {
|
|
||||||
[P in keyof T]: number[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never;
|
|
||||||
|
|
||||||
type UnflattenSingleton<K extends string, V> = K extends `${infer A}.${infer B}`
|
|
||||||
? { [_ in A]: UnflattenSingleton<B, V>; }
|
|
||||||
: { [_ in K]: V; };
|
|
||||||
|
|
||||||
type Unflatten<T extends Record<string, any>> = UnionToIntersection<
|
|
||||||
{
|
|
||||||
[K in Extract<keyof T, string>]: UnflattenSingleton<K, T[K]>;
|
|
||||||
}[Extract<keyof T, string>]
|
|
||||||
>;
|
|
||||||
|
|
||||||
type ToJsonSchema<S> = {
|
|
||||||
type: 'object';
|
|
||||||
properties: {
|
|
||||||
[K in keyof S]: S[K] extends number[] ? { type: 'array'; items: { type: 'number'; }; } : ToJsonSchema<S[K]>;
|
|
||||||
},
|
|
||||||
required: (keyof S)[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export function getJsonSchema<S extends Schema>(schema: S): ToJsonSchema<Unflatten<ChartResult<S>>> {
|
|
||||||
const jsonSchema = {
|
|
||||||
type: 'object',
|
|
||||||
properties: {} as Record<string, unknown>,
|
|
||||||
required: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const k in schema) {
|
|
||||||
jsonSchema.properties[k] = {
|
|
||||||
type: 'array',
|
|
||||||
items: { type: 'number' },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonSchema as ToJsonSchema<Unflatten<ChartResult<S>>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 様々なチャートの管理を司るクラス
|
* 様々なチャートの管理を司るクラス
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,36 +1,15 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { getJsonSchema } from '@/core/chart/core.js';
|
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import PerUserDriveChart from '@/core/chart/charts/per-user-drive.js';
|
import PerUserDriveChart from '@/core/chart/charts/per-user-drive.js';
|
||||||
import { schema } from '@/core/chart/charts/entities/per-user-drive.js';
|
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
tags: ['charts', 'drive', 'users'],
|
|
||||||
|
|
||||||
res: getJsonSchema(schema),
|
|
||||||
|
|
||||||
allowGet: true,
|
|
||||||
cacheSec: 60 * 60,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const paramDef = {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
span: { type: 'string', enum: ['day', 'hour'] },
|
|
||||||
limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 },
|
|
||||||
offset: { type: 'integer', nullable: true, default: null },
|
|
||||||
userId: { type: 'string', format: 'misskey:id' },
|
|
||||||
},
|
|
||||||
required: ['span', 'userId'],
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-default-export
|
// eslint-disable-next-line import/no-default-export
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export default class extends Endpoint<typeof meta, typeof paramDef> {
|
export default class extends Endpoint<'charts/user/drive'> {
|
||||||
|
name = 'charts/user/drive' as const;
|
||||||
constructor(
|
constructor(
|
||||||
private perUserDriveChart: PerUserDriveChart,
|
private perUserDriveChart: PerUserDriveChart,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(async (ps, me) => {
|
||||||
return await this.perUserDriveChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null, ps.userId);
|
return await this.perUserDriveChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null, ps.userId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,9 @@ import type { JSONSchema7 } from 'schema-type';
|
||||||
import { IEndpointMeta } from './endpoints.types';
|
import { IEndpointMeta } from './endpoints.types';
|
||||||
import { localUsernameSchema, passwordSchema } from './schemas/user';
|
import { localUsernameSchema, passwordSchema } from './schemas/user';
|
||||||
import ms from 'ms';
|
import ms from 'ms';
|
||||||
|
import { getJsonSchema } from './schemas';
|
||||||
|
import * as perUserDriveChartSchema from './schemas/charts/per-user-drive';
|
||||||
|
import * as driveChartSchema from './schemas/charts/drive';
|
||||||
|
|
||||||
export const endpoints = {
|
export const endpoints = {
|
||||||
//#region admin
|
//#region admin
|
||||||
|
@ -2984,6 +2987,29 @@ export const endpoints = {
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
//#region charts
|
||||||
|
'charts/user/drive': {
|
||||||
|
tags: ['charts', 'drive', 'users'],
|
||||||
|
|
||||||
|
allowGet: true,
|
||||||
|
cacheSec: 60 * 60,
|
||||||
|
|
||||||
|
defines: [{
|
||||||
|
req: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
span: { type: 'string', enum: ['day', 'hour'] },
|
||||||
|
limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 },
|
||||||
|
offset: { type: 'integer', nullable: true, default: null },
|
||||||
|
userId: { type: 'string', format: 'misskey:id' },
|
||||||
|
},
|
||||||
|
required: ['span', 'userId'],
|
||||||
|
},
|
||||||
|
res: getJsonSchema(perUserDriveChartSchema.schema) satisfies JSONSchema7,
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
//#endregion
|
||||||
} as const satisfies { [x: string]: IEndpointMeta; };
|
} as const satisfies { [x: string]: IEndpointMeta; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -58,7 +58,7 @@ import {
|
||||||
import { packedModerationLogSchema } from './schemas/moderation-log.js';
|
import { packedModerationLogSchema } from './schemas/moderation-log.js';
|
||||||
import { packedAuthSessionSchema } from './schemas/auth-session.js';
|
import { packedAuthSessionSchema } from './schemas/auth-session.js';
|
||||||
import { Error, ApiError } from './schemas/error.js';
|
import { Error, ApiError } from './schemas/error.js';
|
||||||
import type { JSONSchema7, JSONSchema7Definition, GetDef, GetRefs, GetKeys, UnionToArray, Serialized } from 'schema-type';
|
import type { JSONSchema7, JSONSchema7Definition, GetDef, GetRefs, GetKeys, UnionToArray, Serialized, Projected } from 'schema-type';
|
||||||
|
|
||||||
export const refs = {
|
export const refs = {
|
||||||
Id: IdSchema,
|
Id: IdSchema,
|
||||||
|
@ -120,3 +120,57 @@ export type References = GetRefs<typeof refs>;
|
||||||
|
|
||||||
export type Packed<x extends GetKeys<References, 'https://misskey-hub.net/api/schemas/'>> = Serialized<GetDef<References, x, false, 'https://misskey-hub.net/api/schemas/'>>;
|
export type Packed<x extends GetKeys<References, 'https://misskey-hub.net/api/schemas/'>> = Serialized<GetDef<References, x, false, 'https://misskey-hub.net/api/schemas/'>>;
|
||||||
export type Def<x extends GetKeys<References>> = GetDef<References, x>;
|
export type Def<x extends GetKeys<References>> = GetDef<References, x>;
|
||||||
|
|
||||||
|
//#reginon Chart
|
||||||
|
export type ChartSchema = Record<string, {
|
||||||
|
uniqueIncrement?: boolean;
|
||||||
|
|
||||||
|
intersection?: string[] | ReadonlyArray<string>;
|
||||||
|
|
||||||
|
range?: 'big' | 'small' | 'medium';
|
||||||
|
|
||||||
|
// previousな値を引き継ぐかどうか
|
||||||
|
accumulate?: boolean;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type ChartResult<T extends ChartSchema> = {
|
||||||
|
[P in keyof T]: number[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never;
|
||||||
|
|
||||||
|
type UnflattenSingleton<K extends string, V> = K extends `${infer A}.${infer B}`
|
||||||
|
? { [_ in A]: UnflattenSingleton<B, V>; }
|
||||||
|
: { [_ in K]: V; };
|
||||||
|
|
||||||
|
export type Unflatten<T extends Record<string, any>> = Projected<UnionToIntersection<
|
||||||
|
{
|
||||||
|
[K in Extract<keyof T, string>]: UnflattenSingleton<K, T[K]>;
|
||||||
|
}[Extract<keyof T, string>]
|
||||||
|
>>;
|
||||||
|
|
||||||
|
type ToJsonSchema<S> = {
|
||||||
|
type: 'object';
|
||||||
|
properties: {
|
||||||
|
[K in keyof S]: S[K] extends number[] ? { type: 'array'; items: { type: 'number'; }; } : ToJsonSchema<S[K]>;
|
||||||
|
},
|
||||||
|
required: (keyof S)[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getJsonSchema<S extends ChartSchema>(schema: S): ToJsonSchema<Unflatten<ChartResult<S>>> {
|
||||||
|
const jsonSchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {} as Record<string, unknown>,
|
||||||
|
required: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const k in schema) {
|
||||||
|
jsonSchema.properties[k] = {
|
||||||
|
type: 'array',
|
||||||
|
items: { type: 'number' },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonSchema as ToJsonSchema<Unflatten<ChartResult<S>>>;
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
export const name = 'activeUsers';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'readWrite': { intersection: ['read', 'write'] },
|
||||||
|
'read': { uniqueIncrement: true },
|
||||||
|
'write': { uniqueIncrement: true },
|
||||||
|
'registeredWithinWeek': { uniqueIncrement: true },
|
||||||
|
'registeredWithinMonth': { uniqueIncrement: true },
|
||||||
|
'registeredWithinYear': { uniqueIncrement: true },
|
||||||
|
'registeredOutsideWeek': { uniqueIncrement: true },
|
||||||
|
'registeredOutsideMonth': { uniqueIncrement: true },
|
||||||
|
'registeredOutsideYear': { uniqueIncrement: true },
|
||||||
|
} as const;
|
|
@ -0,0 +1,7 @@
|
||||||
|
export const name = 'apRequest';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'deliverFailed': { },
|
||||||
|
'deliverSucceeded': { },
|
||||||
|
'inboxReceived': { },
|
||||||
|
} as const;
|
|
@ -0,0 +1,12 @@
|
||||||
|
export const name = 'drive';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'local.incCount': {},
|
||||||
|
'local.incSize': {}, // in kilobyte
|
||||||
|
'local.decCount': {},
|
||||||
|
'local.decSize': {}, // in kilobyte
|
||||||
|
'remote.incCount': {},
|
||||||
|
'remote.incSize': {}, // in kilobyte
|
||||||
|
'remote.decCount': {},
|
||||||
|
'remote.decSize': {}, // in kilobyte
|
||||||
|
} as const;
|
|
@ -0,0 +1,12 @@
|
||||||
|
export const name = 'federation';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'deliveredInstances': { uniqueIncrement: true, range: 'small' },
|
||||||
|
'inboxInstances': { uniqueIncrement: true, range: 'small' },
|
||||||
|
'stalled': { uniqueIncrement: true, range: 'small' },
|
||||||
|
'sub': { accumulate: true, range: 'small' },
|
||||||
|
'pub': { accumulate: true, range: 'small' },
|
||||||
|
'pubsub': { accumulate: true, range: 'small' },
|
||||||
|
'subActive': { accumulate: true, range: 'small' },
|
||||||
|
'pubActive': { accumulate: true, range: 'small' },
|
||||||
|
} as const;
|
|
@ -0,0 +1,28 @@
|
||||||
|
export const name = 'instance';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'requests.failed': { range: 'small' },
|
||||||
|
'requests.succeeded': { range: 'small' },
|
||||||
|
'requests.received': { range: 'small' },
|
||||||
|
'notes.total': { accumulate: true },
|
||||||
|
'notes.inc': {},
|
||||||
|
'notes.dec': {},
|
||||||
|
'notes.diffs.normal': {},
|
||||||
|
'notes.diffs.reply': {},
|
||||||
|
'notes.diffs.renote': {},
|
||||||
|
'notes.diffs.withFile': {},
|
||||||
|
'users.total': { accumulate: true },
|
||||||
|
'users.inc': { range: 'small' },
|
||||||
|
'users.dec': { range: 'small' },
|
||||||
|
'following.total': { accumulate: true },
|
||||||
|
'following.inc': { range: 'small' },
|
||||||
|
'following.dec': { range: 'small' },
|
||||||
|
'followers.total': { accumulate: true },
|
||||||
|
'followers.inc': { range: 'small' },
|
||||||
|
'followers.dec': { range: 'small' },
|
||||||
|
'drive.totalFiles': { accumulate: true },
|
||||||
|
'drive.incFiles': {},
|
||||||
|
'drive.decFiles': {},
|
||||||
|
'drive.incUsage': {}, // in kilobyte
|
||||||
|
'drive.decUsage': {}, // in kilobyte
|
||||||
|
} as const;
|
|
@ -0,0 +1,18 @@
|
||||||
|
export const name = 'notes';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'local.total': { accumulate: true },
|
||||||
|
'local.inc': {},
|
||||||
|
'local.dec': {},
|
||||||
|
'local.diffs.normal': {},
|
||||||
|
'local.diffs.reply': {},
|
||||||
|
'local.diffs.renote': {},
|
||||||
|
'local.diffs.withFile': {},
|
||||||
|
'remote.total': { accumulate: true },
|
||||||
|
'remote.inc': {},
|
||||||
|
'remote.dec': {},
|
||||||
|
'remote.diffs.normal': {},
|
||||||
|
'remote.diffs.reply': {},
|
||||||
|
'remote.diffs.renote': {},
|
||||||
|
'remote.diffs.withFile': {},
|
||||||
|
} as const;
|
|
@ -0,0 +1,10 @@
|
||||||
|
export const name = 'perUserDrive';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'totalCount': { accumulate: true },
|
||||||
|
'totalSize': { accumulate: true }, // in kilobyte
|
||||||
|
'incCount': { range: 'small' },
|
||||||
|
'incSize': {}, // in kilobyte
|
||||||
|
'decCount': { range: 'small' },
|
||||||
|
'decSize': {}, // in kilobyte
|
||||||
|
} as const;
|
|
@ -0,0 +1,16 @@
|
||||||
|
export const name = 'perUserFollowing';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'local.followings.total': { accumulate: true },
|
||||||
|
'local.followings.inc': { range: 'small' },
|
||||||
|
'local.followings.dec': { range: 'small' },
|
||||||
|
'local.followers.total': { accumulate: true },
|
||||||
|
'local.followers.inc': { range: 'small' },
|
||||||
|
'local.followers.dec': { range: 'small' },
|
||||||
|
'remote.followings.total': { accumulate: true },
|
||||||
|
'remote.followings.inc': { range: 'small' },
|
||||||
|
'remote.followings.dec': { range: 'small' },
|
||||||
|
'remote.followers.total': { accumulate: true },
|
||||||
|
'remote.followers.inc': { range: 'small' },
|
||||||
|
'remote.followers.dec': { range: 'small' },
|
||||||
|
} as const;
|
|
@ -0,0 +1,11 @@
|
||||||
|
export const name = 'perUserNotes';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'total': { accumulate: true },
|
||||||
|
'inc': { range: 'small' },
|
||||||
|
'dec': { range: 'small' },
|
||||||
|
'diffs.normal': { range: 'small' },
|
||||||
|
'diffs.reply': { range: 'small' },
|
||||||
|
'diffs.renote': { range: 'small' },
|
||||||
|
'diffs.withFile': { range: 'small' },
|
||||||
|
} as const;
|
|
@ -0,0 +1,8 @@
|
||||||
|
export const name = 'perUserPv';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'upv.user': { uniqueIncrement: true, range: 'small' },
|
||||||
|
'pv.user': { range: 'small' },
|
||||||
|
'upv.visitor': { uniqueIncrement: true, range: 'small' },
|
||||||
|
'pv.visitor': { range: 'small' },
|
||||||
|
} as const;
|
|
@ -0,0 +1,6 @@
|
||||||
|
export const name = 'perUserReaction';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'local.count': { range: 'small' },
|
||||||
|
'remote.count': { range: 'small' },
|
||||||
|
} as const;
|
|
@ -0,0 +1,7 @@
|
||||||
|
export const name = 'testGrouped';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'foo.total': { accumulate: true },
|
||||||
|
'foo.inc': {},
|
||||||
|
'foo.dec': {},
|
||||||
|
} as const;
|
|
@ -0,0 +1,7 @@
|
||||||
|
export const name = 'testIntersection';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'a': { uniqueIncrement: true },
|
||||||
|
'b': { uniqueIncrement: true },
|
||||||
|
'aAndB': { intersection: ['a', 'b'] },
|
||||||
|
} as const;
|
|
@ -0,0 +1,5 @@
|
||||||
|
export const name = 'testUnique';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'foo': { uniqueIncrement: true },
|
||||||
|
} as const;
|
|
@ -0,0 +1,7 @@
|
||||||
|
export const name = 'test';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'foo.total': { accumulate: true },
|
||||||
|
'foo.inc': {},
|
||||||
|
'foo.dec': {},
|
||||||
|
} as const;
|
|
@ -0,0 +1,10 @@
|
||||||
|
export const name = 'users';
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
'local.total': { accumulate: true },
|
||||||
|
'local.inc': { range: 'small' },
|
||||||
|
'local.dec': { range: 'small' },
|
||||||
|
'remote.total': { accumulate: true },
|
||||||
|
'remote.inc': { range: 'small' },
|
||||||
|
'remote.dec': { range: 'small' },
|
||||||
|
} as const;
|
Loading…
Reference in New Issue