summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2019-02-24 09:45:27 +0900
committersyuilo <syuilotan@yahoo.co.jp>2019-02-24 09:45:27 +0900
commitb679163d01b0152b38db658fe49d8a57c6aad930 (patch)
tree9919cc598ed825c6841f47813010dac2d704614d /src
parentUpdate schemas.ts (diff)
downloadsharkey-b679163d01b0152b38db658fe49d8a57c6aad930.tar.gz
sharkey-b679163d01b0152b38db658fe49d8a57c6aad930.tar.bz2
sharkey-b679163d01b0152b38db658fe49d8a57c6aad930.zip
Improve type definitions
Diffstat (limited to 'src')
-rw-r--r--src/prelude/schema.ts38
-rw-r--r--src/server/api/endpoints.ts3
-rw-r--r--src/server/api/endpoints/charts/notes.ts10
-rw-r--r--src/server/api/endpoints/notes/create.ts6
-rw-r--r--src/server/api/openapi/gen-spec.ts29
-rw-r--r--src/services/chart/index.ts16
-rw-r--r--src/services/chart/notes.ts79
7 files changed, 109 insertions, 72 deletions
diff --git a/src/prelude/schema.ts b/src/prelude/schema.ts
new file mode 100644
index 0000000000..7c3d6aac8f
--- /dev/null
+++ b/src/prelude/schema.ts
@@ -0,0 +1,38 @@
+export type Schema = {
+ type: 'number' | 'string' | 'array' | 'object' | any;
+ optional?: boolean;
+ items?: Schema;
+ properties?: Obj;
+ description?: string;
+};
+
+export type Obj = { [key: string]: Schema };
+
+export type ObjType<s extends Obj> = { [P in keyof s]: SchemaType<s[P]> };
+
+// https://qiita.com/hrsh7th@github/items/84e8968c3601009cdcf2
+type MyType<T extends Schema> = {
+ 0: any;
+ 1: SchemaType<T>;
+}[T extends Schema ? 1 : 0];
+
+export type SchemaType<p extends Schema> =
+ p['type'] extends 'number' ? number :
+ p['type'] extends 'string' ? string :
+ p['type'] extends 'array' ? MyType<p['items']>[] :
+ p['type'] extends 'object' ? ObjType<p['properties']> :
+ any;
+
+export function convertOpenApiSchema(schema: Schema) {
+ const x = JSON.parse(JSON.stringify(schema)); // copy
+ if (!['string', 'number', 'boolean', 'array', 'object'].includes(x.type)) {
+ x['$ref'] = `#/components/schemas/${x.type}`;
+ }
+ if (x.type === 'object' && x.properties) {
+ x.required = Object.entries(x.properties).filter(([k, v]: any) => !v.isOptional).map(([k, v]: any) => k);
+ for (const k of Object.keys(x.properties)) {
+ x.properties[k] = convertOpenApiSchema(x.properties[k]);
+ }
+ }
+ return x;
+}
diff --git a/src/server/api/endpoints.ts b/src/server/api/endpoints.ts
index 2873dd3c1e..7abee95a51 100644
--- a/src/server/api/endpoints.ts
+++ b/src/server/api/endpoints.ts
@@ -1,6 +1,7 @@
import { Context } from 'cafy';
import * as path from 'path';
import * as glob from 'glob';
+import { Schema } from '../../prelude/schema';
export type Param = {
validator: Context<any>;
@@ -29,7 +30,7 @@ export interface IEndpointMeta {
};
};
- res?: any;
+ res?: Schema;
/**
* このエンドポイントにリクエストするのにユーザー情報が必須か否か
diff --git a/src/server/api/endpoints/charts/notes.ts b/src/server/api/endpoints/charts/notes.ts
index d254bb854c..cc0ca8bef7 100644
--- a/src/server/api/endpoints/charts/notes.ts
+++ b/src/server/api/endpoints/charts/notes.ts
@@ -1,6 +1,7 @@
import $ from 'cafy';
import define from '../../define';
-import notesChart from '../../../../services/chart/notes';
+import notesChart, { notesLogSchema } from '../../../../services/chart/notes';
+import { convertLog } from '../../../../services/chart';
export const meta = {
stability: 'stable',
@@ -28,12 +29,7 @@ export const meta = {
},
},
- res: {
- type: 'array',
- items: {
- type: 'object',
- },
- },
+ res: convertLog(notesLogSchema),
};
export default define(meta, async (ps) => {
diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts
index a4f262bdad..7df86625d6 100644
--- a/src/server/api/endpoints/notes/create.ts
+++ b/src/server/api/endpoints/notes/create.ts
@@ -175,12 +175,10 @@ export const meta = {
res: {
type: 'object',
- props: {
+ properties: {
createdNote: {
type: 'Note',
- desc: {
- 'ja-JP': '作成した投稿'
- }
+ description: '作成した投稿'
}
}
},
diff --git a/src/server/api/openapi/gen-spec.ts b/src/server/api/openapi/gen-spec.ts
index ad46eb20a4..7487918231 100644
--- a/src/server/api/openapi/gen-spec.ts
+++ b/src/server/api/openapi/gen-spec.ts
@@ -4,6 +4,7 @@ import config from '../../../config';
import { errors as basicErrors } from './errors';
import { schemas } from './schemas';
import { description } from './description';
+import { convertOpenApiSchema } from '../../../prelude/schema';
export function genOpenapiSpec(lang = 'ja-JP') {
const spec = {
@@ -104,33 +105,7 @@ export function genOpenapiSpec(lang = 'ja-JP') {
const required = endpoint.meta.params ? Object.entries(endpoint.meta.params).filter(([k, v]) => !v.validator.isOptional).map(([k, v]) => k) : [];
- const resSchema = endpoint.meta.res ? renderType(endpoint.meta.res) : {};
-
- function renderType(x: any) {
- const res = {} as any;
-
- if (['User', 'Note', 'DriveFile'].includes(x.type)) {
- res['$ref'] = `#/components/schemas/${x.type}`;
- } else if (x.type === 'object') {
- res['type'] = 'object';
- if (x.props) {
- const props = {} as any;
- for (const kv of Object.entries(x.props)) {
- props[kv[0]] = renderType(kv[1]);
- }
- res['properties'] = props;
- }
- } else if (x.type === 'array') {
- res['type'] = 'array';
- if (x.items) {
- res['items'] = renderType(x.items);
- }
- } else {
- res['type'] = x.type;
- }
-
- return res;
- }
+ const resSchema = endpoint.meta.res ? convertOpenApiSchema(endpoint.meta.res) : {};
const info = {
operationId: endpoint.name,
diff --git a/src/services/chart/index.ts b/src/services/chart/index.ts
index 30ef2847d6..1e6ff0ca97 100644
--- a/src/services/chart/index.ts
+++ b/src/services/chart/index.ts
@@ -9,6 +9,7 @@ import * as mongo from 'mongodb';
import db from '../../db/mongodb';
import { ICollection } from 'monk';
import Logger from '../../misc/logger';
+import { Schema } from '../../prelude/schema';
const logger = new Logger('chart');
@@ -346,3 +347,18 @@ export default abstract class Chart<T extends Obj> {
return res;
}
}
+
+export function convertLog(logSchema: Schema): Schema {
+ const v: Schema = JSON.parse(JSON.stringify(logSchema)); // copy
+ if (v.type === 'number') {
+ v.type = 'array';
+ v.items = {
+ type: 'number'
+ };
+ } else if (v.type === 'object') {
+ for (const k of Object.keys(v.properties)) {
+ v.properties[k] = convertLog(v.properties[k]);
+ }
+ }
+ return v;
+}
diff --git a/src/services/chart/notes.ts b/src/services/chart/notes.ts
index 8f95f63638..d3704fed9a 100644
--- a/src/services/chart/notes.ts
+++ b/src/services/chart/notes.ts
@@ -2,48 +2,61 @@ import autobind from 'autobind-decorator';
import Chart, { Obj } from '.';
import Note, { INote } from '../../models/note';
import { isLocalUser } from '../../models/user';
+import { SchemaType } from '../../prelude/schema';
-/**
- * 投稿に関するチャート
- */
-type NotesLog = {
- local: {
- /**
- * 集計期間時点での、全投稿数
- */
- total: number;
+const logSchema = {
+ total: {
+ type: 'number' as 'number',
+ description: '集計期間時点での、全投稿数'
+ },
- /**
- * 増加した投稿数
- */
- inc: number;
+ inc: {
+ type: 'number' as 'number',
+ description: '増加した投稿数'
+ },
- /**
- * 減少した投稿数
- */
- dec: number;
+ dec: {
+ type: 'number' as 'number',
+ description: '減少した投稿数'
+ },
- diffs: {
- /**
- * 通常の投稿数の差分
- */
- normal: number;
+ diffs: {
+ type: 'object' as 'object',
+ properties: {
+ normal: {
+ type: 'number' as 'number',
+ description: '通常の投稿数の差分'
+ },
- /**
- * リプライの投稿数の差分
- */
- reply: number;
+ reply: {
+ type: 'number' as 'number',
+ description: 'リプライの投稿数の差分'
+ },
- /**
- * Renoteの投稿数の差分
- */
- renote: number;
- };
- };
+ renote: {
+ type: 'number' as 'number',
+ description: 'Renoteの投稿数の差分'
+ },
+ }
+ },
+};
- remote: NotesLog['local'];
+export const notesLogSchema = {
+ type: 'object' as 'object',
+ properties: {
+ local: {
+ type: 'object' as 'object',
+ properties: logSchema
+ },
+ remote: {
+ type: 'object' as 'object',
+ properties: logSchema
+ },
+ }
};
+type NotesLog = SchemaType<typeof notesLogSchema>;
+
class NotesChart extends Chart<NotesLog> {
constructor() {
super('notes');