summaryrefslogtreecommitdiff
path: root/packages/backend
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2022-04-28 11:00:06 +0900
committerGitHub <noreply@github.com>2022-04-28 11:00:06 +0900
commit25e82283810325703716231a87704c964bbed2d4 (patch)
tree97e3ab46ff0af7e5d2f9534434072f1f555cd1e5 /packages/backend
parentローカルのjsonファイルを保存・読み込みできるように (diff)
parentfix(client): fix lint issues in autocomplete (#8548) (diff)
downloadmisskey-25e82283810325703716231a87704c964bbed2d4.tar.gz
misskey-25e82283810325703716231a87704c964bbed2d4.tar.bz2
misskey-25e82283810325703716231a87704c964bbed2d4.zip
Merge branch 'develop' into preferences-registry
Diffstat (limited to 'packages/backend')
-rw-r--r--packages/backend/package.json39
-rw-r--r--packages/backend/src/@types/jsrsasign.d.ts800
-rw-r--r--packages/backend/src/boot/index.ts4
-rw-r--r--packages/backend/src/daemons/queue-stats.ts4
-rw-r--r--packages/backend/src/daemons/server-stats.ts4
-rw-r--r--packages/backend/src/misc/cafy-id.ts33
-rw-r--r--packages/backend/src/misc/schema.ts37
-rw-r--r--packages/backend/src/models/entities/user.ts4
-rw-r--r--packages/backend/src/models/repositories/drive-file.ts47
-rw-r--r--packages/backend/src/models/repositories/page.ts6
-rw-r--r--packages/backend/src/models/repositories/user.ts28
-rw-r--r--packages/backend/src/remote/activitypub/kernel/move/index.ts0
-rw-r--r--packages/backend/src/remote/activitypub/models/mention.ts8
-rw-r--r--packages/backend/src/remote/activitypub/models/person.ts36
-rw-r--r--packages/backend/src/remote/activitypub/renderer/flag.ts2
-rw-r--r--packages/backend/src/remote/activitypub/renderer/note.ts16
-rw-r--r--packages/backend/src/remote/activitypub/resolver.ts10
-rw-r--r--packages/backend/src/remote/activitypub/type.ts6
-rw-r--r--packages/backend/src/server/activitypub/followers.ts24
-rw-r--r--packages/backend/src/server/activitypub/following.ts21
-rw-r--r--packages/backend/src/server/activitypub/outbox.ts37
-rw-r--r--packages/backend/src/server/api/2fa.ts4
-rw-r--r--packages/backend/src/server/api/common/signin.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/announcements/list.ts19
-rw-r--r--packages/backend/src/server/api/endpoints/admin/show-users.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/antennas/notes.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/clips/notes.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/drive/files/show.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/notes/create.ts22
-rw-r--r--packages/backend/src/server/api/endpoints/notes/reactions.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/notes/translate.ts15
-rw-r--r--packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/pages/show.ts8
-rw-r--r--packages/backend/src/server/api/service/discord.ts30
-rw-r--r--packages/backend/src/server/api/service/github.ts30
-rw-r--r--packages/backend/src/server/api/service/twitter.ts20
-rw-r--r--packages/backend/src/server/api/stream/channels/queue-stats.ts4
-rw-r--r--packages/backend/src/server/api/stream/channels/server-stats.ts4
-rw-r--r--packages/backend/src/server/api/stream/index.ts42
-rw-r--r--packages/backend/src/server/index.ts20
-rw-r--r--packages/backend/src/server/web/feed.ts6
-rw-r--r--packages/backend/src/server/web/index.ts30
-rw-r--r--packages/backend/src/server/web/manifest.ts12
-rw-r--r--packages/backend/src/server/web/views/clip.pug2
-rw-r--r--packages/backend/src/server/web/views/note.pug2
-rw-r--r--packages/backend/src/server/web/views/page.pug2
-rw-r--r--packages/backend/src/server/web/views/user.pug3
-rw-r--r--packages/backend/src/services/blocking/create.ts17
-rw-r--r--packages/backend/src/services/following/create.ts6
-rw-r--r--packages/backend/src/services/following/delete.ts11
-rw-r--r--packages/backend/src/services/note/delete.ts8
-rw-r--r--packages/backend/src/services/relay.ts2
-rw-r--r--packages/backend/tsconfig.json7
-rw-r--r--packages/backend/yarn.lock340
55 files changed, 541 insertions, 1339 deletions
diff --git a/packages/backend/package.json b/packages/backend/package.json
index 7fe3757eb3..5950cd23ff 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -14,6 +14,7 @@
"lodash": "^4.17.21"
},
"dependencies": {
+ "@bull-board/koa": "3.10.4",
"@discordapp/twemoji": "13.1.1",
"@elastic/elasticsearch": "7.11.0",
"@koa/cors": "3.1.0",
@@ -21,21 +22,19 @@
"@koa/router": "9.0.1",
"@sinonjs/fake-timers": "9.1.1",
"@syuilo/aiscript": "0.11.1",
- "@typescript-eslint/eslint-plugin": "5.18.0",
- "@typescript-eslint/parser": "5.18.0",
- "@bull-board/koa": "3.10.3",
+ "@typescript-eslint/eslint-plugin": "5.20.0",
+ "@typescript-eslint/parser": "5.20.0",
"abort-controller": "3.0.0",
"ajv": "8.11.0",
- "archiver": "5.3.0",
+ "archiver": "5.3.1",
"autobind-decorator": "2.4.0",
"autwh": "0.1.0",
- "aws-sdk": "2.1111.0",
+ "aws-sdk": "2.1120.0",
"bcryptjs": "2.4.3",
"blurhash": "1.1.5",
- "broadcast-channel": "4.10.0",
- "bull": "4.8.1",
+ "broadcast-channel": "4.11.0",
+ "bull": "4.8.2",
"cacheable-lookup": "6.0.4",
- "cafy": "15.2.1",
"cbor": "8.1.0",
"chalk": "5.0.1",
"chalk-template": "0.4.0",
@@ -45,7 +44,7 @@
"date-fns": "2.28.0",
"deep-email-validator": "0.1.21",
"escape-regexp": "0.0.1",
- "eslint": "8.13.0",
+ "eslint": "8.14.0",
"eslint-plugin-import": "2.26.0",
"feed": "4.2.2",
"file-type": "17.1.1",
@@ -53,14 +52,14 @@
"got": "12.0.3",
"hpagent": "0.1.2",
"http-signature": "1.3.6",
- "ip-cidr": "3.0.4",
+ "ip-cidr": "3.0.7",
"is-svg": "4.3.2",
"js-yaml": "4.1.0",
"jsdom": "19.0.0",
"json5": "2.2.1",
"json5-loader": "4.0.1",
"jsonld": "5.2.0",
- "jsrsasign": "8.0.20",
+ "jsrsasign": "10.5.19",
"koa": "2.13.4",
"koa-bodyparser": "4.3.0",
"koa-favicon": "2.1.0",
@@ -101,15 +100,15 @@
"rndstr": "1.0.0",
"s-age": "1.1.2",
"sanitize-html": "2.7.0",
- "semver": "7.3.6",
- "sharp": "0.30.3",
+ "semver": "7.3.7",
+ "sharp": "0.30.4",
"speakeasy": "2.0.0",
"strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0",
"style-loader": "3.3.1",
"summaly": "2.5.0",
"syslog-pro": "1.0.0",
- "systeminformation": "5.11.9",
+ "systeminformation": "5.11.14",
"tinycolor2": "1.4.2",
"tmp": "0.2.1",
"ts-loader": "9.2.8",
@@ -117,7 +116,7 @@
"tsc-alias": "1.4.1",
"tsconfig-paths": "3.14.1",
"twemoji-parser": "14.0.0",
- "typeorm": "0.3.5",
+ "typeorm": "0.3.6",
"typescript": "4.6.3",
"ulid": "2.3.0",
"unzipper": "0.10.11",
@@ -125,10 +124,11 @@
"web-push": "3.4.5",
"websocket": "1.0.34",
"ws": "8.5.0",
- "xev": "2.0.1"
+ "xev": "3.0.2"
},
"devDependencies": {
"@redocly/openapi-core": "1.0.0-beta.93",
+ "@types/semver": "7.3.9",
"@types/bcryptjs": "2.4.2",
"@types/bull": "3.15.8",
"@types/cbor": "6.0.0",
@@ -138,6 +138,7 @@
"@types/js-yaml": "4.0.5",
"@types/jsdom": "16.2.14",
"@types/jsonld": "1.5.6",
+ "@types/jsrsasign": "10.2.1",
"@types/koa": "2.13.4",
"@types/koa-bodyparser": "4.3.7",
"@types/koa-cors": "0.0.2",
@@ -149,8 +150,8 @@
"@types/koa__cors": "3.1.1",
"@types/koa__multer": "2.0.4",
"@types/koa__router": "8.0.11",
- "@types/mocha": "9.1.0",
- "@types/node": "17.0.23",
+ "@types/mocha": "9.1.1",
+ "@types/node": "17.0.25",
"@types/node-fetch": "3.0.3",
"@types/nodemailer": "6.4.4",
"@types/oauth": "0.9.1",
@@ -164,7 +165,7 @@
"@types/redis": "4.0.11",
"@types/rename": "1.0.4",
"@types/sanitize-html": "2.6.2",
- "@types/sharp": "0.30.1",
+ "@types/sharp": "0.30.2",
"@types/sinonjs__fake-timers": "8.1.2",
"@types/speakeasy": "2.0.7",
"@types/tinycolor2": "1.4.3",
diff --git a/packages/backend/src/@types/jsrsasign.d.ts b/packages/backend/src/@types/jsrsasign.d.ts
deleted file mode 100644
index bb52f8f64e..0000000000
--- a/packages/backend/src/@types/jsrsasign.d.ts
+++ /dev/null
@@ -1,800 +0,0 @@
-// Attention: Partial Type Definition
-
-declare module 'jsrsasign' {
- //// HELPER TYPES
-
- /**
- * Attention: The value might be changed by the function.
- */
- type Mutable<T> = T;
-
- /**
- * Deprecated: The function might be deleted in future release.
- */
- type Deprecated<T> = T;
-
- //// COMMON TYPES
-
- /**
- * byte number
- */
- type ByteNumber = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255;
-
- /**
- * hexadecimal string /[0-9A-F]/
- */
- type HexString = string;
-
- /**
- * binary string /[01]/
- */
- type BinString = string;
-
- /**
- * base64 string /[A-Za-z0-9+/]=+/
- */
- type Base64String = string;
-
- /**
- * base64 URL encoded string /[A-Za-z0-9_-]/
- */
- type Base64URLString = string;
-
- /**
- * time value (ex. "151231235959Z")
- */
- type TimeValue = string;
-
- /**
- * OID string (ex. '1.2.3.4.567')
- */
- type OID = string;
-
- /**
- * OID name
- */
- type OIDName = string;
-
- /**
- * PEM formatted string
- */
- type PEM = string;
-
- //// ASN1 TYPES
-
- class ASN1Object {
- public isModified: boolean;
-
- public hTLV: ASN1TLV;
-
- public hT: ASN1T;
-
- public hL: ASN1L;
-
- public hV: ASN1V;
-
- public getLengthHexFromValue(): HexString;
-
- public getEncodedHex(): ASN1TLV;
-
- public getValueHex(): ASN1V;
-
- public getFreshValueHex(): ASN1V;
- }
-
- class DERAbstractStructured extends ASN1Object {
- constructor(params?: Partial<Record<'array', ASN1Object[]>>);
-
- public setByASN1ObjectArray(asn1ObjectArray: ASN1Object[]): void;
-
- public appendASN1Object(asn1Object: ASN1Object): void;
- }
-
- class DERSequence extends DERAbstractStructured {
- constructor(params?: Partial<Record<'array', ASN1Object[]>>);
-
- public getFreshValueHex(): ASN1V;
- }
-
- //// ASN1HEX TYPES
-
- /**
- * ASN.1 DER encoded data (hexadecimal string)
- */
- type ASN1S = HexString;
-
- /**
- * index of something
- */
- type Idx<T extends { [idx: string]: unknown } | { [idx: number]: unknown }> = ASN1S extends { [idx: string]: unknown } ? string : ASN1S extends { [idx: number]: unknown } ? number : never;
-
- /**
- * byte length of something
- */
- type ByteLength<T extends { length: unknown }> = T['length'];
-
- /**
- * ASN.1 L(length) (hexadecimal string)
- */
- type ASN1L = HexString;
-
- /**
- * ASN.1 T(tag) (hexadecimal string)
- */
- type ASN1T = HexString;
-
- /**
- * ASN.1 V(value) (hexadecimal string)
- */
- type ASN1V = HexString;
-
- /**
- * ASN.1 TLV (hexadecimal string)
- */
- type ASN1TLV = HexString;
-
- /**
- * ASN.1 object string
- */
- type ASN1ObjectString = string;
-
- /**
- * nth
- */
- type Nth = number;
-
- /**
- * ASN.1 DER encoded OID value (hexadecimal string)
- */
- type ASN1OIDV = HexString;
-
- class ASN1HEX {
- public static getLblen(s: ASN1S, idx: Idx<ASN1S>): ByteLength<ASN1L>;
-
- public static getL(s: ASN1S, idx: Idx<ASN1S>): ASN1L;
-
- public static getVblen(s: ASN1S, idx: Idx<ASN1S>): ByteLength<ASN1V>;
-
- public static getVidx(s: ASN1S, idx: Idx<ASN1S>): Idx<ASN1V>;
-
- public static getV(s: ASN1S, idx: Idx<ASN1S>): ASN1V;
-
- public static getTLV(s: ASN1S, idx: Idx<ASN1S>): ASN1TLV;
-
- public static getNextSiblingIdx(s: ASN1S, idx: Idx<ASN1S>): Idx<ASN1ObjectString>;
-
- public static getChildIdx(h: ASN1S, pos: Idx<ASN1S>): Idx<ASN1ObjectString>[];
-
- public static getNthChildIdx(h: ASN1S, idx: Idx<ASN1S>, nth: Nth): Idx<ASN1ObjectString>;
-
- public static getIdxbyList(h: ASN1S, currentIndex: Idx<ASN1ObjectString>, nthList: Mutable<Nth[]>, checkingTag?: string): Idx<Mutable<Nth[]>>;
-
- public static getTLVbyList(h: ASN1S, currentIndex: Idx<ASN1ObjectString>, nthList: Mutable<Nth[]>, checkingTag?: string): ASN1TLV;
-
- // eslint:disable-next-line:bool-param-default
- public static getVbyList(h: ASN1S, currentIndex: Idx<ASN1ObjectString>, nthList: Mutable<Nth[]>, checkingTag?: string, removeUnusedbits?: boolean): ASN1V;
-
- public static hextooidstr(hex: ASN1OIDV): OID;
-
- public static dump(hexOrObj: ASN1S | ASN1Object, flags?: Record<string, unknown>, idx?: Idx<ASN1S>, indent?: string): string;
-
- public static isASN1HEX(hex: string): hex is HexString;
-
- public static oidname(oidDotOrHex: OID | ASN1OIDV): OIDName;
- }
-
- //// BIG INTEGER TYPES (PARTIAL)
-
- class BigInteger {
- constructor(a: null);
-
- constructor(a: number, b: SecureRandom);
-
- constructor(a: number, b: number, c: SecureRandom);
-
- constructor(a: unknown);
-
- constructor(a: string, b: number);
-
- public am(i: number, x: number, w: number, j: number, c: number, n: number): number;
-
- public DB: number;
-
- public DM: number;
-
- public DV: number;
-
- public FV: number;
-
- public F1: number;
-
- public F2: number;
-
- protected copyTo(r: Mutable<BigInteger>): void;
-
- protected fromInt(x: number): void;
-
- protected fromString(s: string, b: number): void;
-
- protected clamp(): void;
-
- public toString(b: number): string;
-
- public negate(): BigInteger;
-
- public abs(): BigInteger;
-
- public compareTo(a: BigInteger): number;
-
- public bitLength(): number;
-
- protected dlShiftTo(n: number, r: Mutable<BigInteger>): void;
-
- protected drShiftTo(n: number, r: Mutable<BigInteger>): void;
-
- protected lShiftTo(n: number, r: Mutable<BigInteger>): void;
-
- protected rShiftTo(n: number, r: Mutable<BigInteger>): void;
-
- protected subTo(a: BigInteger, r: Mutable<BigInteger>): void;
-
- protected multiplyTo(a: BigInteger, r: Mutable<BigInteger>): void;
-
- protected squareTo(r: Mutable<BigInteger>): void;
-
- protected divRemTo(m: BigInteger, q: Mutable<BigInteger>, r: Mutable<BigInteger>): void;
-
- public mod(a: BigInteger): BigInteger;
-
- protected invDigit(): number;
-
- protected isEven(): boolean;
-
- protected exp(e: number, z: Classic | Montgomery): BigInteger;
-
- public modPowInt(e: number, m: BigInteger): BigInteger;
-
- public static ZERO: BigInteger;
-
- public static ONE: BigInteger;
- }
-
- class Classic {
- constructor(m: BigInteger);
-
- public convert(x: BigInteger): BigInteger;
-
- public revert(x: BigInteger): BigInteger;
-
- public reduce(x: Mutable<BigInteger>): void;
-
- public mulTo(x: BigInteger, r: Mutable<BigInteger>): void;
-
- public sqrTo(x: BigInteger, y: BigInteger, r: Mutable<BigInteger>): void;
- }
-
- class Montgomery {
- constructor(m: BigInteger);
-
- public convert(x: BigInteger): BigInteger;
-
- public revert(x: BigInteger): BigInteger;
-
- public reduce(x: Mutable<BigInteger>): void;
-
- public mulTo(x: BigInteger, r: Mutable<BigInteger>): void;
-
- public sqrTo(x: BigInteger, y: BigInteger, r: Mutable<BigInteger>): void;
- }
-
- //// KEYUTIL TYPES
-
- type DecryptAES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
-
- type Decrypt3DES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
-
- type DecryptDES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
-
- type EncryptAES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
-
- type Encrypt3DES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
-
- type EncryptDES = (dataHex: HexString, keyHex: HexString, ivHex: HexString) => HexString;
-
- type AlgList = {
- 'AES-256-CBC': { 'proc': DecryptAES; 'eproc': EncryptAES; keylen: 32; ivlen: 16; };
- 'AES-192-CBC': { 'proc': DecryptAES; 'eproc': EncryptAES; keylen: 24; ivlen: 16; };
- 'AES-128-CBC': { 'proc': DecryptAES; 'eproc': EncryptAES; keylen: 16; ivlen: 16; };
- 'DES-EDE3-CBC': { 'proc': Decrypt3DES; 'eproc': Encrypt3DES; keylen: 24; ivlen: 8; };
- 'DES-CBC': { 'proc': DecryptDES; 'eproc': EncryptDES; keylen: 8; ivlen: 8; };
- };
-
- type AlgName = keyof AlgList;
-
- type PEMHeadAlgName = 'RSA' | 'EC' | 'DSA';
-
- type GetKeyRSAParam = RSAKey | {
- n: BigInteger;
- e: number;
- } | Record<'n' | 'e', HexString> | Record<'n' | 'e', HexString> & Record<'d' | 'p' | 'q' | 'dp' | 'dq' | 'co', HexString | null> | {
- n: BigInteger;
- e: number;
- d: BigInteger;
- } | {
- kty: 'RSA';
- } & Record<'n' | 'e', Base64URLString> | {
- kty: 'RSA';
- } & Record<'n' | 'e' | 'd' | 'p' | 'q' | 'dp' | 'dq' | 'qi', Base64URLString> | {
- kty: 'RSA';
- } & Record<'n' | 'e' | 'd', Base64URLString>;
-
- type GetKeyECDSAParam = KJUR.crypto.ECDSA | {
- curve: KJUR.crypto.CurveName;
- xy: HexString;
- } | {
- curve: KJUR.crypto.CurveName;
- d: HexString;
- } | {
- kty: 'EC';
- crv: KJUR.crypto.CurveName;
- x: Base64URLString;
- y: Base64URLString;
- } | {
- kty: 'EC';
- crv: KJUR.crypto.CurveName;
- x: Base64URLString;
- y: Base64URLString;
- d: Base64URLString;
- };
-
- type GetKeyDSAParam = KJUR.crypto.DSA | Record<'p' | 'q' | 'g', BigInteger> & Record<'y', BigInteger | null> | Record<'p' | 'q' | 'g' | 'x', BigInteger> & Record<'y', BigInteger | null>;
-
- type GetKeyParam = GetKeyRSAParam | GetKeyECDSAParam | GetKeyDSAParam | string;
-
- class KEYUTIL {
- public version: '1.0.0';
-
- public parsePKCS5PEM(sPKCS5PEM: PEM): Partial<Record<'type' | 's', string>> & (Record<'cipher' | 'ivsalt', string> | Record<'cipher' | 'ivsalt', undefined>);
-
- public getKeyAndUnusedIvByPasscodeAndIvsalt(algName: AlgName, passcode: string, ivsaltHex: HexString): Record<'keyhex' | 'ivhex', HexString>;
-
- public decryptKeyB64(privateKeyB64: Base64String, sharedKeyAlgName: AlgName, sharedKeyHex: HexString, ivsaltHex: HexString): Base64String;
-
- public getDecryptedKeyHex(sEncryptedPEM: PEM, passcode: string): HexString;
-
- public getEncryptedPKCS5PEMFromPrvKeyHex(pemHeadAlg: PEMHeadAlgName, hPrvKey: string, passcode: string, sharedKeyAlgName?: AlgName | null, ivsaltHex?: HexString | null): PEM;
-
- public parseHexOfEncryptedPKCS8(sHEX: HexString): {
- ciphertext: ASN1V;
- encryptionSchemeAlg: 'TripleDES';
- encryptionSchemeIV: ASN1V;
- pbkdf2Salt: ASN1V;
- pbkdf2Iter: number;
- };
-
- public getPBKDF2KeyHexFromParam(info: ReturnType<this['parseHexOfEncryptedPKCS8']>, passcode: string): HexString;
-
- private _getPlainPKCS8HexFromEncryptedPKCS8PEM(pkcs8PEM: PEM, passcode: string): HexString;
-
- public getKeyFromEncryptedPKCS8PEM(prvKeyHex: HexString): ReturnType<this['getKeyFromPlainPrivatePKCS8Hex']>;
-
- public parsePlainPrivatePKCS8Hex(pkcs8PrvHex: HexString): {
- algparam: ASN1V | null;
- algoid: ASN1V;
- keyidx: Idx<ASN1V>;
- };
-
- public getKeyFromPlainPrivatePKCS8PEM(prvKeyHex: HexString): ReturnType<this['getKeyFromPlainPrivatePKCS8Hex']>;
-
- public getKeyFromPlainPrivatePKCS8Hex(prvKeyHex: HexString): RSAKey | KJUR.crypto.DSA | KJUR.crypto.ECDSA;
-
- private _getKeyFromPublicPKCS8Hex(h: HexString): RSAKey | KJUR.crypto.DSA | KJUR.crypto.ECDSA;
-
- public parsePublicRawRSAKeyHex(pubRawRSAHex: HexString): Record<'n' | 'e', ASN1V>;
-
- public parsePublicPKCS8Hex(pkcs8PubHex: HexString): {
- algparam: ASN1V | Record<'p' | 'q' | 'g', ASN1V> | null;
- algoid: ASN1V;
- key: ASN1V;
- };
-
- public static getKey(param: GetKeyRSAParam): RSAKey;
-
- public static getKey(param: GetKeyECDSAParam): KJUR.crypto.ECDSA;
-
- public static getKey(param: GetKeyDSAParam): KJUR.crypto.DSA;
-
- public static getKey(param: string, passcode?: string, hextype?: string): RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA;
-
- public static generateKeypair(alg: 'RSA', keylen: number): Record<'prvKeyObj' | 'pubKeyObj', RSAKey>;
-
- public static generateKeypair(alg: 'EC', curve: KJUR.crypto.CurveName): Record<'prvKeyObj' | 'pubKeyObj', KJUR.crypto.ECDSA>;
-
- public static getPEM(keyObjOrHex: RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA, formatType?: 'PKCS1PRV' | 'PKCS5PRV' | 'PKCS8PRV', passwd?: string, encAlg?: 'DES-CBC' | 'DES-EDE3-CBC' | 'AES-128-CBC' | 'AES-192-CBC' | 'AES-256-CBC', hexType?: string, ivsaltHex?: HexString): object; // To Do
-
- public static getKeyFromCSRPEM(csrPEM: PEM): RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA;
-
- public static getKeyFromCSRHex(csrHex: HexString): RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA;
-
- public static parseCSRHex(csrHex: HexString): Record<'p8pubkeyhex', ASN1TLV>;
-
- public static getJWKFromKey(keyObj: RSAKey): {
- kty: 'RSA';
- } & Record<'n' | 'e' | 'd' | 'p' | 'q' | 'dp' | 'dq' | 'qi', Base64URLString> | {
- kty: 'RSA';
- } & Record<'n' | 'e', Base64URLString>;
-
- public static getJWKFromKey(keyObj: KJUR.crypto.ECDSA): {
- kty: 'EC';
- crv: KJUR.crypto.CurveName;
- x: Base64URLString;
- y: Base64URLString;
- d: Base64URLString;
- } | {
- kty: 'EC';
- crv: KJUR.crypto.CurveName;
- x: Base64URLString;
- y: Base64URLString;
- };
- }
-
- //// KJUR NAMESPACE (PARTIAL)
-
- namespace KJUR {
- namespace crypto {
- type CurveName = 'secp128r1' | 'secp160k1' | 'secp160r1' | 'secp192k1' | 'secp192r1' | 'secp224r1' | 'secp256k1' | 'secp256r1' | 'secp384r1' | 'secp521r1';
-
- class DSA {
- public p: BigInteger | null;
-
- public q: BigInteger | null;
-
- public g: BigInteger | null;
-
- public y: BigInteger | null;
-
- public x: BigInteger | null;
-
- public type: 'DSA';
-
- public isPrivate: boolean;
-
- public isPublic: boolean;
-
- public setPrivate(p: BigInteger, q: BigInteger, g: BigInteger, y: BigInteger | null, x: BigInteger): void;
-
- public setPrivateHex(hP: HexString, hQ: HexString, hG: HexString, hY: HexString | null, hX: HexString): void;
-
- public setPublic(p: BigInteger, q: BigInteger, g: BigInteger, y: BigInteger): void;
-
- public setPublicHex(hP: HexString, hQ: HexString, hG: HexString, hY: HexString): void;
-
- public signWithMessageHash(sHashHex: HexString): HexString;
-
- public verifyWithMessageHash(sHashHex: HexString, hSigVal: HexString): boolean;
-
- public parseASN1Signature(hSigVal: HexString): [BigInteger, BigInteger];
-
- public readPKCS5PrvKeyHex(h: HexString): void;
-
- public readPKCS8PrvKeyHex(h: HexString): void;
-
- public readPKCS8PubKeyHex(h: HexString): void;
-
- public readCertPubKeyHex(h: HexString, nthPKI: number): void;
- }
-
- class ECDSA {
- constructor(params?: {
- curve?: CurveName;
- prv?: HexString;
- pub?: HexString;
- });
-
- public p: BigInteger | null;
-
- public q: BigInteger | null;
-
- public g: BigInteger | null;
-
- public y: BigInteger | null;
-
- public x: BigInteger | null;
-
- public type: 'EC';
-
- public isPrivate: boolean;
-
- public isPublic: boolean;
-
- public getBigRandom(limit: BigInteger): BigInteger;
-
- public setNamedCurve(curveName: CurveName): void;
-
- public setPrivateKeyHex(prvKeyHex: HexString): void;
-
- public setPublicKeyHex(pubKeyHex: HexString): void;
-
- public getPublicKeyXYHex(): Record<'x' | 'y', HexString>;
-
- public getShortNISTPCurveName(): 'P-256' | 'P-384' | null;
-
- public generateKeyPairHex(): Record<'ecprvhex' | 'ecpubhex', HexString>;
-
- public signWithMessageHash(hashHex: HexString): HexString;
-
- public signHex(hashHex: HexString, privHex: HexString): HexString;
-
- public verifyWithMessageHash(sHashHex: HexString, hSigVal: HexString): boolean;
-
- public parseASN1Signature(hSigVal: HexString): [BigInteger, BigInteger];
-
- public readPKCS5PrvKeyHex(h: HexString): void;
-
- public readPKCS8PrvKeyHex(h: HexString): void;
-
- public readPKCS8PubKeyHex(h: HexString): void;
-
- public readCertPubKeyHex(h: HexString, nthPKI: number): void;
-
- public static parseSigHex(sigHex: HexString): Record<'r' | 's', BigInteger>;
-
- public static parseSigHexInHexRS(sigHex: HexString): Record<'r' | 's', ASN1V>;
-
- public static asn1SigToConcatSig(asn1Sig: HexString): HexString;
-
- public static concatSigToASN1Sig(concatSig: HexString): ASN1TLV;
-
- public static hexRSSigToASN1Sig(hR: HexString, hS: HexString): ASN1TLV;
-
- public static biRSSigToASN1Sig(biR: BigInteger, biS: BigInteger): ASN1TLV;
-
- public static getName(s: CurveName | HexString): 'secp256r1' | 'secp256k1' | 'secp384r1' | null;
- }
-
- class Signature {
- constructor(params?: ({
- alg: string;
- prov?: string;
- } | {}) & ({
- psssaltlen: number;
- } | {}) & ({
- prvkeypem: PEM;
- prvkeypas?: never;
- } | {}));
-
- private _setAlgNames(): void;
-
- private _zeroPaddingOfSignature(hex: HexString, bitLength: number): HexString;
-
- public setAlgAndProvider(alg: string, prov: string): void;
-
- public init(key: GetKeyParam, pass?: string): void;
-
- public updateString(str: string): void;
-
- public updateHex(hex: HexString): void;
-
- public sign(): HexString;
-
- public signString(str: string): HexString;
-
- public signHex(hex: HexString): HexString;
-
- public verify(hSigVal: string): boolean | 0;
- }
- }
- }
-
- //// RSAKEY TYPES
-
- class RSAKey {
- public n: BigInteger | null;
-
- public e: number;
-
- public d: BigInteger | null;
-
- public p: BigInteger | null;
-
- public q: BigInteger | null;
-
- public dmp1: BigInteger | null;
-
- public dmq1: BigInteger | null;
-
- public coeff: BigInteger | null;
-
- public type: 'RSA';
-
- public isPrivate?: boolean;
-
- public isPublic?: boolean;
-
- //// RSA PUBLIC
-
- protected doPublic(x: BigInteger): BigInteger;
-
- public setPublic(N: BigInteger, E: number): void;
-
- public setPublic(N: HexString, E: HexString): void;
-
- public encrypt(text: string): HexString | null;
-
- public encryptOAEP(text: string, hash?: string | ((s: string) => string), hashLen?: number): HexString | null;
-
- //// RSA PRIVATE
-
- protected doPrivate(x: BigInteger): BigInteger;
-
- public setPrivate(N: BigInteger, E: number, D: BigInteger): void;
-
- public setPrivate(N: HexString, E: HexString, D: HexString): void;
-
- public setPrivateEx(N: HexString, E: HexString, D?: HexString | null, P?: HexString | null, Q?: HexString | null, DP?: HexString | null, DQ?: HexString | null, C?: HexString | null): void;
-
- public generate(B: number, E: HexString): void;
-
- public decrypt(ctext: HexString): string;
-
- public decryptOAEP(ctext: HexString, hash?: string | ((s: string) => string), hashLen?: number): string | null;
-
- //// RSA PEM
-
- public getPosArrayOfChildrenFromHex(hPrivateKey: PEM): Idx<ASN1ObjectString>[];
-
- public getHexValueArrayOfChildrenFromHex(hPrivateKey: PEM): Idx<ASN1ObjectString>[];
-
- public readPrivateKeyFromPEMString(keyPEM: PEM): void;
-
- public readPKCS5PrvKeyHex(h: HexString): void;
-
- public readPKCS8PrvKeyHex(h: HexString): void;
-
- public readPKCS5PubKeyHex(h: HexString): void;
-
- public readPKCS8PubKeyHex(h: HexString): void;
-
- public readCertPubKeyHex(h: HexString, nthPKI: Nth): void;
-
- //// RSA SIGN
-
- public sign(s: string, hashAlg: string): HexString;
-
- public signWithMessageHash(sHashHex: HexString, hashAlg: string): HexString;
-
- public signPSS(s: string, hashAlg: string, sLen: number): HexString;
-
- public signWithMessageHashPSS(hHash: HexString, hashAlg: string, sLen: number): HexString;
-
- public verify(sMsg: string, hSig: HexString): boolean | 0;
-
- public verifyWithMessageHash(sHashHex: HexString, hSig: HexString): boolean | 0;
-
- public verifyPSS(sMsg: string, hSig: HexString, hashAlg: string, sLen: number): boolean;
-
- public verifyWithMessageHashPSS(hHash: HexString, hSig: HexString, hashAlg: string, sLen: number): boolean;
-
- public static SALT_LEN_HLEN: -1;
-
- public static SALT_LEN_MAX: -2;
-
- public static SALT_LEN_RECOVER: -2;
- }
-
- /// RNG TYPES
- class SecureRandom {
- public nextBytes(ba: Mutable<ByteNumber[]>): void;
- }
-
- //// X509 TYPES
-
- type ExtInfo = {
- critical: boolean;
- oid: OID;
- vidx: Idx<ASN1V>;
- };
-
- type ExtAIAInfo = Record<'ocsp' | 'caissuer', string>;
-
- type ExtCertificatePolicy = {
- id: OIDName;
- } & Partial<{
- cps: string;
- } | {
- unotice: string;
- }>;
-
- class X509 {
- public hex: HexString | null;
-
- public version: number;
-
- public foffset: number;
-
- public aExtInfo: null;
-
- public getVersion(): number;
-
- public getSerialNumberHex(): ASN1V;
-
- public getSignatureAlgorithmField(): OIDName;
-
- public getIssuerHex(): ASN1TLV;
-
- public getIssuerString(): HexString;
-
- public getSubjectHex(): ASN1TLV;
-
- public getSubjectString(): HexString;
-
- public getNotBefore(): TimeValue;
-
- public getNotAfter(): TimeValue;
-
- public getPublicKeyHex(): ASN1TLV;
-
- public getPublicKeyIdx(): Idx<Mutable<Nth[]>>;
-
- public getPublicKeyContentIdx(): Idx<Mutable<Nth[]>>;
-
- public getPublicKey(): RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA;
-
- public getSignatureAlgorithmName(): OIDName;
-
- public getSignatureValueHex(): ASN1V;
-
- public verifySignature(pubKey: GetKeyParam): boolean | 0;
-
- public parseExt(): void;
-
- public getExtInfo(oidOrName: OID | string): ExtInfo | undefined;
-
- public getExtBasicConstraints(): ExtInfo | {} | {
- cA: true;
- pathLen?: number;
- };
-
- public getExtKeyUsageBin(): BinString;
-
- public getExtKeyUsageString(): string;
-
- public getExtSubjectKeyIdentifier(): ASN1V | undefined;
-
- public getExtAuthorityKeyIdentifier(): {
- kid: ASN1V;
- } | undefined;
-
- public getExtExtKeyUsageName(): OIDName[] | undefined;
-
- public getExtSubjectAltName(): Deprecated<string[]>;
-
- public getExtSubjectAltName2(): ['MAIL' | 'DNS' | 'DN' | 'URI' | 'IP', string][] | undefined;
-
- public getExtCRLDistributionPointsURI(): string[] | undefined;
-
- public getExtAIAInfo(): ExtAIAInfo | undefined;
-
- public getExtCertificatePolicies(): ExtCertificatePolicy[] | undefined;
-
- public readCertPEM(sCertPEM: PEM): void;
-
- public readCertHex(sCertHex: HexString): void;
-
- public getInfo(): string;
-
- public static hex2dn(hex: HexString, idx?: Idx<HexString>): string;
-
- public static hex2rdn(hex: HexString, idx?: Idx<HexString>): string;
-
- public static hex2attrTypeValue(hex: HexString, idx?: Idx<HexString>): string;
-
- public static getPublicKeyFromCertPEM(sCertPEM: PEM): RSAKey | KJUR.crypto.ECDSA | KJUR.crypto.DSA;
-
- public static getPublicKeyInfoPropOfCertPEM(sCertPEM: PEM): {
- algparam: ASN1V | null;
- leyhex: ASN1V;
- algoid: ASN1V;
- };
- }
-}
diff --git a/packages/backend/src/boot/index.ts b/packages/backend/src/boot/index.ts
index 5bb20a729f..c3d0592256 100644
--- a/packages/backend/src/boot/index.ts
+++ b/packages/backend/src/boot/index.ts
@@ -1,6 +1,6 @@
import cluster from 'node:cluster';
import chalk from 'chalk';
-import { default as Xev } from 'xev';
+import Xev from 'xev';
import Logger from '@/services/logger.js';
import { envOption } from '../env.js';
@@ -12,7 +12,7 @@ import { workerMain } from './worker.js';
const logger = new Logger('core', 'cyan');
const clusterLogger = logger.createSubLogger('cluster', 'orange', false);
-const ev = new Xev.default();
+const ev = new Xev();
/**
* Init process
diff --git a/packages/backend/src/daemons/queue-stats.ts b/packages/backend/src/daemons/queue-stats.ts
index bfef110545..1535abc6af 100644
--- a/packages/backend/src/daemons/queue-stats.ts
+++ b/packages/backend/src/daemons/queue-stats.ts
@@ -1,7 +1,7 @@
-import { default as Xev } from 'xev';
+import Xev from 'xev';
import { deliverQueue, inboxQueue } from '../queue/queues.js';
-const ev = new Xev.default();
+const ev = new Xev();
const interval = 10000;
diff --git a/packages/backend/src/daemons/server-stats.ts b/packages/backend/src/daemons/server-stats.ts
index 327305ccc5..faf4e6e4a4 100644
--- a/packages/backend/src/daemons/server-stats.ts
+++ b/packages/backend/src/daemons/server-stats.ts
@@ -1,8 +1,8 @@
import si from 'systeminformation';
-import { default as Xev } from 'xev';
+import Xev from 'xev';
import * as osUtils from 'os-utils';
-const ev = new Xev.default();
+const ev = new Xev();
const interval = 2000;
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/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' ? (
diff --git a/packages/backend/src/models/entities/user.ts b/packages/backend/src/models/entities/user.ts
index c76824c977..29d9a0c2ca 100644
--- a/packages/backend/src/models/entities/user.ts
+++ b/packages/backend/src/models/entities/user.ts
@@ -1,6 +1,6 @@
import { Entity, Column, Index, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm';
-import { DriveFile } from './drive-file.js';
import { id } from '../id.js';
+import { DriveFile } from './drive-file.js';
@Entity()
@Index(['usernameLower', 'host'], { unique: true })
@@ -207,7 +207,7 @@ export class User {
@Column('boolean', {
default: false,
- comment: 'Whether to show users replying to other users in the timeline'
+ comment: 'Whether to show users replying to other users in the timeline',
})
public showTimelineReplies: boolean;
diff --git a/packages/backend/src/models/repositories/drive-file.ts b/packages/backend/src/models/repositories/drive-file.ts
index 69dc1721c2..b626359d98 100644
--- a/packages/backend/src/models/repositories/drive-file.ts
+++ b/packages/backend/src/models/repositories/drive-file.ts
@@ -1,6 +1,5 @@
import { db } from '@/db/postgre.js';
import { DriveFile } from '@/models/entities/drive-file.js';
-import { Users, DriveFolders } from '../index.js';
import { User } from '@/models/entities/user.js';
import { toPuny } from '@/misc/convert-host.js';
import { awaitAll, Promiseable } from '@/prelude/await-all.js';
@@ -9,6 +8,7 @@ import config from '@/config/index.js';
import { query, appendQuery } from '@/prelude/url.js';
import { Meta } from '@/models/entities/meta.js';
import { fetchMeta } from '@/misc/fetch-meta.js';
+import { Users, DriveFolders } from '../index.js';
type PackOptions = {
detail?: boolean,
@@ -29,7 +29,7 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
getPublicProperties(file: DriveFile): DriveFile['properties'] {
if (file.properties.orientation != null) {
- const properties = JSON.parse(JSON.stringify(file.properties));
+ const properties = structuredClone(file.properties);
if (file.properties.orientation >= 5) {
[properties.width, properties.height] = [properties.height, properties.width];
}
@@ -111,7 +111,40 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
async pack(
src: DriveFile['id'] | DriveFile,
- options?: PackOptions
+ options?: PackOptions,
+ ): Promise<Packed<'DriveFile'>> {
+ const opts = Object.assign({
+ detail: false,
+ self: false,
+ }, options);
+
+ const file = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src });
+
+ return await awaitAll<Packed<'DriveFile'>>({
+ id: file.id,
+ createdAt: file.createdAt.toISOString(),
+ name: file.name,
+ type: file.type,
+ md5: file.md5,
+ size: file.size,
+ isSensitive: file.isSensitive,
+ blurhash: file.blurhash,
+ properties: opts.self ? file.properties : this.getPublicProperties(file),
+ url: opts.self ? file.url : this.getPublicUrl(file, false),
+ thumbnailUrl: this.getPublicUrl(file, true),
+ comment: file.comment,
+ folderId: file.folderId,
+ folder: opts.detail && file.folderId ? DriveFolders.pack(file.folderId, {
+ detail: true,
+ }) : null,
+ userId: opts.withUser ? file.userId : null,
+ user: (opts.withUser && file.userId) ? Users.pack(file.userId) : null,
+ });
+ },
+
+ async packNullable(
+ src: DriveFile['id'] | DriveFile,
+ options?: PackOptions,
): Promise<Packed<'DriveFile'> | null> {
const opts = Object.assign({
detail: false,
@@ -145,9 +178,9 @@ export const DriveFileRepository = db.getRepository(DriveFile).extend({
async packMany(
files: (DriveFile['id'] | DriveFile)[],
- options?: PackOptions
- ) {
- const items = await Promise.all(files.map(f => this.pack(f, options)));
- return items.filter(x => x != null);
+ options?: PackOptions,
+ ): Promise<Packed<'DriveFile'>[]> {
+ const items = await Promise.all(files.map(f => this.packNullable(f, options)));
+ return items.filter((x): x is Packed<'DriveFile'> => x != null);
},
});
diff --git a/packages/backend/src/models/repositories/page.ts b/packages/backend/src/models/repositories/page.ts
index 1bffb23fa2..092b26b396 100644
--- a/packages/backend/src/models/repositories/page.ts
+++ b/packages/backend/src/models/repositories/page.ts
@@ -1,10 +1,10 @@
import { db } from '@/db/postgre.js';
import { Page } from '@/models/entities/page.js';
import { Packed } from '@/misc/schema.js';
-import { Users, DriveFiles, PageLikes } from '../index.js';
import { awaitAll } from '@/prelude/await-all.js';
import { DriveFile } from '@/models/entities/drive-file.js';
import { User } from '@/models/entities/user.js';
+import { Users, DriveFiles, PageLikes } from '../index.js';
export const PageRepository = db.getRepository(Page).extend({
async pack(
@@ -14,7 +14,7 @@ export const PageRepository = db.getRepository(Page).extend({
const meId = me ? me.id : null;
const page = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src });
- const attachedFiles: Promise<DriveFile | undefined>[] = [];
+ const attachedFiles: Promise<DriveFile | null>[] = [];
const collectFile = (xs: any[]) => {
for (const x of xs) {
if (x.type === 'image') {
@@ -73,7 +73,7 @@ export const PageRepository = db.getRepository(Page).extend({
script: page.script,
eyeCatchingImageId: page.eyeCatchingImageId,
eyeCatchingImage: page.eyeCatchingImageId ? await DriveFiles.pack(page.eyeCatchingImageId) : null,
- attachedFiles: DriveFiles.packMany(await Promise.all(attachedFiles)),
+ attachedFiles: DriveFiles.packMany((await Promise.all(attachedFiles)).filter((x): x is DriveFile => x != null)),
likedCount: page.likedCount,
isLiked: meId ? await PageLikes.findOneBy({ pageId: page.id, userId: meId }).then(x => x != null) : undefined,
});
diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts
index 2f4b7d6787..541fbaf003 100644
--- a/packages/backend/src/models/repositories/user.ts
+++ b/packages/backend/src/models/repositories/user.ts
@@ -1,7 +1,6 @@
import { EntityRepository, Repository, In, Not } from 'typeorm';
import Ajv from 'ajv';
import { User, ILocalUser, IRemoteUser } from '@/models/entities/user.js';
-import { Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings, Instances, DriveFiles } from '../index.js';
import config from '@/config/index.js';
import { Packed } from '@/misc/schema.js';
import { awaitAll, Promiseable } from '@/prelude/await-all.js';
@@ -9,8 +8,9 @@ import { populateEmojis } from '@/misc/populate-emojis.js';
import { getAntennas } from '@/misc/antenna-cache.js';
import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js';
import { Cache } from '@/misc/cache.js';
-import { Instance } from '../entities/instance.js';
import { db } from '@/db/postgre.js';
+import { Instance } from '../entities/instance.js';
+import { Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings, Instances, DriveFiles } from '../index.js';
const userInstanceCache = new Cache<Instance | null>(1000 * 60 * 60 * 3);
@@ -112,7 +112,7 @@ export const UserRepository = db.getRepository(User).extend({
const joinings = await UserGroupJoinings.findBy({ userId: userId });
const groupQs = Promise.all(joinings.map(j => MessagingMessages.createQueryBuilder('message')
- .where(`message.groupId = :groupId`, { groupId: j.userGroupId })
+ .where('message.groupId = :groupId', { groupId: j.userGroupId })
.andWhere('message.userId != :userId', { userId: userId })
.andWhere('NOT (:userId = ANY(message.reads))', { userId: userId })
.andWhere('message.createdAt > :joinedAt', { joinedAt: j.createdAt }) // 自分が加入する前の会話については、未読扱いしない
@@ -204,8 +204,18 @@ export const UserRepository = db.getRepository(User).extend({
);
},
- getAvatarUrl(user: User): string {
- // TODO: avatarIdがあるがavatarがない(JOINされてない)場合のハンドリング
+ async getAvatarUrl(user: User): Promise<string> {
+ if (user.avatar) {
+ return DriveFiles.getPublicUrl(user.avatar, true) || this.getIdenticonUrl(user.id);
+ } else if (user.avatarId) {
+ const avatar = await DriveFiles.findOneByOrFail({ id: user.avatarId });
+ return DriveFiles.getPublicUrl(avatar, true) || this.getIdenticonUrl(user.id);
+ } else {
+ return this.getIdenticonUrl(user.id);
+ }
+ },
+
+ getAvatarUrlSync(user: User): string {
if (user.avatar) {
return DriveFiles.getPublicUrl(user.avatar, true) || this.getIdenticonUrl(user.id);
} else {
@@ -223,7 +233,7 @@ export const UserRepository = db.getRepository(User).extend({
options?: {
detail?: D,
includeSecrets?: boolean,
- }
+ },
): Promise<IsMeAndIsUserDetailed<ExpectsMe, D>> {
const opts = Object.assign({
detail: false,
@@ -274,7 +284,7 @@ export const UserRepository = db.getRepository(User).extend({
name: user.name,
username: user.username,
host: user.host,
- avatarUrl: this.getAvatarUrl(user),
+ avatarUrl: this.getAvatarUrlSync(user),
avatarBlurhash: user.avatar?.blurhash || null,
avatarColor: null, // 後方互換性のため
isAdmin: user.isAdmin || falsy,
@@ -283,7 +293,7 @@ export const UserRepository = db.getRepository(User).extend({
isCat: user.isCat || falsy,
instance: user.host ? userInstanceCache.fetch(user.host,
() => Instances.findOneBy({ host: user.host! }),
- v => v != null
+ v => v != null,
).then(instance => instance ? {
name: instance.name,
softwareName: instance.softwareName,
@@ -403,7 +413,7 @@ export const UserRepository = db.getRepository(User).extend({
options?: {
detail?: D,
includeSecrets?: boolean,
- }
+ },
): Promise<IsUserDetailed<D>[]> {
return Promise.all(users.map(u => this.pack(u, me, options)));
},
diff --git a/packages/backend/src/remote/activitypub/kernel/move/index.ts b/packages/backend/src/remote/activitypub/kernel/move/index.ts
deleted file mode 100644
index e69de29bb2..0000000000
--- a/packages/backend/src/remote/activitypub/kernel/move/index.ts
+++ /dev/null
diff --git a/packages/backend/src/remote/activitypub/models/mention.ts b/packages/backend/src/remote/activitypub/models/mention.ts
index a160092969..13f77424ec 100644
--- a/packages/backend/src/remote/activitypub/models/mention.ts
+++ b/packages/backend/src/remote/activitypub/models/mention.ts
@@ -1,9 +1,9 @@
+import promiseLimit from 'promise-limit';
import { toArray, unique } from '@/prelude/array.js';
+import { CacheableUser, User } from '@/models/entities/user.js';
import { IObject, isMention, IApMention } from '../type.js';
-import { resolvePerson } from './person.js';
-import promiseLimit from 'promise-limit';
import Resolver from '../resolver.js';
-import { CacheableUser, User } from '@/models/entities/user.js';
+import { resolvePerson } from './person.js';
export async function extractApMentions(tags: IObject | IObject[] | null | undefined) {
const hrefs = unique(extractApMentionObjects(tags).map(x => x.href as string));
@@ -12,7 +12,7 @@ export async function extractApMentions(tags: IObject | IObject[] | null | undef
const limit = promiseLimit<CacheableUser | null>(2);
const mentionedUsers = (await Promise.all(
- hrefs.map(x => limit(() => resolvePerson(x, resolver).catch(() => null)))
+ hrefs.map(x => limit(() => resolvePerson(x, resolver).catch(() => null))),
)).filter((x): x is CacheableUser => x != null);
return mentionedUsers;
diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts
index 4267f46fb3..6097e3b6ed 100644
--- a/packages/backend/src/remote/activitypub/models/person.ts
+++ b/packages/backend/src/remote/activitypub/models/person.ts
@@ -1,7 +1,6 @@
import { URL } from 'node:url';
import promiseLimit from 'promise-limit';
-import $, { Context } from 'cafy';
import config from '@/config/index.js';
import { registerOrFetchInstanceDoc } from '@/services/register-or-fetch-instance-doc.js';
import { Note } from '@/models/entities/note.js';
@@ -54,20 +53,33 @@ function validateActor(x: IObject, uri: string): IActor {
throw new Error(`invalid Actor type '${x.type}'`);
}
- const validate = (name: string, value: any, validater: Context) => {
- const e = validater.test(value);
- if (e) throw new Error(`invalid Actor: ${name} ${e.message}`);
- };
+ if (!(typeof x.id === 'string' && x.id.length > 0)) {
+ throw new Error('invalid Actor: wrong id');
+ }
- validate('id', x.id, $.default.str.min(1));
- validate('inbox', x.inbox, $.default.str.min(1));
- validate('preferredUsername', x.preferredUsername, $.default.str.min(1).max(128).match(/^\w([\w-.]*\w)?$/));
+ if (!(typeof x.inbox === 'string' && x.inbox.length > 0)) {
+ throw new Error('invalid Actor: wrong inbox');
+ }
+
+ if (!(typeof x.preferredUsername === 'string' && x.preferredUsername.length > 0 && x.preferredUsername.length <= 128 && /^\w([\w-.]*\w)?$/.test(x.preferredUsername))) {
+ throw new Error('invalid Actor: wrong username');
+ }
// These fields are only informational, and some AP software allows these
// fields to be very long. If they are too long, we cut them off. This way
// we can at least see these users and their activities.
- validate('name', truncate(x.name, nameLength), $.default.optional.nullable.str);
- validate('summary', truncate(x.summary, summaryLength), $.default.optional.nullable.str);
+ if (x.name) {
+ if (!(typeof x.name === 'string' && x.name.length > 0)) {
+ throw new Error('invalid Actor: wrong name');
+ }
+ x.name = truncate(x.name, nameLength);
+ }
+ if (x.summary) {
+ if (!(typeof x.summary === 'string' && x.summary.length > 0)) {
+ throw new Error('invalid Actor: wrong summary');
+ }
+ x.summary = truncate(x.summary, summaryLength);
+ }
const idHost = toPuny(new URL(x.id!).hostname);
if (idHost !== expectHost) {
@@ -271,7 +283,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
* @param resolver Resolver
* @param hint Hint of Person object (この値が正当なPersonの場合、Remote resolveをせずに更新に利用します)
*/
-export async function updatePerson(uri: string, resolver?: Resolver | null, hint?: Record<string, unknown>): Promise<void> {
+export async function updatePerson(uri: string, resolver?: Resolver | null, hint?: IObject): Promise<void> {
if (typeof uri !== 'string') throw new Error('uri is not string');
// URIがこのサーバーを指しているならスキップ
@@ -289,7 +301,7 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
if (resolver == null) resolver = new Resolver();
- const object = hint || await resolver.resolve(uri) as any;
+ const object = hint || await resolver.resolve(uri);
const person = validateActor(object, uri);
diff --git a/packages/backend/src/remote/activitypub/renderer/flag.ts b/packages/backend/src/remote/activitypub/renderer/flag.ts
index 6fbc11580f..58eadddbaa 100644
--- a/packages/backend/src/remote/activitypub/renderer/flag.ts
+++ b/packages/backend/src/remote/activitypub/renderer/flag.ts
@@ -5,7 +5,7 @@ import { getInstanceActor } from '@/services/instance-actor.js';
// to anonymise reporters, the reporting actor must be a system user
// object has to be a uri or array of uris
-export const renderFlag = (user: ILocalUser, object: [string], content: string): IActivity => {
+export const renderFlag = (user: ILocalUser, object: [string], content: string) => {
return {
type: 'Flag',
actor: `${config.url}/users/${user.id}`,
diff --git a/packages/backend/src/remote/activitypub/renderer/note.ts b/packages/backend/src/remote/activitypub/renderer/note.ts
index 679c8bbfe4..e8d429e5de 100644
--- a/packages/backend/src/remote/activitypub/renderer/note.ts
+++ b/packages/backend/src/remote/activitypub/renderer/note.ts
@@ -1,15 +1,15 @@
-import renderDocument from './document.js';
-import renderHashtag from './hashtag.js';
-import renderMention from './mention.js';
-import renderEmoji from './emoji.js';
+import { In, IsNull } from 'typeorm';
import config from '@/config/index.js';
-import toHtml from '../misc/get-note-html.js';
import { Note, IMentionedRemoteUsers } from '@/models/entities/note.js';
import { DriveFile } from '@/models/entities/drive-file.js';
import { DriveFiles, Notes, Users, Emojis, Polls } from '@/models/index.js';
-import { In, IsNull } from 'typeorm';
import { Emoji } from '@/models/entities/emoji.js';
import { Poll } from '@/models/entities/poll.js';
+import toHtml from '../misc/get-note-html.js';
+import renderEmoji from './emoji.js';
+import renderMention from './mention.js';
+import renderHashtag from './hashtag.js';
+import renderDocument from './document.js';
export default async function renderNote(note: Note, dive = true, isTalk = false): Promise<Record<string, unknown>> {
const getPromisedFiles = async (ids: string[]) => {
@@ -83,7 +83,7 @@ export default async function renderNote(note: Note, dive = true, isTalk = false
const files = await getPromisedFiles(note.fileIds);
const text = note.text;
- let poll: Poll | null;
+ let poll: Poll | null = null;
if (note.hasPoll) {
poll = await Polls.findOneBy({ noteId: note.id });
@@ -159,7 +159,7 @@ export async function getEmojis(names: string[]): Promise<Emoji[]> {
names.map(name => Emojis.findOneBy({
name,
host: IsNull(),
- }))
+ })),
);
return emojis.filter(emoji => emoji != null) as Emoji[];
diff --git a/packages/backend/src/remote/activitypub/resolver.ts b/packages/backend/src/remote/activitypub/resolver.ts
index c1269c75c5..334eae9843 100644
--- a/packages/backend/src/remote/activitypub/resolver.ts
+++ b/packages/backend/src/remote/activitypub/resolver.ts
@@ -2,10 +2,10 @@ import config from '@/config/index.js';
import { getJson } from '@/misc/fetch.js';
import { ILocalUser } from '@/models/entities/user.js';
import { getInstanceActor } from '@/services/instance-actor.js';
-import { signedGet } from './request.js';
-import { IObject, isCollectionOrOrderedCollection, ICollection, IOrderedCollection } from './type.js';
import { fetchMeta } from '@/misc/fetch-meta.js';
import { extractDbHost } from '@/misc/convert-host.js';
+import { signedGet } from './request.js';
+import { IObject, isCollectionOrOrderedCollection, ICollection, IOrderedCollection } from './type.js';
export default class Resolver {
private history: Set<string>;
@@ -56,13 +56,13 @@ export default class Resolver {
this.user = await getInstanceActor();
}
- const object = this.user
+ const object = (this.user
? await signedGet(value, this.user)
- : await getJson(value, 'application/activity+json, application/ld+json');
+ : await getJson(value, 'application/activity+json, application/ld+json')) as IObject;
if (object == null || (
Array.isArray(object['@context']) ?
- !object['@context'].includes('https://www.w3.org/ns/activitystreams') :
+ !(object['@context'] as unknown[]).includes('https://www.w3.org/ns/activitystreams') :
object['@context'] !== 'https://www.w3.org/ns/activitystreams'
)) {
throw new Error('invalid response');
diff --git a/packages/backend/src/remote/activitypub/type.ts b/packages/backend/src/remote/activitypub/type.ts
index 2051d2624d..ef5b98b59e 100644
--- a/packages/backend/src/remote/activitypub/type.ts
+++ b/packages/backend/src/remote/activitypub/type.ts
@@ -2,7 +2,7 @@ export type obj = { [x: string]: any };
export type ApObject = IObject | string | (IObject | string)[];
export interface IObject {
- '@context': string | obj | obj[];
+ '@context': string | string[] | obj | obj[];
type: string | string[];
id?: string;
summary?: string;
@@ -48,7 +48,7 @@ export function getOneApId(value: ApObject): string {
export function getApId(value: string | IObject): string {
if (typeof value === 'string') return value;
if (typeof value.id === 'string') return value.id;
- throw new Error(`cannot detemine id`);
+ throw new Error('cannot detemine id');
}
/**
@@ -57,7 +57,7 @@ export function getApId(value: string | IObject): string {
export function getApType(value: IObject): string {
if (typeof value.type === 'string') return value.type;
if (Array.isArray(value.type) && typeof value.type[0] === 'string') return value.type[0];
- throw new Error(`cannot detect type`);
+ throw new Error('cannot detect type');
}
export function getOneApHrefNullable(value: ApObject | undefined): string | undefined {
diff --git a/packages/backend/src/server/activitypub/followers.ts b/packages/backend/src/server/activitypub/followers.ts
index 4d4f733162..beb48713a6 100644
--- a/packages/backend/src/server/activitypub/followers.ts
+++ b/packages/backend/src/server/activitypub/followers.ts
@@ -1,32 +1,26 @@
import Router from '@koa/router';
+import { FindOptionsWhere, IsNull, LessThan } from 'typeorm';
import config from '@/config/index.js';
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id.js';
import * as url from '@/prelude/url.js';
import { renderActivity } from '@/remote/activitypub/renderer/index.js';
import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection.js';
import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page.js';
import renderFollowUser from '@/remote/activitypub/renderer/follow-user.js';
-import { setResponseType } from '../activitypub.js';
import { Users, Followings, UserProfiles } from '@/models/index.js';
-import { IsNull, LessThan } from 'typeorm';
+import { Following } from '@/models/entities/following.js';
+import { setResponseType } from '../activitypub.js';
export default async (ctx: Router.RouterContext) => {
const userId = ctx.params.user;
- // Get 'cursor' parameter
- const [cursor, cursorErr] = $.default.optional.type(ID).get(ctx.request.query.cursor);
-
- // Get 'page' parameter
- const pageErr = !$.default.optional.str.or(['true', 'false']).ok(ctx.request.query.page);
- const page: boolean = ctx.request.query.page === 'true';
-
- // Validate parameters
- if (cursorErr || pageErr) {
+ const cursor = ctx.request.query.cursor;
+ if (cursor != null && typeof cursor !== 'string') {
ctx.status = 400;
return;
}
+ const page = ctx.request.query.page === 'true';
+
const user = await Users.findOneBy({
id: userId,
host: IsNull(),
@@ -57,7 +51,7 @@ export default async (ctx: Router.RouterContext) => {
if (page) {
const query = {
followeeId: user.id,
- } as any;
+ } as FindOptionsWhere<Following>;
// カーソルが指定されている場合
if (cursor) {
@@ -86,7 +80,7 @@ export default async (ctx: Router.RouterContext) => {
inStock ? `${partOf}?${url.query({
page: 'true',
cursor: followings[followings.length - 1].id,
- })}` : undefined
+ })}` : undefined,
);
ctx.body = renderActivity(rendered);
diff --git a/packages/backend/src/server/activitypub/following.ts b/packages/backend/src/server/activitypub/following.ts
index 0af1f424f9..3a25a6316c 100644
--- a/packages/backend/src/server/activitypub/following.ts
+++ b/packages/backend/src/server/activitypub/following.ts
@@ -1,33 +1,26 @@
import Router from '@koa/router';
+import { LessThan, IsNull, FindOptionsWhere } from 'typeorm';
import config from '@/config/index.js';
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id.js';
import * as url from '@/prelude/url.js';
import { renderActivity } from '@/remote/activitypub/renderer/index.js';
import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection.js';
import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page.js';
import renderFollowUser from '@/remote/activitypub/renderer/follow-user.js';
-import { setResponseType } from '../activitypub.js';
import { Users, Followings, UserProfiles } from '@/models/index.js';
-import { LessThan, IsNull, FindOptionsWhere } from 'typeorm';
import { Following } from '@/models/entities/following.js';
+import { setResponseType } from '../activitypub.js';
export default async (ctx: Router.RouterContext) => {
const userId = ctx.params.user;
- // Get 'cursor' parameter
- const [cursor, cursorErr] = $.default.optional.type(ID).get(ctx.request.query.cursor);
-
- // Get 'page' parameter
- const pageErr = !$.default.optional.str.or(['true', 'false']).ok(ctx.request.query.page);
- const page: boolean = ctx.request.query.page === 'true';
-
- // Validate parameters
- if (cursorErr || pageErr) {
+ const cursor = ctx.request.query.cursor;
+ if (cursor != null && typeof cursor !== 'string') {
ctx.status = 400;
return;
}
+ const page = ctx.request.query.page === 'true';
+
const user = await Users.findOneBy({
id: userId,
host: IsNull(),
@@ -87,7 +80,7 @@ export default async (ctx: Router.RouterContext) => {
inStock ? `${partOf}?${url.query({
page: 'true',
cursor: followings[followings.length - 1].id,
- })}` : undefined
+ })}` : undefined,
);
ctx.body = renderActivity(rendered);
diff --git a/packages/backend/src/server/activitypub/outbox.ts b/packages/backend/src/server/activitypub/outbox.ts
index 6b9592bcf3..7a2586998a 100644
--- a/packages/backend/src/server/activitypub/outbox.ts
+++ b/packages/backend/src/server/activitypub/outbox.ts
@@ -1,36 +1,37 @@
import Router from '@koa/router';
+import { Brackets, IsNull } from 'typeorm';
import config from '@/config/index.js';
-import $ from 'cafy';
-import { ID } from '@/misc/cafy-id.js';
import { renderActivity } from '@/remote/activitypub/renderer/index.js';
import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection.js';
import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page.js';
-import { setResponseType } from '../activitypub.js';
import renderNote from '@/remote/activitypub/renderer/note.js';
import renderCreate from '@/remote/activitypub/renderer/create.js';
import renderAnnounce from '@/remote/activitypub/renderer/announce.js';
import { countIf } from '@/prelude/array.js';
import * as url from '@/prelude/url.js';
import { Users, Notes } from '@/models/index.js';
-import { makePaginationQuery } from '../api/common/make-pagination-query.js';
-import { Brackets, IsNull } from 'typeorm';
import { Note } from '@/models/entities/note.js';
+import { makePaginationQuery } from '../api/common/make-pagination-query.js';
+import { setResponseType } from '../activitypub.js';
export default async (ctx: Router.RouterContext) => {
const userId = ctx.params.user;
- // Get 'sinceId' parameter
- const [sinceId, sinceIdErr] = $.default.optional.type(ID).get(ctx.request.query.since_id);
+ const sinceId = ctx.request.query.since_id;
+ if (sinceId != null && typeof sinceId !== 'string') {
+ ctx.status = 400;
+ return;
+ }
- // Get 'untilId' parameter
- const [untilId, untilIdErr] = $.default.optional.type(ID).get(ctx.request.query.until_id);
+ const untilId = ctx.request.query.until_id;
+ if (untilId != null && typeof untilId !== 'string') {
+ ctx.status = 400;
+ return;
+ }
- // Get 'page' parameter
- const pageErr = !$.default.optional.str.or(['true', 'false']).ok(ctx.request.query.page);
- const page: boolean = ctx.request.query.page === 'true';
+ const page = ctx.request.query.page === 'true';
- // Validate parameters
- if (sinceIdErr || untilIdErr || pageErr || countIf(x => x != null, [sinceId, untilId]) > 1) {
+ if (countIf(x => x != null, [sinceId, untilId]) > 1) {
ctx.status = 400;
return;
}
@@ -52,8 +53,8 @@ export default async (ctx: Router.RouterContext) => {
const query = makePaginationQuery(Notes.createQueryBuilder('note'), sinceId, untilId)
.andWhere('note.userId = :userId', { userId: user.id })
.andWhere(new Brackets(qb => { qb
- .where(`note.visibility = 'public'`)
- .orWhere(`note.visibility = 'home'`);
+ .where('note.visibility = \'public\'')
+ .orWhere('note.visibility = \'home\'');
}))
.andWhere('note.localOnly = FALSE');
@@ -76,7 +77,7 @@ export default async (ctx: Router.RouterContext) => {
notes.length ? `${partOf}?${url.query({
page: 'true',
until_id: notes[notes.length - 1].id,
- })}` : undefined
+ })}` : undefined,
);
ctx.body = renderActivity(rendered);
@@ -85,7 +86,7 @@ export default async (ctx: Router.RouterContext) => {
// index page
const rendered = renderOrderedCollection(partOf, user.notesCount,
`${partOf}?page=true`,
- `${partOf}?page=true&since_id=000000000000000000000000`
+ `${partOf}?page=true&since_id=000000000000000000000000`,
);
ctx.body = renderActivity(rendered);
ctx.set('Cache-Control', 'public, max-age=180');
diff --git a/packages/backend/src/server/api/2fa.ts b/packages/backend/src/server/api/2fa.ts
index dce8accaac..96b9316e47 100644
--- a/packages/backend/src/server/api/2fa.ts
+++ b/packages/backend/src/server/api/2fa.ts
@@ -1,6 +1,6 @@
import * as crypto from 'node:crypto';
-import config from '@/config/index.js';
import * as jsrsasign from 'jsrsasign';
+import config from '@/config/index.js';
const ECC_PRELUDE = Buffer.from([0x04]);
const NULL_BYTE = Buffer.from([0]);
@@ -145,7 +145,7 @@ export function verifyLogin({
export const procedures = {
none: {
- verify({ publicKey }: {publicKey: Map<number, Buffer>}) {
+ verify({ publicKey }: { publicKey: Map<number, Buffer> }) {
const negTwo = publicKey.get(-2);
if (!negTwo || negTwo.length !== 32) {
diff --git a/packages/backend/src/server/api/common/signin.ts b/packages/backend/src/server/api/common/signin.ts
index f1dccee2ce..038fd8d96e 100644
--- a/packages/backend/src/server/api/common/signin.ts
+++ b/packages/backend/src/server/api/common/signin.ts
@@ -9,7 +9,7 @@ import { publishMainStream } from '@/services/stream.js';
export default function(ctx: Koa.Context, user: ILocalUser, redirect = false) {
if (redirect) {
//#region Cookie
- ctx.cookies.set('igi', user.token, {
+ ctx.cookies.set('igi', user.token!, {
path: '/',
// SEE: https://github.com/koajs/koa/issues/974
// When using a SSL proxy it should be configured to add the "X-Forwarded-Proto: https" header
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
index 1d8eb1d618..7a5758d75b 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
@@ -1,5 +1,6 @@
-import define from '../../../define.js';
import { Announcements, AnnouncementReads } from '@/models/index.js';
+import { Announcement } from '@/models/entities/announcement.js';
+import define from '../../../define.js';
import { makePaginationQuery } from '../../../common/make-pagination-query.js';
export const meta = {
@@ -68,11 +69,21 @@ export default define(meta, paramDef, async (ps) => {
const announcements = await query.take(ps.limit).getMany();
+ const reads = new Map<Announcement, number>();
+
for (const announcement of announcements) {
- (announcement as any).reads = await AnnouncementReads.countBy({
+ reads.set(announcement, await AnnouncementReads.countBy({
announcementId: announcement.id,
- });
+ }));
}
- return announcements;
+ return announcements.map(announcement => ({
+ id: announcement.id,
+ createdAt: announcement.createdAt.toISOString(),
+ updatedAt: announcement.updatedAt?.toISOString() ?? null,
+ title: announcement.title,
+ text: announcement.text,
+ imageUrl: announcement.imageUrl,
+ reads: reads.get(announcement)!,
+ }));
});
diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts
index 2703b4b9db..1575d81d5d 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-users.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts
@@ -1,5 +1,5 @@
-import define from '../../define.js';
import { Users } from '@/models/index.js';
+import define from '../../define.js';
export const meta = {
tags: ['admin'],
@@ -24,8 +24,8 @@ export const paramDef = {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
offset: { type: 'integer', default: 0 },
sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt'] },
- state: { type: 'string', enum: ['all', 'available', 'admin', 'moderator', 'adminOrModerator', 'silenced', 'suspended'], default: "all" },
- origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" },
+ state: { type: 'string', enum: ['all', 'alive', 'available', 'admin', 'moderator', 'adminOrModerator', 'silenced', 'suspended'], default: 'all' },
+ origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: 'local' },
username: { type: 'string', nullable: true, default: null },
hostname: {
type: 'string',
diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts
index 004e4c131d..8aac55b4a0 100644
--- a/packages/backend/src/server/api/endpoints/antennas/notes.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts
@@ -57,13 +57,9 @@ export default define(meta, paramDef, async (ps, user) => {
throw new ApiError(meta.errors.noSuchAntenna);
}
- const antennaQuery = AntennaNotes.createQueryBuilder('joining')
- .select('joining.noteId')
- .where('joining.antennaId = :antennaId', { antennaId: antenna.id });
-
const query = makePaginationQuery(Notes.createQueryBuilder('note'),
ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
- .andWhere(`note.id IN (${ antennaQuery.getQuery() })`)
+ .innerJoin(AntennaNotes.metadata.targetName, 'antennaNote', 'antennaNote.noteId = note.id')
.innerJoinAndSelect('note.user', 'user')
.leftJoinAndSelect('user.avatar', 'avatar')
.leftJoinAndSelect('user.banner', 'banner')
@@ -75,7 +71,7 @@ export default define(meta, paramDef, async (ps, user) => {
.leftJoinAndSelect('renote.user', 'renoteUser')
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner')
- .setParameters(antennaQuery.getParameters());
+ .andWhere('antennaNote.antennaId = :antennaId', { antennaId: antenna.id });
generateVisibilityQuery(query, user);
generateMutedUserQuery(query, user);
diff --git a/packages/backend/src/server/api/endpoints/clips/notes.ts b/packages/backend/src/server/api/endpoints/clips/notes.ts
index 4b6782fca0..4ace747efe 100644
--- a/packages/backend/src/server/api/endpoints/clips/notes.ts
+++ b/packages/backend/src/server/api/endpoints/clips/notes.ts
@@ -57,12 +57,8 @@ export default define(meta, paramDef, async (ps, user) => {
throw new ApiError(meta.errors.noSuchClip);
}
- const clipQuery = ClipNotes.createQueryBuilder('joining')
- .select('joining.noteId')
- .where('joining.clipId = :clipId', { clipId: clip.id });
-
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .andWhere(`note.id IN (${ clipQuery.getQuery() })`)
+ .innerJoin(ClipNotes.metadata.targetName, 'clipNote', 'clipNote.noteId = note.id')
.innerJoinAndSelect('note.user', 'user')
.leftJoinAndSelect('user.avatar', 'avatar')
.leftJoinAndSelect('user.banner', 'banner')
@@ -74,7 +70,7 @@ export default define(meta, paramDef, async (ps, user) => {
.leftJoinAndSelect('renote.user', 'renoteUser')
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner')
- .setParameters(clipQuery.getParameters());
+ .andWhere('clipNote.clipId = :clipId', { clipId: clip.id });
if (user) {
generateVisibilityQuery(query, user);
diff --git a/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts b/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts
index f9b4ea89ea..0b74cb9f01 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts
@@ -1,5 +1,5 @@
-import define from '../../../define.js';
import { DriveFiles } from '@/models/index.js';
+import define from '../../../define.js';
export const meta = {
tags: ['drive'],
diff --git a/packages/backend/src/server/api/endpoints/drive/files/show.ts b/packages/backend/src/server/api/endpoints/drive/files/show.ts
index a2bc0c7aa4..fb19345fee 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/show.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/show.ts
@@ -1,7 +1,7 @@
-import define from '../../../define.js';
-import { ApiError } from '../../../error.js';
import { DriveFile } from '@/models/entities/drive-file.js';
import { DriveFiles, Users } from '@/models/index.js';
+import define from '../../../define.js';
+import { ApiError } from '../../../error.js';
export const meta = {
tags: ['drive'],
@@ -51,7 +51,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
- let file: DriveFile | undefined;
+ let file: DriveFile | null = null;
if (ps.fileId) {
file = await DriveFiles.findOneBy({ id: ps.fileId });
diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts
index 9de05918c0..40a3ba73ca 100644
--- a/packages/backend/src/server/api/endpoints/notes/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/create.ts
@@ -1,15 +1,15 @@
import ms from 'ms';
+import { In } from 'typeorm';
import create from '@/services/note/create.js';
-import define from '../../define.js';
-import { ApiError } from '../../error.js';
import { User } from '@/models/entities/user.js';
import { Users, DriveFiles, Notes, Channels, Blockings } from '@/models/index.js';
import { DriveFile } from '@/models/entities/drive-file.js';
import { Note } from '@/models/entities/note.js';
-import { noteVisibilities } from '../../../../types.js';
import { Channel } from '@/models/entities/channel.js';
import { MAX_NOTE_TEXT_LENGTH } from '@/const.js';
-import { In } from 'typeorm';
+import { noteVisibilities } from '../../../../types.js';
+import { ApiError } from '../../error.js';
+import define from '../../define.js';
export const meta = {
tags: ['notes'],
@@ -83,7 +83,7 @@ export const meta = {
export const paramDef = {
type: 'object',
properties: {
- visibility: { type: 'string', enum: ['public', 'home', 'followers', 'specified'], default: "public" },
+ visibility: { type: 'string', enum: ['public', 'home', 'followers', 'specified'], default: 'public' },
visibleUserIds: { type: 'array', uniqueItems: true, items: {
type: 'string', format: 'misskey:id',
} },
@@ -149,7 +149,7 @@ export const paramDef = {
{
// (re)note with poll, text and files are optional
properties: {
- poll: { type: 'object', nullable: false, },
+ poll: { type: 'object', nullable: false },
},
required: ['poll'],
},
@@ -178,14 +178,14 @@ export default define(meta, paramDef, async (ps, user) => {
});
}
- let renote: Note | null;
+ let renote: Note | null = null;
if (ps.renoteId != null) {
// Fetch renote to note
renote = await Notes.findOneBy({ id: ps.renoteId });
if (renote == null) {
throw new ApiError(meta.errors.noSuchRenoteTarget);
- } else if (renote.renoteId && !renote.text && !renote.fileIds && !renote.poll) {
+ } else if (renote.renoteId && !renote.text && !renote.fileIds && !renote.hasPoll) {
throw new ApiError(meta.errors.cannotReRenote);
}
@@ -201,14 +201,14 @@ export default define(meta, paramDef, async (ps, user) => {
}
}
- let reply: Note | null;
+ let reply: Note | null = null;
if (ps.replyId != null) {
// Fetch reply
reply = await Notes.findOneBy({ id: ps.replyId });
if (reply == null) {
throw new ApiError(meta.errors.noSuchReplyTarget);
- } else if (reply.renoteId && !reply.text && !reply.fileIds && !renote.poll) {
+ } else if (reply.renoteId && !reply.text && !reply.fileIds && !reply.hasPoll) {
throw new ApiError(meta.errors.cannotReplyToPureRenote);
}
@@ -234,7 +234,7 @@ export default define(meta, paramDef, async (ps, user) => {
}
}
- let channel: Channel | undefined;
+ let channel: Channel | null = null;
if (ps.channelId != null) {
channel = await Channels.findOneBy({ id: ps.channelId });
diff --git a/packages/backend/src/server/api/endpoints/notes/reactions.ts b/packages/backend/src/server/api/endpoints/notes/reactions.ts
index 3555424fa6..fbb065329c 100644
--- a/packages/backend/src/server/api/endpoints/notes/reactions.ts
+++ b/packages/backend/src/server/api/endpoints/notes/reactions.ts
@@ -1,8 +1,8 @@
-import define from '../../define.js';
-import { ApiError } from '../../error.js';
+import { DeepPartial, FindOptionsWhere } from 'typeorm';
import { NoteReactions } from '@/models/index.js';
-import { DeepPartial } from 'typeorm';
import { NoteReaction } from '@/models/entities/note-reaction.js';
+import define from '../../define.js';
+import { ApiError } from '../../error.js';
export const meta = {
tags: ['notes', 'reactions'],
@@ -45,7 +45,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
const query = {
noteId: ps.noteId,
- } as DeepPartial<NoteReaction>;
+ } as FindOptionsWhere<NoteReaction>;
if (ps.type) {
// ローカルリアクションはホスト名が . とされているが
diff --git a/packages/backend/src/server/api/endpoints/notes/translate.ts b/packages/backend/src/server/api/endpoints/notes/translate.ts
index c602981b30..5e40e7106f 100644
--- a/packages/backend/src/server/api/endpoints/notes/translate.ts
+++ b/packages/backend/src/server/api/endpoints/notes/translate.ts
@@ -1,12 +1,12 @@
-import define from '../../define.js';
-import { getNote } from '../../common/getters.js';
-import { ApiError } from '../../error.js';
+import { URLSearchParams } from 'node:url';
import fetch from 'node-fetch';
import config from '@/config/index.js';
import { getAgentByUrl } from '@/misc/fetch.js';
-import { URLSearchParams } from 'node:url';
import { fetchMeta } from '@/misc/fetch-meta.js';
import { Notes } from '@/models/index.js';
+import { ApiError } from '../../error.js';
+import { getNote } from '../../common/getters.js';
+import define from '../../define.js';
export const meta = {
tags: ['notes'],
@@ -80,7 +80,12 @@ export default define(meta, paramDef, async (ps, user) => {
agent: getAgentByUrl,
});
- const json = await res.json();
+ const json = (await res.json()) as {
+ translations: {
+ detected_source_language: string;
+ text: string;
+ }[];
+ };
return {
sourceLang: json.translations[0].detected_source_language,
diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
index 6c6402603a..fd4a879035 100644
--- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -63,12 +63,8 @@ export default define(meta, paramDef, async (ps, user) => {
}
//#region Construct query
- const listQuery = UserListJoinings.createQueryBuilder('joining')
- .select('joining.userId')
- .where('joining.userListId = :userListId', { userListId: list.id });
-
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
- .andWhere(`note.userId IN (${ listQuery.getQuery() })`)
+ .innerJoin(UserListJoinings.metadata.targetName, 'userListJoining', 'userListJoining.userId = note.userId')
.innerJoinAndSelect('note.user', 'user')
.leftJoinAndSelect('user.avatar', 'avatar')
.leftJoinAndSelect('user.banner', 'banner')
@@ -80,7 +76,7 @@ export default define(meta, paramDef, async (ps, user) => {
.leftJoinAndSelect('renote.user', 'renoteUser')
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner')
- .setParameters(listQuery.getParameters());
+ .andWhere('userListJoining.userListId = :userListId', { userListId: list.id });
generateVisibilityQuery(query, user);
diff --git a/packages/backend/src/server/api/endpoints/pages/show.ts b/packages/backend/src/server/api/endpoints/pages/show.ts
index 3dcce8550f..5d37e86b91 100644
--- a/packages/backend/src/server/api/endpoints/pages/show.ts
+++ b/packages/backend/src/server/api/endpoints/pages/show.ts
@@ -1,8 +1,8 @@
-import define from '../../define.js';
-import { ApiError } from '../../error.js';
+import { IsNull } from 'typeorm';
import { Pages, Users } from '@/models/index.js';
import { Page } from '@/models/entities/page.js';
-import { IsNull } from 'typeorm';
+import define from '../../define.js';
+import { ApiError } from '../../error.js';
export const meta = {
tags: ['pages'],
@@ -45,7 +45,7 @@ export const paramDef = {
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
- let page: Page | undefined;
+ let page: Page | null = null;
if (ps.pageId) {
page = await Pages.findOneBy({ id: ps.pageId });
diff --git a/packages/backend/src/server/api/service/discord.ts b/packages/backend/src/server/api/service/discord.ts
index 04197574c2..97cbcbecdb 100644
--- a/packages/backend/src/server/api/service/discord.ts
+++ b/packages/backend/src/server/api/service/discord.ts
@@ -1,16 +1,16 @@
import Koa from 'koa';
import Router from '@koa/router';
-import { getJson } from '@/misc/fetch.js';
import { OAuth2 } from 'oauth';
+import { v4 as uuid } from 'uuid';
+import { IsNull } from 'typeorm';
+import { getJson } from '@/misc/fetch.js';
import config from '@/config/index.js';
import { publishMainStream } from '@/services/stream.js';
-import { redisClient } from '../../../db/redis.js';
-import { v4 as uuid } from 'uuid';
-import signin from '../common/signin.js';
import { fetchMeta } from '@/misc/fetch-meta.js';
import { Users, UserProfiles } from '@/models/index.js';
import { ILocalUser } from '@/models/entities/user.js';
-import { IsNull } from 'typeorm';
+import { redisClient } from '../../../db/redis.js';
+import signin from '../common/signin.js';
function getUserToken(ctx: Koa.BaseContext): string | null {
return ((ctx.headers['cookie'] || '').match(/igi=(\w+)/) || [null, null])[1];
@@ -54,7 +54,7 @@ router.get('/disconnect/discord', async ctx => {
integrations: profile.integrations,
});
- ctx.body = `Discordの連携を解除しました :v:`;
+ ctx.body = 'Discordの連携を解除しました :v:';
// Publish i updated event
publishMainStream(user.id, 'meUpdated', await Users.pack(user, user, {
@@ -140,7 +140,7 @@ router.get('/dc/cb', async ctx => {
const code = ctx.query.code;
- if (!code) {
+ if (!code || typeof code !== 'string') {
ctx.throw(400, 'invalid session');
return;
}
@@ -174,17 +174,17 @@ router.get('/dc/cb', async ctx => {
}
}));
- const { id, username, discriminator } = await getJson('https://discord.com/api/users/@me', '*/*', 10 * 1000, {
+ const { id, username, discriminator } = (await getJson('https://discord.com/api/users/@me', '*/*', 10 * 1000, {
'Authorization': `Bearer ${accessToken}`,
- });
+ })) as Record<string, unknown>;
- if (!id || !username || !discriminator) {
+ if (typeof id !== 'string' || typeof username !== 'string' || typeof discriminator !== 'string') {
ctx.throw(400, 'invalid session');
return;
}
const profile = await UserProfiles.createQueryBuilder()
- .where(`"integrations"->'discord'->>'id' = :id`, { id: id })
+ .where('"integrations"->\'discord\'->>\'id\' = :id', { id: id })
.andWhere('"userHost" IS NULL')
.getOne();
@@ -211,7 +211,7 @@ router.get('/dc/cb', async ctx => {
} else {
const code = ctx.query.code;
- if (!code) {
+ if (!code || typeof code !== 'string') {
ctx.throw(400, 'invalid session');
return;
}
@@ -245,10 +245,10 @@ router.get('/dc/cb', async ctx => {
}
}));
- const { id, username, discriminator } = await getJson('https://discord.com/api/users/@me', '*/*', 10 * 1000, {
+ const { id, username, discriminator } = (await getJson('https://discord.com/api/users/@me', '*/*', 10 * 1000, {
'Authorization': `Bearer ${accessToken}`,
- });
- if (!id || !username || !discriminator) {
+ })) as Record<string, unknown>;
+ if (typeof id !== 'string' || typeof username !== 'string' || typeof discriminator !== 'string') {
ctx.throw(400, 'invalid session');
return;
}
diff --git a/packages/backend/src/server/api/service/github.ts b/packages/backend/src/server/api/service/github.ts
index 61bb768a63..04dbd1f7ab 100644
--- a/packages/backend/src/server/api/service/github.ts
+++ b/packages/backend/src/server/api/service/github.ts
@@ -1,16 +1,16 @@
import Koa from 'koa';
import Router from '@koa/router';
-import { getJson } from '@/misc/fetch.js';
import { OAuth2 } from 'oauth';
+import { v4 as uuid } from 'uuid';
+import { IsNull } from 'typeorm';
+import { getJson } from '@/misc/fetch.js';
import config from '@/config/index.js';
import { publishMainStream } from '@/services/stream.js';
-import { redisClient } from '../../../db/redis.js';
-import { v4 as uuid } from 'uuid';
-import signin from '../common/signin.js';
import { fetchMeta } from '@/misc/fetch-meta.js';
import { Users, UserProfiles } from '@/models/index.js';
import { ILocalUser } from '@/models/entities/user.js';
-import { IsNull } from 'typeorm';
+import { redisClient } from '../../../db/redis.js';
+import signin from '../common/signin.js';
function getUserToken(ctx: Koa.BaseContext): string | null {
return ((ctx.headers['cookie'] || '').match(/igi=(\w+)/) || [null, null])[1];
@@ -54,7 +54,7 @@ router.get('/disconnect/github', async ctx => {
integrations: profile.integrations,
});
- ctx.body = `GitHubの連携を解除しました :v:`;
+ ctx.body = 'GitHubの連携を解除しました :v:';
// Publish i updated event
publishMainStream(user.id, 'meUpdated', await Users.pack(user, user, {
@@ -138,7 +138,7 @@ router.get('/gh/cb', async ctx => {
const code = ctx.query.code;
- if (!code) {
+ if (!code || typeof code !== 'string') {
ctx.throw(400, 'invalid session');
return;
}
@@ -167,16 +167,16 @@ router.get('/gh/cb', async ctx => {
}
}));
- const { login, id } = await getJson('https://api.github.com/user', 'application/vnd.github.v3+json', 10 * 1000, {
+ const { login, id } = (await getJson('https://api.github.com/user', 'application/vnd.github.v3+json', 10 * 1000, {
'Authorization': `bearer ${accessToken}`,
- });
- if (!login || !id) {
+ })) as Record<string, unknown>;
+ if (typeof login !== 'string' || typeof id !== 'string') {
ctx.throw(400, 'invalid session');
return;
}
const link = await UserProfiles.createQueryBuilder()
- .where(`"integrations"->'github'->>'id' = :id`, { id: id })
+ .where('"integrations"->\'github\'->>\'id\' = :id', { id: id })
.andWhere('"userHost" IS NULL')
.getOne();
@@ -189,7 +189,7 @@ router.get('/gh/cb', async ctx => {
} else {
const code = ctx.query.code;
- if (!code) {
+ if (!code || typeof code !== 'string') {
ctx.throw(400, 'invalid session');
return;
}
@@ -219,11 +219,11 @@ router.get('/gh/cb', async ctx => {
}
}));
- const { login, id } = await getJson('https://api.github.com/user', 'application/vnd.github.v3+json', 10 * 1000, {
+ const { login, id } = (await getJson('https://api.github.com/user', 'application/vnd.github.v3+json', 10 * 1000, {
'Authorization': `bearer ${accessToken}`,
- });
+ })) as Record<string, unknown>;
- if (!login || !id) {
+ if (typeof login !== 'string' || typeof id !== 'string') {
ctx.throw(400, 'invalid session');
return;
}
diff --git a/packages/backend/src/server/api/service/twitter.ts b/packages/backend/src/server/api/service/twitter.ts
index e72b71e2f7..2b4f9f6daa 100644
--- a/packages/backend/src/server/api/service/twitter.ts
+++ b/packages/backend/src/server/api/service/twitter.ts
@@ -2,14 +2,14 @@ import Koa from 'koa';
import Router from '@koa/router';
import { v4 as uuid } from 'uuid';
import autwh from 'autwh';
-import { redisClient } from '../../../db/redis.js';
+import { IsNull } from 'typeorm';
import { publishMainStream } from '@/services/stream.js';
import config from '@/config/index.js';
-import signin from '../common/signin.js';
import { fetchMeta } from '@/misc/fetch-meta.js';
import { Users, UserProfiles } from '@/models/index.js';
import { ILocalUser } from '@/models/entities/user.js';
-import { IsNull } from 'typeorm';
+import signin from '../common/signin.js';
+import { redisClient } from '../../../db/redis.js';
function getUserToken(ctx: Koa.BaseContext): string | null {
return ((ctx.headers['cookie'] || '').match(/igi=(\w+)/) || [null, null])[1];
@@ -53,7 +53,7 @@ router.get('/disconnect/twitter', async ctx => {
integrations: profile.integrations,
});
- ctx.body = `Twitterの連携を解除しました :v:`;
+ ctx.body = 'Twitterの連携を解除しました :v:';
// Publish i updated event
publishMainStream(user.id, 'meUpdated', await Users.pack(user, user, {
@@ -132,10 +132,16 @@ router.get('/tw/cb', async ctx => {
const twCtx = await get;
- const result = await twAuth!.done(JSON.parse(twCtx), ctx.query.oauth_verifier);
+ const verifier = ctx.query.oauth_verifier;
+ if (!verifier || typeof verifier !== 'string') {
+ ctx.throw(400, 'invalid session');
+ return;
+ }
+
+ const result = await twAuth!.done(JSON.parse(twCtx), verifier);
const link = await UserProfiles.createQueryBuilder()
- .where(`"integrations"->'twitter'->>'userId' = :id`, { id: result.userId })
+ .where('"integrations"->\'twitter\'->>\'userId\' = :id', { id: result.userId })
.andWhere('"userHost" IS NULL')
.getOne();
@@ -148,7 +154,7 @@ router.get('/tw/cb', async ctx => {
} else {
const verifier = ctx.query.oauth_verifier;
- if (verifier == null) {
+ if (!verifier || typeof verifier !== 'string') {
ctx.throw(400, 'invalid session');
return;
}
diff --git a/packages/backend/src/server/api/stream/channels/queue-stats.ts b/packages/backend/src/server/api/stream/channels/queue-stats.ts
index 043d03ab8d..b67600474b 100644
--- a/packages/backend/src/server/api/stream/channels/queue-stats.ts
+++ b/packages/backend/src/server/api/stream/channels/queue-stats.ts
@@ -1,7 +1,7 @@
-import { default as Xev } from 'xev';
+import Xev from 'xev';
import Channel from '../channel.js';
-const ev = new Xev.default();
+const ev = new Xev();
export default class extends Channel {
public readonly chName = 'queueStats';
diff --git a/packages/backend/src/server/api/stream/channels/server-stats.ts b/packages/backend/src/server/api/stream/channels/server-stats.ts
index 0da1895767..db75a6fa38 100644
--- a/packages/backend/src/server/api/stream/channels/server-stats.ts
+++ b/packages/backend/src/server/api/stream/channels/server-stats.ts
@@ -1,7 +1,7 @@
-import { default as Xev } from 'xev';
+import Xev from 'xev';
import Channel from '../channel.js';
-const ev = new Xev.default();
+const ev = new Xev();
export default class extends Channel {
public readonly chName = 'serverStats';
diff --git a/packages/backend/src/server/api/stream/index.ts b/packages/backend/src/server/api/stream/index.ts
index b803478281..2d23145f14 100644
--- a/packages/backend/src/server/api/stream/index.ts
+++ b/packages/backend/src/server/api/stream/index.ts
@@ -1,27 +1,25 @@
+import { EventEmitter } from 'events';
import * as websocket from 'websocket';
-import { readNotification } from '../common/read-notification.js';
-import call from '../call.js';
import readNote from '@/services/note/read.js';
-import Channel from './channel.js';
-import channels from './channels/index.js';
-import { EventEmitter } from 'events';
import { User } from '@/models/entities/user.js';
import { Channel as ChannelModel } from '@/models/entities/channel.js';
import { Users, Followings, Mutings, UserProfiles, ChannelFollowings, Blockings } from '@/models/index.js';
-import { ApiError } from '../error.js';
import { AccessToken } from '@/models/entities/access-token.js';
import { UserProfile } from '@/models/entities/user-profile.js';
import { publishChannelStream, publishGroupMessagingStream, publishMessagingStream } from '@/services/stream.js';
import { UserGroup } from '@/models/entities/user-group.js';
-import { StreamEventEmitter, StreamMessages } from './types.js';
import { Packed } from '@/misc/schema.js';
+import { readNotification } from '../common/read-notification.js';
+import channels from './channels/index.js';
+import Channel from './channel.js';
+import { StreamEventEmitter, StreamMessages } from './types.js';
/**
* Main stream connection
*/
export default class Connection {
public user?: User;
- public userProfile?: UserProfile;
+ public userProfile?: UserProfile | null;
public following: Set<User['id']> = new Set();
public muting: Set<User['id']> = new Set();
public blocking: Set<User['id']> = new Set(); // "被"blocking
@@ -84,7 +82,7 @@ export default class Connection {
this.muting.delete(data.body.id);
break;
- // TODO: block events
+ // TODO: block events
case 'followChannel':
this.followingChannels.add(data.body.id);
@@ -126,7 +124,6 @@ export default class Connection {
const { type, body } = obj;
switch (type) {
- case 'api': this.onApiRequest(body); break;
case 'readNotification': this.onReadNotification(body); break;
case 'subNote': this.onSubscribeNote(body); break;
case 's': this.onSubscribeNote(body); break; // alias
@@ -183,31 +180,6 @@ export default class Connection {
}
}
- /**
- * APIリクエスト要求時
- */
- private async onApiRequest(payload: any) {
- // 新鮮なデータを利用するためにユーザーをフェッチ
- const user = this.user ? await Users.findOneBy({ id: this.user.id }) : null;
-
- const endpoint = payload.endpoint || payload.ep; // alias
-
- // 呼び出し
- call(endpoint, user, this.token, payload.data).then(res => {
- this.sendMessageToWs(`api:${payload.id}`, { res });
- }).catch((e: ApiError) => {
- this.sendMessageToWs(`api:${payload.id}`, {
- error: {
- message: e.message,
- code: e.code,
- id: e.id,
- kind: e.kind,
- ...(e.info ? { info: e.info } : {}),
- },
- });
- });
- }
-
private onReadNotification(payload: any) {
if (!payload.id) return;
readNotification(this.user!.id, [payload.id]);
diff --git a/packages/backend/src/server/index.ts b/packages/backend/src/server/index.ts
index d00bf8996f..c1a2a6dfff 100644
--- a/packages/backend/src/server/index.ts
+++ b/packages/backend/src/server/index.ts
@@ -10,23 +10,23 @@ import mount from 'koa-mount';
import koaLogger from 'koa-logger';
import * as slow from 'koa-slow';
-import activityPub from './activitypub.js';
-import nodeinfo from './nodeinfo.js';
-import wellKnown from './well-known.js';
+import { IsNull } from 'typeorm';
import config from '@/config/index.js';
-import apiServer from './api/index.js';
-import fileServer from './file/index.js';
-import proxyServer from './proxy/index.js';
-import webServer from './web/index.js';
import Logger from '@/services/logger.js';
-import { envOption } from '../env.js';
import { UserProfiles, Users } from '@/models/index.js';
import { genIdenticon } from '@/misc/gen-identicon.js';
import { createTemp } from '@/misc/create-temp.js';
import { publishMainStream } from '@/services/stream.js';
import * as Acct from '@/misc/acct.js';
+import { envOption } from '../env.js';
+import activityPub from './activitypub.js';
+import nodeinfo from './nodeinfo.js';
+import wellKnown from './well-known.js';
+import apiServer from './api/index.js';
+import fileServer from './file/index.js';
+import proxyServer from './proxy/index.js';
+import webServer from './web/index.js';
import { initializeStreamingServer } from './api/streaming.js';
-import { IsNull } from 'typeorm';
export const serverLogger = new Logger('server', 'gray', false);
@@ -81,7 +81,7 @@ router.get('/avatar/@:acct', async ctx => {
});
if (user) {
- ctx.redirect(Users.getAvatarUrl(user));
+ ctx.redirect(Users.getAvatarUrlSync(user));
} else {
ctx.redirect('/static-assets/user-unknown.png');
}
diff --git a/packages/backend/src/server/web/feed.ts b/packages/backend/src/server/web/feed.ts
index eba8dc58d4..4abe2885cf 100644
--- a/packages/backend/src/server/web/feed.ts
+++ b/packages/backend/src/server/web/feed.ts
@@ -1,8 +1,8 @@
import { Feed } from 'feed';
+import { In, IsNull } from 'typeorm';
import config from '@/config/index.js';
import { User } from '@/models/entities/user.js';
-import { Notes, DriveFiles, UserProfiles } from '@/models/index.js';
-import { In, IsNull } from 'typeorm';
+import { Notes, DriveFiles, UserProfiles, Users } from '@/models/index.js';
export default async function(user: User) {
const author = {
@@ -29,7 +29,7 @@ export default async function(user: User) {
generator: 'Misskey',
description: `${user.notesCount} Notes, ${profile.ffVisibility === 'public' ? user.followingCount : '?'} Following, ${profile.ffVisibility === 'public' ? user.followersCount : '?'} Followers${profile.description ? ` · ${profile.description}` : ''}`,
link: author.link,
- image: user.avatarUrl ? user.avatarUrl : undefined,
+ image: await Users.getAvatarUrl(user),
feedLinks: {
json: `${author.link}.json`,
atom: `${author.link}.atom`,
diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts
index 48bf6f7338..e80bf45d14 100644
--- a/packages/backend/src/server/web/index.ts
+++ b/packages/backend/src/server/web/index.ts
@@ -11,20 +11,20 @@ import send from 'koa-send';
import favicon from 'koa-favicon';
import views from 'koa-views';
import { createBullBoard } from '@bull-board/api';
-import { BullAdapter } from '@bull-board/api/bullAdapter.js';
+import { BullAdapter } from '@bull-board/api/bullAdapter.js';
import { KoaAdapter } from '@bull-board/koa';
-import packFeed from './feed.js';
+import { In, IsNull } from 'typeorm';
import { fetchMeta } from '@/misc/fetch-meta.js';
-import { genOpenapiSpec } from '../api/openapi/gen-spec.js';
import config from '@/config/index.js';
import { Users, Notes, UserProfiles, Pages, Channels, Clips, GalleryPosts } from '@/models/index.js';
import * as Acct from '@/misc/acct.js';
import { getNoteSummary } from '@/misc/get-note-summary.js';
+import { queues } from '@/queue/queues.js';
+import { genOpenapiSpec } from '../api/openapi/gen-spec.js';
import { urlPreviewHandler } from './url-preview.js';
import { manifestHandler } from './manifest.js';
-import { queues } from '@/queue/queues.js';
-import { IsNull } from 'typeorm';
+import packFeed from './feed.js';
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
@@ -127,7 +127,7 @@ router.get('/twemoji/(.*)', async ctx => {
return;
}
- ctx.set('Content-Security-Policy', `default-src 'none'; style-src 'unsafe-inline'`);
+ ctx.set('Content-Security-Policy', 'default-src \'none\'; style-src \'unsafe-inline\'');
await send(ctx as any, path, {
root: `${_dirname}/../../../node_modules/@discordapp/twemoji/dist/svg/`,
@@ -235,6 +235,7 @@ router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => {
await ctx.render('user', {
user, profile, me,
+ avatarUrl: await Users.getAvatarUrl(user),
sub: ctx.params.sub,
instanceName: meta.name || 'Misskey',
icon: meta.iconUrl,
@@ -265,7 +266,10 @@ router.get('/users/:user', async ctx => {
// Note
router.get('/notes/:note', async (ctx, next) => {
- const note = await Notes.findOneBy({ id: ctx.params.note });
+ const note = await Notes.findOneBy({
+ id: ctx.params.note,
+ visibility: In(['public', 'home']),
+ });
if (note) {
const _note = await Notes.pack(note);
@@ -274,6 +278,7 @@ router.get('/notes/:note', async (ctx, next) => {
await ctx.render('note', {
note: _note,
profile,
+ avatarUrl: await Users.getAvatarUrl(await Users.findOneByOrFail({ id: note.userId })),
// TODO: Let locale changeable by instance setting
summary: getNoteSummary(_note),
instanceName: meta.name || 'Misskey',
@@ -281,11 +286,7 @@ router.get('/notes/:note', async (ctx, next) => {
themeColor: meta.themeColor,
});
- if (['public', 'home'].includes(note.visibility)) {
- ctx.set('Cache-Control', 'public, max-age=180');
- } else {
- ctx.set('Cache-Control', 'private, max-age=0, must-revalidate');
- }
+ ctx.set('Cache-Control', 'public, max-age=180');
return;
}
@@ -315,6 +316,7 @@ router.get('/@:user/pages/:page', async (ctx, next) => {
await ctx.render('page', {
page: _page,
profile,
+ avatarUrl: await Users.getAvatarUrl(await Users.findOneByOrFail({ id: page.userId })),
instanceName: meta.name || 'Misskey',
icon: meta.iconUrl,
themeColor: meta.themeColor,
@@ -346,6 +348,7 @@ router.get('/clips/:clip', async (ctx, next) => {
await ctx.render('clip', {
clip: _clip,
profile,
+ avatarUrl: await Users.getAvatarUrl(await Users.findOneByOrFail({ id: clip.userId })),
instanceName: meta.name || 'Misskey',
icon: meta.iconUrl,
themeColor: meta.themeColor,
@@ -370,6 +373,7 @@ router.get('/gallery/:post', async (ctx, next) => {
await ctx.render('gallery-post', {
post: _post,
profile,
+ avatarUrl: await Users.getAvatarUrl(await Users.findOneByOrFail({ id: post.userId })),
instanceName: meta.name || 'Misskey',
icon: meta.iconUrl,
themeColor: meta.themeColor,
@@ -434,7 +438,7 @@ router.get('/cli', async ctx => {
});
});
-const override = (source: string, target: string, depth: number = 0) =>
+const override = (source: string, target: string, depth = 0) =>
[, ...target.split('/').filter(x => x), ...source.split('/').filter(x => x).splice(depth)].join('/');
router.get('/flush', async ctx => {
diff --git a/packages/backend/src/server/web/manifest.ts b/packages/backend/src/server/web/manifest.ts
index bcbf9b76a7..61d7660066 100644
--- a/packages/backend/src/server/web/manifest.ts
+++ b/packages/backend/src/server/web/manifest.ts
@@ -1,16 +1,16 @@
import Koa from 'koa';
-import manifest from './manifest.json' assert { type: 'json' };
import { fetchMeta } from '@/misc/fetch-meta.js';
+import manifest from './manifest.json' assert { type: 'json' };
export const manifestHandler = async (ctx: Koa.Context) => {
- const json = JSON.parse(JSON.stringify(manifest));
+ const res = structuredClone(manifest);
const instance = await fetchMeta(true);
- json.short_name = instance.name || 'Misskey';
- json.name = instance.name || 'Misskey';
- if (instance.themeColor) json.theme_color = instance.themeColor;
+ res.short_name = instance.name || 'Misskey';
+ res.name = instance.name || 'Misskey';
+ if (instance.themeColor) res.theme_color = instance.themeColor;
ctx.set('Cache-Control', 'max-age=300');
- ctx.body = json;
+ ctx.body = res;
};
diff --git a/packages/backend/src/server/web/views/clip.pug b/packages/backend/src/server/web/views/clip.pug
index 7a84d50f6c..4c692bf59b 100644
--- a/packages/backend/src/server/web/views/clip.pug
+++ b/packages/backend/src/server/web/views/clip.pug
@@ -16,7 +16,7 @@ block og
meta(property='og:title' content= title)
meta(property='og:description' content= clip.description)
meta(property='og:url' content= url)
- meta(property='og:image' content= user.avatarUrl)
+ meta(property='og:image' content= avatarUrl)
block meta
if profile.noCrawle
diff --git a/packages/backend/src/server/web/views/note.pug b/packages/backend/src/server/web/views/note.pug
index 34b03f9833..65696ea138 100644
--- a/packages/backend/src/server/web/views/note.pug
+++ b/packages/backend/src/server/web/views/note.pug
@@ -17,7 +17,7 @@ block og
meta(property='og:title' content= title)
meta(property='og:description' content= summary)
meta(property='og:url' content= url)
- meta(property='og:image' content= user.avatarUrl)
+ meta(property='og:image' content= avatarUrl)
block meta
if user.host || isRenote || profile.noCrawle
diff --git a/packages/backend/src/server/web/views/page.pug b/packages/backend/src/server/web/views/page.pug
index b6c9548025..4219e76a52 100644
--- a/packages/backend/src/server/web/views/page.pug
+++ b/packages/backend/src/server/web/views/page.pug
@@ -16,7 +16,7 @@ block og
meta(property='og:title' content= title)
meta(property='og:description' content= page.summary)
meta(property='og:url' content= url)
- meta(property='og:image' content= page.eyeCatchingImage ? page.eyeCatchingImage.thumbnailUrl : user.avatarUrl)
+ meta(property='og:image' content= page.eyeCatchingImage ? page.eyeCatchingImage.thumbnailUrl : avatarUrl)
block meta
if profile.noCrawle
diff --git a/packages/backend/src/server/web/views/user.pug b/packages/backend/src/server/web/views/user.pug
index 2adec0f889..119993fdb5 100644
--- a/packages/backend/src/server/web/views/user.pug
+++ b/packages/backend/src/server/web/views/user.pug
@@ -3,7 +3,6 @@ extends ./base
block vars
- const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`;
- const url = `${config.url}/@${(user.host ? `${user.username}@${user.host}` : user.username)}`;
- - const img = user.avatarUrl || null;
block title
= `${title} | ${instanceName}`
@@ -16,7 +15,7 @@ block og
meta(property='og:title' content= title)
meta(property='og:description' content= profile.description)
meta(property='og:url' content= url)
- meta(property='og:image' content= img)
+ meta(property='og:image' content= avatarUrl)
block meta
if user.host || profile.noCrawle
diff --git a/packages/backend/src/services/blocking/create.ts b/packages/backend/src/services/blocking/create.ts
index 5e96e5037f..b2be78b220 100644
--- a/packages/backend/src/services/blocking/create.ts
+++ b/packages/backend/src/services/blocking/create.ts
@@ -95,17 +95,12 @@ async function unFollow(follower: User, followee: User) {
return;
}
- Followings.delete(following.id);
-
- //#region Decrement following count
- Users.decrement({ id: follower.id }, 'followingCount', 1);
- //#endregion
-
- //#region Decrement followers count
- Users.decrement({ id: followee.id }, 'followersCount', 1);
- //#endregion
-
- perUserFollowingChart.update(follower, followee, false);
+ await Promise.all([
+ Followings.delete(following.id),
+ Users.decrement({ id: follower.id }, 'followingCount', 1),
+ Users.decrement({ id: followee.id }, 'followersCount', 1),
+ perUserFollowingChart.update(follower, followee, false),
+ ]);
// Publish unfollow event
if (Users.isLocalUser(follower)) {
diff --git a/packages/backend/src/services/following/create.ts b/packages/backend/src/services/following/create.ts
index 7491c44f83..72c24676bb 100644
--- a/packages/backend/src/services/following/create.ts
+++ b/packages/backend/src/services/following/create.ts
@@ -67,8 +67,10 @@ export async function insertFollowingDoc(followee: { id: User['id']; host: User[
if (alreadyFollowed) return;
//#region Increment counts
- Users.increment({ id: follower.id }, 'followingCount', 1);
- Users.increment({ id: followee.id }, 'followersCount', 1);
+ await Promise.all([
+ Users.increment({ id: follower.id }, 'followingCount', 1),
+ Users.increment({ id: followee.id }, 'followersCount', 1),
+ ]);
//#endregion
//#region Update instance stats
diff --git a/packages/backend/src/services/following/delete.ts b/packages/backend/src/services/following/delete.ts
index 241f9606e5..91b5a3d61d 100644
--- a/packages/backend/src/services/following/delete.ts
+++ b/packages/backend/src/services/following/delete.ts
@@ -58,12 +58,11 @@ export default async function(follower: { id: User['id']; host: User['host']; ur
}
export async function decrementFollowing(follower: { id: User['id']; host: User['host']; }, followee: { id: User['id']; host: User['host']; }) {
- //#region Decrement following count
- Users.decrement({ id: follower.id }, 'followingCount', 1);
- //#endregion
-
- //#region Decrement followers count
- Users.decrement({ id: followee.id }, 'followersCount', 1);
+ //#region Decrement following / followers counts
+ await Promise.all([
+ Users.decrement({ id: follower.id }, 'followingCount', 1),
+ Users.decrement({ id: followee.id }, 'followersCount', 1),
+ ]);
//#endregion
//#region Update instance stats
diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts
index ffd609dd84..4963200161 100644
--- a/packages/backend/src/services/note/delete.ts
+++ b/packages/backend/src/services/note/delete.ts
@@ -1,3 +1,4 @@
+import { Brackets, In } from 'typeorm';
import { publishNoteStream } from '@/services/stream.js';
import renderDelete from '@/remote/activitypub/renderer/delete.js';
import renderAnnounce from '@/remote/activitypub/renderer/announce.js';
@@ -5,15 +6,14 @@ import renderUndo from '@/remote/activitypub/renderer/undo.js';
import { renderActivity } from '@/remote/activitypub/renderer/index.js';
import renderTombstone from '@/remote/activitypub/renderer/tombstone.js';
import config from '@/config/index.js';
-import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc.js';
import { User, ILocalUser, IRemoteUser } from '@/models/entities/user.js';
import { Note, IMentionedRemoteUsers } from '@/models/entities/note.js';
import { Notes, Users, Instances } from '@/models/index.js';
import { notesChart, perUserNotesChart, instanceChart } from '@/services/chart/index.js';
import { deliverToFollowers, deliverToUser } from '@/remote/activitypub/deliver-manager.js';
import { countSameRenotes } from '@/misc/count-same-renotes.js';
+import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc.js';
import { deliverToRelays } from '../relay.js';
-import { Brackets, In } from 'typeorm';
/**
* 投稿を削除します。
@@ -40,7 +40,7 @@ export default async function(user: { id: User['id']; uri: User['uri']; host: Us
//#region ローカルの投稿なら削除アクティビティを配送
if (Users.isLocalUser(user) && !note.localOnly) {
- let renote: Note | null;
+ let renote: Note | null = null;
// if deletd note is renote
if (note.renoteId && note.text == null && !note.hasPoll && (note.fileIds == null || note.fileIds.length === 0)) {
@@ -113,7 +113,7 @@ async function getMentionedRemoteUsers(note: Note) {
const uris = (JSON.parse(note.mentionedRemoteUsers) as IMentionedRemoteUsers).map(x => x.uri);
if (uris.length > 0) {
where.push(
- { uri: In(uris) }
+ { uri: In(uris) },
);
}
diff --git a/packages/backend/src/services/relay.ts b/packages/backend/src/services/relay.ts
index 1ab45588da..08bf72cc26 100644
--- a/packages/backend/src/services/relay.ts
+++ b/packages/backend/src/services/relay.ts
@@ -88,7 +88,7 @@ export async function deliverToRelays(user: { id: User['id']; host: null; }, act
}));
if (relays.length === 0) return;
- const copy = JSON.parse(JSON.stringify(activity));
+ const copy = structuredClone(activity);
if (!copy.to) copy.to = ['https://www.w3.org/ns/activitystreams#Public'];
const signed = await attachLdSignature(copy, user);
diff --git a/packages/backend/tsconfig.json b/packages/backend/tsconfig.json
index 3120851aae..22338a4976 100644
--- a/packages/backend/tsconfig.json
+++ b/packages/backend/tsconfig.json
@@ -25,9 +25,14 @@
"rootDir": "./src",
"baseUrl": "./",
"paths": {
- "@/*": ["./src/*"]
+ "@/*": [
+ "./src/*"
+ ]
},
"outDir": "./built",
+ "types": [
+ "node"
+ ],
"typeRoots": [
"./node_modules/@types",
"./src/@types"
diff --git a/packages/backend/yarn.lock b/packages/backend/yarn.lock
index 5cd71acf9c..8fbfa6459b 100644
--- a/packages/backend/yarn.lock
+++ b/packages/backend/yarn.lock
@@ -35,20 +35,20 @@
lodash "^4.17.19"
to-fast-properties "^2.0.0"
-"@bull-board/api@3.10.3":
- version "3.10.3"
- resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-3.10.3.tgz#c6aad9f5cfb3acbe02c57e823ee81c1ae575849d"
- integrity sha512-kV6EPwi9j71qBmozvDmtT01j986r4cFqNmBgq7HApYXW0G2U8Brmv0Ut0iMQZRc/X7aA5KYL3qXcEsriFnq+jw==
+"@bull-board/api@3.10.4":
+ version "3.10.4"
+ resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-3.10.4.tgz#f29d95a9624224ceec0f3ff26ef2c2bba8106921"
+ integrity sha512-JJjMg8O/ELeaqkuL1Wsdn6rdQfH+/2+BfnFD0B7j4ZCtLVAPfsOUZYpLqSKUgaNizwp1nTw0e3L/EI0yvX5aiw==
dependencies:
redis-info "^3.0.8"
-"@bull-board/koa@3.10.3":
- version "3.10.3"
- resolved "https://registry.yarnpkg.com/@bull-board/koa/-/koa-3.10.3.tgz#b9f02629f96f056d6a038c3c58fc339d58e55abb"
- integrity sha512-DK8m09MwcRwUR3tz3xI0iSK/Ih2huQ2MAWm8krYjO5deswP2yBaCWE4OtpiULLfVpf8z4zB3Oqa0xNJrKRHTOQ==
+"@bull-board/koa@3.10.4":
+ version "3.10.4"
+ resolved "https://registry.yarnpkg.com/@bull-board/koa/-/koa-3.10.4.tgz#8e54600bfd8e003a8d5838ae6e65f9ec8c9979f7"
+ integrity sha512-NO0kzgVrl5lGNnX6maBAuP6aecGvROGka3RJSALubDfsrQ3aWNuY2BjUMUvm4ZDVfAeYT3wPaak8rdRCwxYE2g==
dependencies:
- "@bull-board/api" "3.10.3"
- "@bull-board/ui" "3.10.3"
+ "@bull-board/api" "3.10.4"
+ "@bull-board/ui" "3.10.4"
ejs "^3.1.6"
koa "^2.13.1"
koa-mount "^4.0.0"
@@ -56,12 +56,12 @@
koa-static "^5.0.0"
koa-views "^7.0.1"
-"@bull-board/ui@3.10.3":
- version "3.10.3"
- resolved "https://registry.yarnpkg.com/@bull-board/ui/-/ui-3.10.3.tgz#b921199d42b32d8ddd9bbf0e35c25be0d64403e9"
- integrity sha512-6zYW3FqySg+4IKEeM1jt/5ixNVBKQjtZLG9W81ADVcHk8YceQ++7URWzDb8nQEct3rEW4bjR6nicVWNXMSN7Lw==
+"@bull-board/ui@3.10.4":
+ version "3.10.4"
+ resolved "https://registry.yarnpkg.com/@bull-board/ui/-/ui-3.10.4.tgz#6455b4e75fdbec1bc2ee84fde2a6a283b3c77bc9"
+ integrity sha512-nqnE3wqqpso7ORPcmcGVesYeFkHwv3AsBdRV2W0VLtfBPGzMdqZ1sJeSTAmlanFZnvTprU4Eg/G0DcEeMUTGhA==
dependencies:
- "@bull-board/api" "3.10.3"
+ "@bull-board/api" "3.10.4"
"@cspotcode/source-map-consumer@0.8.0":
version "0.8.0"
@@ -110,10 +110,10 @@
pump "^3.0.0"
secure-json-parse "^2.1.0"
-"@eslint/eslintrc@^1.2.1":
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.1.tgz#8b5e1c49f4077235516bc9ec7d41378c0f69b8c6"
- integrity sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==
+"@eslint/eslintrc@^1.2.2":
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.2.tgz#4989b9e8c0216747ee7cca314ae73791bb281aae"
+ integrity sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==
dependencies:
ajv "^6.12.4"
debug "^4.3.2"
@@ -527,6 +527,11 @@
resolved "https://registry.yarnpkg.com/@types/jsonld/-/jsonld-1.5.6.tgz#4396c0b17128abf5773bb68b5453b88fc565b0d4"
integrity sha512-OUcfMjRie5IOrJulUQwVNvV57SOdKcTfBj3pjXNxzXqeOIrY2aGDNGW/Tlp83EQPkz4tCE6YWVrGuc/ZeaAQGg==
+"@types/jsrsasign@10.2.1":
+ version "10.2.1"
+ resolved "https://registry.yarnpkg.com/@types/jsrsasign/-/jsrsasign-10.2.1.tgz#b82882523dfb5c476673dbef344ad838f96fb43d"
+ integrity sha512-piCIOMY0+d2wwRNcRw56VBqFYCYYeZ1c/NlUKVHTV3Y9j1RE2qpgCQvClI6yhH2sk8OoXiah43i9FmnC5tL2RQ==
+
"@types/keygrip@*":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72"
@@ -649,10 +654,10 @@
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d"
integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==
-"@types/mocha@9.1.0":
- version "9.1.0"
- resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.0.tgz#baf17ab2cca3fcce2d322ebc30454bff487efad5"
- integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg==
+"@types/mocha@9.1.1":
+ version "9.1.1"
+ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4"
+ integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==
"@types/node-fetch@3.0.3":
version "3.0.3"
@@ -666,10 +671,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.2.tgz#331b7b9f8621c638284787c5559423822fdffc50"
integrity sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA==
-"@types/node@17.0.23":
- version "17.0.23"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da"
- integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==
+"@types/node@17.0.25":
+ version "17.0.25"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.25.tgz#527051f3c2f77aa52e5dc74e45a3da5fb2301448"
+ integrity sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w==
"@types/node@^14.11.8":
version "14.17.9"
@@ -777,6 +782,11 @@
dependencies:
htmlparser2 "^6.0.0"
+"@types/semver@7.3.9":
+ version "7.3.9"
+ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.9.tgz#152c6c20a7688c30b967ec1841d31ace569863fc"
+ integrity sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==
+
"@types/serve-static@*":
version "1.13.3"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1"
@@ -785,10 +795,10 @@
"@types/express-serve-static-core" "*"
"@types/mime" "*"
-"@types/sharp@0.30.1":
- version "0.30.1"
- resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.30.1.tgz#31bd128f2437e8fc31424eb23d8284aa127bfa8d"
- integrity sha512-LxzQsKo2YtvA2DlqACNXmlbLGMVJCSU/HhV4N9RrStClUEf02iN+AakD/zUOpZkbo1OG+lHk2LeqoHedLwln2w==
+"@types/sharp@0.30.2":
+ version "0.30.2"
+ resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.30.2.tgz#df5ff34140b3bad165482e6f3d26b08e42a0503a"
+ integrity sha512-uLCBwjDg/BTcQit0dpNGvkIjvH3wsb8zpaJePCjvONBBSfaKHoxXBIuq1MT8DMQEfk2fKYnpC9QExCgFhkGkMQ==
dependencies:
"@types/node" "*"
@@ -845,14 +855,14 @@
dependencies:
"@types/node" "*"
-"@typescript-eslint/eslint-plugin@5.18.0":
- version "5.18.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.18.0.tgz#950df411cec65f90d75d6320a03b2c98f6c3af7d"
- integrity sha512-tzrmdGMJI/uii9/V6lurMo4/o+dMTKDH82LkNjhJ3adCW22YQydoRs5MwTiqxGF9CSYxPxQ7EYb4jLNlIs+E+A==
+"@typescript-eslint/eslint-plugin@5.20.0":
+ version "5.20.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.20.0.tgz#022531a639640ff3faafaf251d1ce00a2ef000a1"
+ integrity sha512-fapGzoxilCn3sBtC6NtXZX6+P/Hef7VDbyfGqTTpzYydwhlkevB+0vE0EnmHPVTVSy68GUncyJ/2PcrFBeCo5Q==
dependencies:
- "@typescript-eslint/scope-manager" "5.18.0"
- "@typescript-eslint/type-utils" "5.18.0"
- "@typescript-eslint/utils" "5.18.0"
+ "@typescript-eslint/scope-manager" "5.20.0"
+ "@typescript-eslint/type-utils" "5.20.0"
+ "@typescript-eslint/utils" "5.20.0"
debug "^4.3.2"
functional-red-black-tree "^1.0.1"
ignore "^5.1.8"
@@ -860,69 +870,69 @@
semver "^7.3.5"
tsutils "^3.21.0"
-"@typescript-eslint/parser@5.18.0":
- version "5.18.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.18.0.tgz#2bcd4ff21df33621df33e942ccb21cb897f004c6"
- integrity sha512-+08nYfurBzSSPndngnHvFw/fniWYJ5ymOrn/63oMIbgomVQOvIDhBoJmYZ9lwQOCnQV9xHGvf88ze3jFGUYooQ==
+"@typescript-eslint/parser@5.20.0":
+ version "5.20.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.20.0.tgz#4991c4ee0344315c2afc2a62f156565f689c8d0b"
+ integrity sha512-UWKibrCZQCYvobmu3/N8TWbEeo/EPQbS41Ux1F9XqPzGuV7pfg6n50ZrFo6hryynD8qOTTfLHtHjjdQtxJ0h/w==
dependencies:
- "@typescript-eslint/scope-manager" "5.18.0"
- "@typescript-eslint/types" "5.18.0"
- "@typescript-eslint/typescript-estree" "5.18.0"
+ "@typescript-eslint/scope-manager" "5.20.0"
+ "@typescript-eslint/types" "5.20.0"
+ "@typescript-eslint/typescript-estree" "5.20.0"
debug "^4.3.2"
-"@typescript-eslint/scope-manager@5.18.0":
- version "5.18.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.18.0.tgz#a7d7b49b973ba8cebf2a3710eefd457ef2fb5505"
- integrity sha512-C0CZML6NyRDj+ZbMqh9FnPscg2PrzSaVQg3IpTmpe0NURMVBXlghGZgMYqBw07YW73i0MCqSDqv2SbywnCS8jQ==
+"@typescript-eslint/scope-manager@5.20.0":
+ version "5.20.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.20.0.tgz#79c7fb8598d2942e45b3c881ced95319818c7980"
+ integrity sha512-h9KtuPZ4D/JuX7rpp1iKg3zOH0WNEa+ZIXwpW/KWmEFDxlA/HSfCMhiyF1HS/drTICjIbpA6OqkAhrP/zkCStg==
dependencies:
- "@typescript-eslint/types" "5.18.0"
- "@typescript-eslint/visitor-keys" "5.18.0"
+ "@typescript-eslint/types" "5.20.0"
+ "@typescript-eslint/visitor-keys" "5.20.0"
-"@typescript-eslint/type-utils@5.18.0":
- version "5.18.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.18.0.tgz#62dbfc8478abf36ba94a90ddf10be3cc8e471c74"
- integrity sha512-vcn9/6J5D6jtHxpEJrgK8FhaM8r6J1/ZiNu70ZUJN554Y3D9t3iovi6u7JF8l/e7FcBIxeuTEidZDR70UuCIfA==
+"@typescript-eslint/type-utils@5.20.0":
+ version "5.20.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.20.0.tgz#151c21cbe9a378a34685735036e5ddfc00223be3"
+ integrity sha512-WxNrCwYB3N/m8ceyoGCgbLmuZwupvzN0rE8NBuwnl7APgjv24ZJIjkNzoFBXPRCGzLNkoU/WfanW0exvp/+3Iw==
dependencies:
- "@typescript-eslint/utils" "5.18.0"
+ "@typescript-eslint/utils" "5.20.0"
debug "^4.3.2"
tsutils "^3.21.0"
-"@typescript-eslint/types@5.18.0":
- version "5.18.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.18.0.tgz#4f0425d85fdb863071680983853c59a62ce9566e"
- integrity sha512-bhV1+XjM+9bHMTmXi46p1Led5NP6iqQcsOxgx7fvk6gGiV48c6IynY0apQb7693twJDsXiVzNXTflhplmaiJaw==
+"@typescript-eslint/types@5.20.0":
+ version "5.20.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.20.0.tgz#fa39c3c2aa786568302318f1cb51fcf64258c20c"
+ integrity sha512-+d8wprF9GyvPwtoB4CxBAR/s0rpP25XKgnOvMf/gMXYDvlUC3rPFHupdTQ/ow9vn7UDe5rX02ovGYQbv/IUCbg==
-"@typescript-eslint/typescript-estree@5.18.0":
- version "5.18.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.18.0.tgz#6498e5ee69a32e82b6e18689e2f72e4060986474"
- integrity sha512-wa+2VAhOPpZs1bVij9e5gyVu60ReMi/KuOx4LKjGx2Y3XTNUDJgQ+5f77D49pHtqef/klglf+mibuHs9TrPxdQ==
+"@typescript-eslint/typescript-estree@5.20.0":
+ version "5.20.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.20.0.tgz#ab73686ab18c8781bbf249c9459a55dc9417d6b0"
+ integrity sha512-36xLjP/+bXusLMrT9fMMYy1KJAGgHhlER2TqpUVDYUQg4w0q/NW/sg4UGAgVwAqb8V4zYg43KMUpM8vV2lve6w==
dependencies:
- "@typescript-eslint/types" "5.18.0"
- "@typescript-eslint/visitor-keys" "5.18.0"
+ "@typescript-eslint/types" "5.20.0"
+ "@typescript-eslint/visitor-keys" "5.20.0"
debug "^4.3.2"
globby "^11.0.4"
is-glob "^4.0.3"
semver "^7.3.5"
tsutils "^3.21.0"
-"@typescript-eslint/utils@5.18.0":
- version "5.18.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.18.0.tgz#27fc84cf95c1a96def0aae31684cb43a37e76855"
- integrity sha512-+hFGWUMMri7OFY26TsOlGa+zgjEy1ssEipxpLjtl4wSll8zy85x0GrUSju/FHdKfVorZPYJLkF3I4XPtnCTewA==
+"@typescript-eslint/utils@5.20.0":
+ version "5.20.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.20.0.tgz#b8e959ed11eca1b2d5414e12417fd94cae3517a5"
+ integrity sha512-lHONGJL1LIO12Ujyx8L8xKbwWSkoUKFSO+0wDAqGXiudWB2EO7WEUT+YZLtVbmOmSllAjLb9tpoIPwpRe5Tn6w==
dependencies:
"@types/json-schema" "^7.0.9"
- "@typescript-eslint/scope-manager" "5.18.0"
- "@typescript-eslint/types" "5.18.0"
- "@typescript-eslint/typescript-estree" "5.18.0"
+ "@typescript-eslint/scope-manager" "5.20.0"
+ "@typescript-eslint/types" "5.20.0"
+ "@typescript-eslint/typescript-estree" "5.20.0"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
-"@typescript-eslint/visitor-keys@5.18.0":
- version "5.18.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.18.0.tgz#c7c07709823804171d569017f3b031ced7253e60"
- integrity sha512-Hf+t+dJsjAKpKSkg3EHvbtEpFFb/1CiOHnvI8bjHgOD4/wAw3gKrA0i94LrbekypiZVanJu3McWJg7rWDMzRTg==
+"@typescript-eslint/visitor-keys@5.20.0":
+ version "5.20.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.20.0.tgz#70236b5c6b67fbaf8b2f58bf3414b76c1e826c2a"
+ integrity sha512-1flRpNF+0CAQkMNlTJ6L/Z5jiODG/e5+7mk6XwtPOUS3UrTz3UOiAg9jG2VtKsWI6rZQfy4C6a232QNRZTRGlg==
dependencies:
- "@typescript-eslint/types" "5.18.0"
+ "@typescript-eslint/types" "5.20.0"
eslint-visitor-keys "^3.0.0"
"@ungap/promise-all-settled@1.1.2":
@@ -1131,13 +1141,13 @@ archiver-utils@^2.1.0:
normalize-path "^3.0.0"
readable-stream "^2.0.0"
-archiver@5.3.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.0.tgz#dd3e097624481741df626267564f7dd8640a45ba"
- integrity sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==
+archiver@5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.1.tgz#21e92811d6f09ecfce649fbefefe8c79e57cbbb6"
+ integrity sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==
dependencies:
archiver-utils "^2.1.0"
- async "^3.2.0"
+ async "^3.2.3"
buffer-crc32 "^0.2.1"
readable-stream "^3.6.0"
readdir-glob "^1.0.0"
@@ -1244,10 +1254,10 @@ async@^2.6.0:
dependencies:
lodash "^4.17.14"
-async@^3.2.0:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/async/-/async-3.2.1.tgz#d3274ec66d107a47476a4c49136aacdb00665fc8"
- integrity sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==
+async@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9"
+ integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==
asynckit@^0.4.0:
version "0.4.0"
@@ -1266,10 +1276,10 @@ autwh@0.1.0:
dependencies:
oauth "0.9.15"
-aws-sdk@2.1111.0:
- version "2.1111.0"
- resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1111.0.tgz#02b1e5c530ef8140235ee7c48c710bb2dbd7dc84"
- integrity sha512-WRyNcCckzmu1djTAWfR2r+BuI/PbuLrhG3oa+oH39v4NZ4EecYWFL1CoCPlC2kRUML4maSba5T4zlxjcNl7ELQ==
+aws-sdk@2.1120.0:
+ version "2.1120.0"
+ resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1120.0.tgz#a299f595448019c4b4b69fa9aa57fd58658497a6"
+ integrity sha512-3cKXUFxC3CDBbJ/JlXEKmJZKFZhqGii7idGaLxvV5/OzqEDUstYkHGX3TCJdQRHrRwpFvRVOekXSwLxBltqXuQ==
dependencies:
buffer "4.9.2"
events "1.1.1"
@@ -1327,11 +1337,6 @@ bcryptjs@2.4.3:
resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb"
integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=
-big-integer@^1.6.16:
- version "1.6.48"
- resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e"
- integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==
-
big-integer@^1.6.17:
version "1.6.51"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
@@ -1404,15 +1409,14 @@ braces@^3.0.1, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
-broadcast-channel@4.10.0:
- version "4.10.0"
- resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-4.10.0.tgz#d19fb902df227df40b1b580351713d30c302d198"
- integrity sha512-hOUh312XyHk6JTVyX9cyXaH1UYs+2gHVtnW16oQAu9FL7ALcXGXc/YoJWqlkV8vUn14URQPMmRi4A9q4UrwVEQ==
+broadcast-channel@4.11.0:
+ version "4.11.0"
+ resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-4.11.0.tgz#b9ebc7ce1326120088e61d2197477496908a1a9e"
+ integrity sha512-4FS1Zk+ttekfXHq5I2R7KhN9AsnZUFVV5SczrTtnZPuf5w+jw+fqM1PJHuHzwEXJezJeCbJxoZMDcFqsIN2c1Q==
dependencies:
"@babel/runtime" "^7.16.0"
detect-node "^2.1.0"
- microseconds "0.2.0"
- nano-time "1.0.0"
+ microtime "3.0.0"
oblivious-set "1.0.0"
p-queue "6.6.2"
rimraf "3.0.2"
@@ -1490,10 +1494,10 @@ bufferutil@^4.0.1:
dependencies:
node-gyp-build "~3.7.0"
-bull@4.8.1:
- version "4.8.1"
- resolved "https://registry.yarnpkg.com/bull/-/bull-4.8.1.tgz#83daaefc3118876450b21d7a02bc11ea28a2440e"
- integrity sha512-ojH5AfOchKQsQwwE+thViS1pMpvREGC+Ov1+3HXsQqn5Q27ZSGkgMriMqc6c9J9rvQ/+D732pZE+TN1+2LRWVg==
+bull@4.8.2:
+ version "4.8.2"
+ resolved "https://registry.yarnpkg.com/bull/-/bull-4.8.2.tgz#0d02fe389777abe29d50fd46d123bc62e074cfcd"
+ integrity sha512-S7CNIL9+vsbLKwOGkUI6mawY5iABKQJLZn5a7KPnxAZrDhFXkrxsHHXLCKUR/+Oqys3Vk5ElWdj0SLtK84b1Nw==
dependencies:
cron-parser "^4.2.1"
debuglog "^1.0.0"
@@ -1586,11 +1590,6 @@ cacheable-request@^7.0.2:
normalize-url "^6.0.1"
responselike "^2.0.0"
-cafy@15.2.1:
- version "15.2.1"
- resolved "https://registry.yarnpkg.com/cafy/-/cafy-15.2.1.tgz#5a55eaeb721c604c7dca652f3d555c392e5f995a"
- integrity sha512-g2zOmFb63p6XcZ/zeMWKYP8YKQYNWnhJmi6K71Ql4EAFTAay31xF0PBPtdBCCfQ0fiETgWTMxKtySAVI/Od6aQ==
-
call-bind@^1.0.0, call-bind@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
@@ -1859,10 +1858,10 @@ color-support@^1.1.2:
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
-color@^4.2.1:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/color/-/color-4.2.1.tgz#498aee5fce7fc982606c8875cab080ac0547c884"
- integrity sha512-MFJr0uY4RvTQUKvPq7dh9grVOTYSFeXja2mBXioCGjnjJoXrAp9jJ1NQTDR73c9nwBSAQiNKloKl5zq9WB9UPw==
+color@^4.2.3:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a"
+ integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==
dependencies:
color-convert "^2.0.1"
color-string "^1.9.0"
@@ -2710,12 +2709,12 @@ eslint-visitor-keys@^3.3.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
-eslint@8.13.0:
- version "8.13.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.13.0.tgz#6fcea43b6811e655410f5626cfcf328016badcd7"
- integrity sha512-D+Xei61eInqauAyTJ6C0q6x9mx7kTUC1KZ0m0LSEexR0V+e94K12LmWX076ZIsldwfQ2RONdaJe0re0TRGQbRQ==
+eslint@8.14.0:
+ version "8.14.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.14.0.tgz#62741f159d9eb4a79695b28ec4989fcdec623239"
+ integrity sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==
dependencies:
- "@eslint/eslintrc" "^1.2.1"
+ "@eslint/eslintrc" "^1.2.2"
"@humanwhocodes/config-array" "^0.9.2"
ajv "^6.10.0"
chalk "^4.0.0"
@@ -3700,10 +3699,10 @@ ip-address@^7.1.0:
jsbn "1.1.0"
sprintf-js "1.1.2"
-ip-cidr@3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/ip-cidr/-/ip-cidr-3.0.4.tgz#a915c47e00f47ea8d5f8ed662ea6161471c44375"
- integrity sha512-pKNiqmBlTvEkhaLAa3+FOmYSY0/jjADVxxjA3NbujZZTT8mjLI90Q+6mwg6kd0fNm0RuAOkWJ1u1a/ETmlrPNQ==
+ip-cidr@3.0.7:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/ip-cidr/-/ip-cidr-3.0.7.tgz#22708dd4f2d3f6397c0fb7d647b44e3c565937e9"
+ integrity sha512-0cBBICDnmmpAdULMbMVdi4f0mSG+VWY/QBPL/OIIjuom14x7Y63VhpS/uSAOycasXOeGXah5y0eu//PDU51aNw==
dependencies:
ip-address "^7.1.0"
jsbn "^1.1.0"
@@ -4172,10 +4171,10 @@ jsprim@^2.0.2:
json-schema "0.4.0"
verror "1.10.0"
-jsrsasign@8.0.20:
- version "8.0.20"
- resolved "https://registry.yarnpkg.com/jsrsasign/-/jsrsasign-8.0.20.tgz#37d8029c9d8f794d8ac8d8998bce319921491f11"
- integrity sha512-JTXt9+nqdynIB8wFsS6e8ffHhIjilhywXwdaEVHSj9OVmwldG2H0EoCqkQ+KXkm2tVqREfH/HEmklY4k1/6Rcg==
+jsrsasign@10.5.19:
+ version "10.5.19"
+ resolved "https://registry.yarnpkg.com/jsrsasign/-/jsrsasign-10.5.19.tgz#61cd378190c3e65bd1a26a088696736e4437a806"
+ integrity sha512-GgOdly2Ee9nS+qxOjLkQKaoSTKqlk6lFKcKLPlNJOApoOUcqL2z+l4dAcBzYnZkA3tg+LwFOyQnqbuFn5IPdvw==
jstransformer@1.0.0:
version "1.0.0"
@@ -4573,11 +4572,6 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
-lru-cache@^7.4.0:
- version "7.8.1"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.8.1.tgz#68ee3f4807a57d2ba185b7fd90827d5c21ce82bb"
- integrity sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==
-
luxon@^1.28.0:
version "1.28.0"
resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf"
@@ -4655,10 +4649,13 @@ micromatch@^4.0.0, micromatch@^4.0.2:
braces "^3.0.1"
picomatch "^2.0.5"
-microseconds@0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39"
- integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==
+microtime@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/microtime/-/microtime-3.0.0.tgz#d140914bde88aa89b4f9fd2a18620b435af0f39b"
+ integrity sha512-SirJr7ZL4ow2iWcb54bekS4aWyBQNVcEDBiwAz9D/sTgY59A+uE8UJU15cp5wyZmPBwg/3zf8lyCJ5NUe1nVlQ==
+ dependencies:
+ node-addon-api "^1.2.0"
+ node-gyp-build "^3.8.0"
mime-db@1.44.0:
version "1.44.0"
@@ -4846,9 +4843,9 @@ mocha@9.2.2:
yargs-unparser "2.0.0"
moment@^2.22.2:
- version "2.24.0"
- resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
- integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
+ version "2.29.3"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.3.tgz#edd47411c322413999f7a5940d526de183c031f3"
+ integrity sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==
ms@2.0.0:
version "2.0.0"
@@ -4918,13 +4915,6 @@ nan@^2.14.2, nan@^2.15.0:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee"
integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==
-nano-time@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef"
- integrity sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8=
- dependencies:
- big-integer "^1.6.16"
-
nanoid@3.3.1, nanoid@^3.1.30:
version "3.3.1"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35"
@@ -4976,6 +4966,11 @@ node-abi@^3.3.0:
dependencies:
semver "^7.3.5"
+node-addon-api@^1.2.0:
+ version "1.7.2"
+ resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d"
+ integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==
+
node-addon-api@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f"
@@ -5019,6 +5014,11 @@ node-fetch@^2.6.1:
dependencies:
whatwg-url "^5.0.0"
+node-gyp-build@^3.8.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-3.9.0.tgz#53a350187dd4d5276750da21605d1cb681d09e25"
+ integrity sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A==
+
node-gyp-build@^4.2.3:
version "4.3.0"
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
@@ -6213,12 +6213,12 @@ seedrandom@3.0.5:
resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7"
integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==
-semver@7.3.6:
- version "7.3.6"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.6.tgz#5d73886fb9c0c6602e79440b97165c29581cbb2b"
- integrity sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==
+semver@7.3.7, semver@^7.3.7:
+ version "7.3.7"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
+ integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
dependencies:
- lru-cache "^7.4.0"
+ lru-cache "^6.0.0"
semver@^5.6.0:
version "5.7.1"
@@ -6274,16 +6274,16 @@ sha.js@^2.4.11:
inherits "^2.0.1"
safe-buffer "^5.0.1"
-sharp@0.30.3:
- version "0.30.3"
- resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.30.3.tgz#315a1817423a4d1cde5119a21c99c234a7a6fb37"
- integrity sha512-rjpfJFK58ZOFSG8sxYSo3/JQb4ej095HjXp9X7gVu7gEn1aqSG8TCW29h/Rr31+PXrFADo1H/vKfw0uhMQWFtg==
+sharp@0.30.4:
+ version "0.30.4"
+ resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.30.4.tgz#73d9daa63bbc20da189c9328d75d5d395fc8fb73"
+ integrity sha512-3Onig53Y6lji4NIZo69s14mERXXY/GV++6CzOYx/Rd8bnTwbhFbL09WZd7Ag/CCnA0WxFID8tkY0QReyfL6v0Q==
dependencies:
- color "^4.2.1"
+ color "^4.2.3"
detect-libc "^2.0.1"
node-addon-api "^4.3.0"
prebuild-install "^7.0.1"
- semver "^7.3.5"
+ semver "^7.3.7"
simple-get "^4.0.1"
tar-fs "^2.1.1"
tunnel-agent "^0.6.0"
@@ -6642,10 +6642,10 @@ syslog-pro@1.0.0:
dependencies:
moment "^2.22.2"
-systeminformation@5.11.9:
- version "5.11.9"
- resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.11.9.tgz#95f2334e739dd224178948a2afaced7d9abfdf9d"
- integrity sha512-eeMtL9UJFR/LYG+2rpeAgZ0Va4ojlNQTkYiQH/xbbPwDjDMsaetj3Pkc+C1aH5G8mav6HvDY8kI4Vl4noksSkA==
+systeminformation@5.11.14:
+ version "5.11.14"
+ resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.11.14.tgz#21fcb6f05d33e17d69c236b9c1b3d9c53d1d2b3a"
+ integrity sha512-m8CJx3fIhKohanB0ExTk5q53uI1J0g5B09p77kU+KxnxRVpADVqTAwCg1PFelqKsj4LHd+qmVnumb511Hg4xow==
tapable@^2.2.0:
version "2.2.0"
@@ -6952,10 +6952,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-typeorm@0.3.5:
- version "0.3.5"
- resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.5.tgz#8fe50d517de5ec6f4b38856ea0f180e4a60cf7e4"
- integrity sha512-KL4c8nQqouHaXs4m1J3xh7oXWqX4+A9poExbceLxBRtlavpJQYqiSnqt3JYGpy7Tl9vD5DG5DrmZrSslTkkW5Q==
+typeorm@0.3.6:
+ version "0.3.6"
+ resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.6.tgz#65203443a1b684bb746785913fe2b0877aa991c0"
+ integrity sha512-DRqgfqcelMiGgWSMbBmVoJNFN2nPNA3EeY2gC324ndr2DZoGRTb9ILtp2oGVGnlA+cu5zgQ6it5oqKFNkte7Aw==
dependencies:
"@sqltools/formatter" "^1.2.2"
app-root-path "^3.0.0"
@@ -7297,10 +7297,10 @@ ws@^8.2.3:
resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.2.tgz#18e749868d8439f2268368829042894b6907aa0b"
integrity sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==
-xev@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/xev/-/xev-2.0.1.tgz#24484173a22115bc8a990ef5d4d5129695b827a7"
- integrity sha512-icDf9M67bDge0F2qf02WKZq+s7mMO/SbPv67ZQPym6JThLEOdlWWLdB7VTVgRJp3ekgaiVItCAyH6aoKCPvfIA==
+xev@3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/xev/-/xev-3.0.2.tgz#3f4080bd8bed0d3479c674050e3696da98d22a4d"
+ integrity sha512-8kxuH95iMXzHZj+fwqfA4UrPcYOy6bGIgfWzo9Ji23JoEc30ge/Z++Ubkiuy8c0+M64nXmmxrmJ7C8wnuBhluw==
xml-js@^1.6.11:
version "1.6.11"