summaryrefslogtreecommitdiff
path: root/packages/backend/src/misc
diff options
context:
space:
mode:
Diffstat (limited to 'packages/backend/src/misc')
-rw-r--r--packages/backend/src/misc/cache.ts1
-rw-r--r--packages/backend/src/misc/cafy-id.ts33
-rw-r--r--packages/backend/src/misc/create-temp.ts13
-rw-r--r--packages/backend/src/misc/fetch-meta.ts13
-rw-r--r--packages/backend/src/misc/fetch.ts10
-rw-r--r--packages/backend/src/misc/get-ip-hash.ts9
-rw-r--r--packages/backend/src/misc/populate-emojis.ts2
-rw-r--r--packages/backend/src/misc/schema.ts37
8 files changed, 58 insertions, 60 deletions
diff --git a/packages/backend/src/misc/cache.ts b/packages/backend/src/misc/cache.ts
index 01bbe98a85..e5b911ed32 100644
--- a/packages/backend/src/misc/cache.ts
+++ b/packages/backend/src/misc/cache.ts
@@ -48,6 +48,7 @@ export class Cache<T> {
// Cache MISS
const value = await fetcher();
+ this.set(key, value);
return value;
}
diff --git a/packages/backend/src/misc/cafy-id.ts b/packages/backend/src/misc/cafy-id.ts
deleted file mode 100644
index dd81c5c4cf..0000000000
--- a/packages/backend/src/misc/cafy-id.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { Context } from 'cafy';
-
-// eslint-disable-next-line @typescript-eslint/ban-types
-export class ID<Maybe = string> extends Context<string | (Maybe extends {} ? string : Maybe)> {
- public readonly name = 'ID';
-
- constructor(optional = false, nullable = false) {
- super(optional, nullable);
-
- this.push((v: any) => {
- if (typeof v !== 'string') {
- return new Error('must-be-an-id');
- }
- return true;
- });
- }
-
- public getType() {
- return super.getType('String');
- }
-
- public makeOptional(): ID<undefined> {
- return new ID(true, false);
- }
-
- public makeNullable(): ID<null> {
- return new ID(false, true);
- }
-
- public makeOptionalNullable(): ID<undefined | null> {
- return new ID(true, true);
- }
-}
diff --git a/packages/backend/src/misc/create-temp.ts b/packages/backend/src/misc/create-temp.ts
index 04604cf7d0..f07be634fb 100644
--- a/packages/backend/src/misc/create-temp.ts
+++ b/packages/backend/src/misc/create-temp.ts
@@ -1,10 +1,19 @@
import * as tmp from 'tmp';
-export function createTemp(): Promise<[string, any]> {
- return new Promise<[string, any]>((res, rej) => {
+export function createTemp(): Promise<[string, () => void]> {
+ return new Promise<[string, () => void]>((res, rej) => {
tmp.file((e, path, fd, cleanup) => {
if (e) return rej(e);
res([path, cleanup]);
});
});
}
+
+export function createTempDir(): Promise<[string, () => void]> {
+ return new Promise<[string, () => void]>((res, rej) => {
+ tmp.dir((e, path, cleanup) => {
+ if (e) return rej(e);
+ res([path, cleanup]);
+ });
+ });
+}
diff --git a/packages/backend/src/misc/fetch-meta.ts b/packages/backend/src/misc/fetch-meta.ts
index 5417c10962..e855ac28ee 100644
--- a/packages/backend/src/misc/fetch-meta.ts
+++ b/packages/backend/src/misc/fetch-meta.ts
@@ -20,9 +20,16 @@ export async function fetchMeta(noCache = false): Promise<Meta> {
cache = meta;
return meta;
} else {
- const saved = await transactionalEntityManager.save(Meta, {
- id: 'x',
- }) as Meta;
+ // metaが空のときfetchMetaが同時に呼ばれるとここが同時に呼ばれてしまうことがあるのでフェイルセーフなupsertを使う
+ const saved = await transactionalEntityManager
+ .upsert(
+ Meta,
+ {
+ id: 'x',
+ },
+ ['id'],
+ )
+ .then((x) => transactionalEntityManager.findOneByOrFail(Meta, x.identifiers[0]));
cache = saved;
return saved;
diff --git a/packages/backend/src/misc/fetch.ts b/packages/backend/src/misc/fetch.ts
index 4b1013c9f5..af6bf2fca7 100644
--- a/packages/backend/src/misc/fetch.ts
+++ b/packages/backend/src/misc/fetch.ts
@@ -1,10 +1,10 @@
-import * as http from 'http';
-import * as https from 'https';
+import * as http from 'node:http';
+import * as https from 'node:https';
+import { URL } from 'node:url';
import CacheableLookup from 'cacheable-lookup';
import fetch from 'node-fetch';
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
import config from '@/config/index.js';
-import { URL } from 'node:url';
export async function getJson(url: string, accept = 'application/json, */*', timeout = 10000, headers?: Record<string, string>) {
const res = await getResponse({
@@ -35,7 +35,7 @@ export async function getHtml(url: string, accept = 'text/html, */*', timeout =
}
export async function getResponse(args: { url: string, method: string, body?: string, headers: Record<string, string>, timeout?: number, size?: number }) {
- const timeout = args?.timeout || 10 * 1000;
+ const timeout = args.timeout || 10 * 1000;
const controller = new AbortController();
setTimeout(() => {
@@ -47,7 +47,7 @@ export async function getResponse(args: { url: string, method: string, body?: st
headers: args.headers,
body: args.body,
timeout,
- size: args?.size || 10 * 1024 * 1024,
+ size: args.size || 10 * 1024 * 1024,
agent: getAgentByUrl,
signal: controller.signal,
});
diff --git a/packages/backend/src/misc/get-ip-hash.ts b/packages/backend/src/misc/get-ip-hash.ts
new file mode 100644
index 0000000000..379325bb13
--- /dev/null
+++ b/packages/backend/src/misc/get-ip-hash.ts
@@ -0,0 +1,9 @@
+import IPCIDR from 'ip-cidr';
+
+export function getIpHash(ip: string) {
+ // because a single person may control many IPv6 addresses,
+ // only a /64 subnet prefix of any IP will be taken into account.
+ // (this means for IPv4 the entire address is used)
+ const prefix = IPCIDR.createAddress(ip).mask(64);
+ return 'ip-' + BigInt('0b' + prefix).toString(36);
+}
diff --git a/packages/backend/src/misc/populate-emojis.ts b/packages/backend/src/misc/populate-emojis.ts
index 86f1356c31..6a185d09f6 100644
--- a/packages/backend/src/misc/populate-emojis.ts
+++ b/packages/backend/src/misc/populate-emojis.ts
@@ -63,7 +63,7 @@ export async function populateEmoji(emojiName: string, noteUserHost: string | nu
const isLocal = emoji.host == null;
const emojiUrl = emoji.publicUrl || emoji.originalUrl; // || emoji.originalUrl してるのは後方互換性のため
- const url = isLocal ? emojiUrl : `${config.url}/proxy/image.png?${query({ url: emojiUrl })}`;
+ const url = isLocal ? emojiUrl : `${config.url}/proxy/${encodeURIComponent((new URL(emojiUrl)).pathname)}?${query({ url: emojiUrl })}`;
return {
name: emojiName,
diff --git a/packages/backend/src/misc/schema.ts b/packages/backend/src/misc/schema.ts
index 5b69812090..fdecc278d4 100644
--- a/packages/backend/src/misc/schema.ts
+++ b/packages/backend/src/misc/schema.ts
@@ -89,7 +89,7 @@ export interface Schema extends OfSchema {
readonly optional?: boolean;
readonly items?: Schema;
readonly properties?: Obj;
- readonly required?: ReadonlyArray<keyof NonNullable<this['properties']>>;
+ readonly required?: ReadonlyArray<Extract<keyof NonNullable<this['properties']>, string>>;
readonly description?: string;
readonly example?: any;
readonly format?: string;
@@ -98,6 +98,9 @@ export interface Schema extends OfSchema {
readonly default?: (this['type'] extends TypeStringef ? StringDefToType<this['type']> : any) | null;
readonly maxLength?: number;
readonly minLength?: number;
+ readonly maximum?: number;
+ readonly minimum?: number;
+ readonly pattern?: string;
}
type RequiredPropertyNames<s extends Obj> = {
@@ -105,24 +108,26 @@ type RequiredPropertyNames<s extends Obj> = {
// K is not optional
s[K]['optional'] extends false ? K :
// K has default value
- s[K]['default'] extends null | string | number | boolean | Record<string, unknown> ? K : never
+ s[K]['default'] extends null | string | number | boolean | Record<string, unknown> ? K :
+ never
}[keyof s];
-export interface Obj { [key: string]: Schema; }
+export type Obj = Record<string, Schema>;
+// https://github.com/misskey-dev/misskey/issues/8535
+// To avoid excessive stack depth error,
+// deceive TypeScript with UnionToIntersection (or more precisely, `infer` expression within it).
export type ObjType<s extends Obj, RequiredProps extends keyof s> =
- { -readonly [P in keyof s]?: SchemaType<s[P]> } &
- { -readonly [P in RequiredProps]: SchemaType<s[P]> } &
- { -readonly [P in RequiredPropertyNames<s>]: SchemaType<s[P]> };
+ UnionToIntersection<
+ { -readonly [R in RequiredPropertyNames<s>]-?: SchemaType<s[R]> } &
+ { -readonly [R in RequiredProps]-?: SchemaType<s[R]> } &
+ { -readonly [P in keyof s]?: SchemaType<s[P]> }
+ >;
type NullOrUndefined<p extends Schema, T> =
- p['nullable'] extends true
- ? p['optional'] extends true
- ? (T | null | undefined)
- : (T | null)
- : p['optional'] extends true
- ? (T | undefined)
- : T;
+ | (p['nullable'] extends true ? null : never)
+ | (p['optional'] extends true ? undefined : never)
+ | T;
// https://stackoverflow.com/questions/54938141/typescript-convert-union-to-intersection
// Get intersection from union
@@ -139,9 +144,9 @@ export type SchemaTypeDef<p extends Schema> =
p['type'] extends 'number' ? number :
p['type'] extends 'string' ? (
p['enum'] extends readonly string[] ?
- p['enum'][number] :
- p['format'] extends 'date-time' ? string : // Dateにする??
- string
+ p['enum'][number] :
+ p['format'] extends 'date-time' ? string : // Dateにする??
+ string
) :
p['type'] extends 'boolean' ? boolean :
p['type'] extends 'object' ? (