diff --git a/cspell.json b/cspell.json index f00cc37bc863..d495d141caa5 100644 --- a/cspell.json +++ b/cspell.json @@ -352,6 +352,7 @@ "openocean", "OPENOCEAN", "pkts", + "plusplus", "pnpm", "poap", "poaps", diff --git a/jest.config.ts b/jest.config.ts index d089e951e89a..5090118f0241 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -24,6 +24,7 @@ const config: InitialOptionsTsJest = { extensionsToTreatAsEsm: ['.ts', '.tsx'], moduleNameMapper: { '@masknet/shared-base': '/packages/shared-base/src/index.ts', + '@masknet/typed-message/base': '/packages/typed-message/base/index.ts', 'jest-websocket-mock': '/packages/web3-shared/base/node_modules/jest-websocket-mock', 'reconnecting-websocket': '/packages/web3-shared/base/node_modules/reconnecting-websocket', 'date-fns/(.*)': '/packages/web3-shared/base/node_modules/date-fns/$1', diff --git a/packages/encryption/package.json b/packages/encryption/package.json index ab0835efd498..60d532970342 100644 --- a/packages/encryption/package.json +++ b/packages/encryption/package.json @@ -7,6 +7,7 @@ "dependencies": { "@dimensiondev/stego-js": "0.11.1-20201027083223-8ab41be", "@masknet/shared-base": "workspace:*", + "@masknet/typed-message": "workspace:*", "@msgpack/msgpack": "^2.7.0" } } diff --git a/packages/encryption/src/encryption/Decryption.ts b/packages/encryption/src/encryption/Decryption.ts index e88eb168adb8..33b33a19d13c 100644 --- a/packages/encryption/src/encryption/Decryption.ts +++ b/packages/encryption/src/encryption/Decryption.ts @@ -1,11 +1,6 @@ import { unreachable } from '@dimensiondev/kit' -import { - decodeTypedMessageFromDocument, - decodeTypedMessageV38ToV40Format, - AESCryptoKey, - EC_Public_CryptoKey, - andThenAsync, -} from '@masknet/shared-base' +import { decodeTypedMessageFromDocument, decodeTypedMessageV38ToV40Format } from '@masknet/typed-message/base' +import { AESCryptoKey, EC_Public_CryptoKey, andThenAsync } from '@masknet/shared-base' import { None, Result } from 'ts-results' import { AESAlgorithmEnum, PayloadParseResult } from '../payload' import { decryptWithAES, importAESFromJWK } from '../utils' diff --git a/packages/encryption/src/encryption/DecryptionTypes.ts b/packages/encryption/src/encryption/DecryptionTypes.ts index 882ad19b8451..fd7ca4dc4896 100644 --- a/packages/encryption/src/encryption/DecryptionTypes.ts +++ b/packages/encryption/src/encryption/DecryptionTypes.ts @@ -1,5 +1,7 @@ -import type { TypedMessage, ProfileIdentifier, AESCryptoKey, EC_Public_CryptoKey } from '@masknet/shared-base' +import type { TypedMessage } from '@masknet/typed-message/base' +import type { ProfileIdentifier, AESCryptoKey, EC_Public_CryptoKey } from '@masknet/shared-base' import type { PayloadParseResult } from '../payload' +import { registerSerializableClass } from '@masknet/shared-base' export interface DecryptOptions { message: PayloadParseResult.Payload @@ -150,6 +152,7 @@ export enum ErrorReasons { // Not used in this library. UnrecognizedAuthor = '[@masknet/encryption] No author is recognized which is required for the image steganography decoding.', CurrentProfileDoesNotConnectedToPersona = '[@masknet/encryption] Cannot decrypt by E2E because no persona is linked with the current profile.', + NoPayloadFound = '[@masknet/encryption] No payload found in this material.', } export class DecryptError extends Error { static Reasons = ErrorReasons @@ -158,3 +161,18 @@ export class DecryptError extends Error { super(message, { cause }) } } +registerSerializableClass( + 'MaskDecryptError', + (x) => x instanceof DecryptError, + (e: DecryptError) => ({ + cause: (e as any).cause, + recoverable: e.recoverable, + message: e.message, + stack: e.stack, + }), + (o) => { + const e = new DecryptError(o.message, o.cause, o.recoverable) + e.stack = o.stack + return e + }, +) diff --git a/packages/encryption/src/encryption/Encryption.ts b/packages/encryption/src/encryption/Encryption.ts index e7e1307085ed..64a44482bf43 100644 --- a/packages/encryption/src/encryption/Encryption.ts +++ b/packages/encryption/src/encryption/Encryption.ts @@ -1,7 +1,6 @@ import type { PersonaIdentifier, ProfileIdentifier, - TypedMessage, AESCryptoKey, PostIVIdentifier, EC_Public_CryptoKey, @@ -9,6 +8,7 @@ import type { ECKeyIdentifier, IdentifierMap, } from '@masknet/shared-base' +import type { TypedMessage } from '@masknet/typed-message/base' export interface EncryptOptions { /** Payload version to use. */ diff --git a/packages/encryption/src/image-steganography/index.ts b/packages/encryption/src/image-steganography/index.ts index 24d796f19516..baf1a29d041d 100644 --- a/packages/encryption/src/image-steganography/index.ts +++ b/packages/encryption/src/image-steganography/index.ts @@ -93,7 +93,7 @@ export async function steganographyEncodeImage(buf: ArrayBuffer, options: Encode export type DecodeImageOptions = SteganographyIO & Partial & Pick -async function steganographyDecodeImage(buf: ArrayBuffer, options: DecodeImageOptions) { +async function inner(buf: ArrayBuffer, options: DecodeImageOptions) { const dimension = getDimension(buf) const preset = dimensionPreset.find((d) => isSameDimension(d, dimension)) if (!preset) return '' @@ -104,6 +104,6 @@ async function steganographyDecodeImage(buf: ArrayBuffer, options: DecodeImageOp }) } -export async function steganographyDecodeImageUrl(url: string, options: DecodeImageOptions) { - return steganographyDecodeImage(await options.downloadImage(url), options) +export async function steganographyDecodeImage(image: Blob | string, options: DecodeImageOptions) { + return inner(typeof image === 'string' ? await options.downloadImage(image) : await image.arrayBuffer(), options) } diff --git a/packages/encryption/src/index.ts b/packages/encryption/src/index.ts index 8b56b2dbb8df..b38c59a7c6e6 100644 --- a/packages/encryption/src/index.ts +++ b/packages/encryption/src/index.ts @@ -37,7 +37,7 @@ export { type EncodeImageOptions, type ImageTemplateTypes, type SteganographyIO, - steganographyDecodeImageUrl, + steganographyDecodeImage, steganographyEncodeImage, GrayscaleAlgorithm, } from './image-steganography' diff --git a/packages/encryption/src/payload/types.ts b/packages/encryption/src/payload/types.ts index dc09dcbc78bb..b108fd0adbdd 100644 --- a/packages/encryption/src/payload/types.ts +++ b/packages/encryption/src/payload/types.ts @@ -116,12 +116,14 @@ export enum AESAlgorithmEnum { A256GCM = 'A256GCM', } export enum SocialNetworkEnum { + Unknown = -1, Facebook = 0, Twitter = 1, Instagram = 2, Minds = 3, } const SocialNetworkEnumToDomain: Record = { + [SocialNetworkEnum.Unknown]: 'localhost', [SocialNetworkEnum.Facebook]: 'facebook.com', [SocialNetworkEnum.Minds]: 'minds.com', [SocialNetworkEnum.Twitter]: 'twitter.com', diff --git a/packages/encryption/src/social-network-encode-decode/index.ts b/packages/encryption/src/social-network-encode-decode/index.ts index 975ed6eb58cd..bee0b7b51ff8 100644 --- a/packages/encryption/src/social-network-encode-decode/index.ts +++ b/packages/encryption/src/social-network-encode-decode/index.ts @@ -1,10 +1,14 @@ -import { Some } from 'ts-results' import { SocialNetworkEnum } from '../payload/types' import { TwitterDecoder, __TwitterEncoder } from './twitter' -export function socialNetworkDecoder(network: SocialNetworkEnum, content: string) { - if (network === SocialNetworkEnum.Twitter) return TwitterDecoder(content) - return Some(content) +export function socialNetworkDecoder(network: SocialNetworkEnum, content: string): string[] { + if (network === SocialNetworkEnum.Twitter) + return TwitterDecoder(content) + .map((x) => [x]) + .unwrapOr([]) + const all = content.match(/(\u{1F3BC}[\w+/=|]+:\|\|)/giu) + if (all) return all + return [] } export function socialNetworkEncoder(network: SocialNetworkEnum, content: string) { if (network === SocialNetworkEnum.Twitter) return __TwitterEncoder(content) diff --git a/packages/encryption/tsconfig.json b/packages/encryption/tsconfig.json index 3d48a608ba0d..7da8d9a0c2c3 100644 --- a/packages/encryption/tsconfig.json +++ b/packages/encryption/tsconfig.json @@ -7,5 +7,5 @@ "stripInternal": true }, "include": ["./src/**/*"], - "references": [{ "path": "../shared-base" }] + "references": [{ "path": "../shared-base" }, { "path": "../typed-message/base" }] } diff --git a/packages/gun-utils/README.md b/packages/gun-utils/README.md new file mode 100644 index 000000000000..f0e4438fc48c --- /dev/null +++ b/packages/gun-utils/README.md @@ -0,0 +1,13 @@ +# @masknet/gun-utils + +This packages wrap Gun with a developer-friendly API. Before using, please make sure you have understand: + +- Gun is a decentralized graph database. +- There're many other applications are using Gun. +- Every change is visible to others (may not be correct, but in our use cases it is). +- There is no "private server", you cannot create a fresh "gun" world that only contains our data. +- DO NOT publish sensitive information on Gun. + +For more information, please access https://gun.eco/. + +It is especially important to understand how Gun is modeling "Array of data". diff --git a/packages/gun-utils/package.json b/packages/gun-utils/package.json new file mode 100644 index 000000000000..acfcfb609881 --- /dev/null +++ b/packages/gun-utils/package.json @@ -0,0 +1,11 @@ +{ + "name": "@masknet/gun-utils", + "private": true, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "type": "module", + "dependencies": { + "event-iterator": "^2.0.0", + "gun": "^0.2020.1234" + } +} diff --git a/packages/gun-utils/src/index.ts b/packages/gun-utils/src/index.ts new file mode 100644 index 000000000000..49e0187f9ea3 --- /dev/null +++ b/packages/gun-utils/src/index.ts @@ -0,0 +1 @@ +export { deleteGunData, getGunData, pushToGunDataArray, setGunData, subscribeGunMapData } from './utils' diff --git a/packages/gun-utils/src/instance.ts b/packages/gun-utils/src/instance.ts new file mode 100644 index 000000000000..26abf595dad5 --- /dev/null +++ b/packages/gun-utils/src/instance.ts @@ -0,0 +1,48 @@ +import Gun from 'gun' +import 'gun/sea' +import 'gun/lib/radix' +import 'gun/lib/radisk' +import 'gun/lib/store' +import 'gun/lib/rindexed' +import { gunServers } from './server' + +export type GunRoot = ReturnType +let gun: GunRoot | undefined +export function getGunInstance(): GunRoot { + if (gun) return gun + return (gun = createGun()) +} + +function createGun() { + class WebSocket extends globalThis.WebSocket { + constructor(url: string | URL) { + super(url) + const abort = (this.abort = () => { + gun = undefined + this.close() + console.log('[Network/gun] WebSocket of the Gun instance is killed due to inactive.') + }) + const tick = (this.tick = () => { + if (this.timer) clearTimeout(this.timer) + this.timer = setTimeout(abort, 15 * 60 * 1000) + }) + this.addEventListener('message', tick, {}) + } + private declare abort: () => void + private declare tick: () => void + declare timer: NodeJS.Timer | undefined + override send(data: any) { + this.tick() + super.send(data) + } + } + + const _ = new Gun({ + peers: [...gunServers], + localStorage: false, + radisk: true, + WebSocket, + }) + _.opt({ retry: Number.POSITIVE_INFINITY }) + return _ +} diff --git a/packages/mask/src/network/gun-servers.ts b/packages/gun-utils/src/server.ts similarity index 100% rename from packages/mask/src/network/gun-servers.ts rename to packages/gun-utils/src/server.ts diff --git a/packages/gun-utils/src/utils.ts b/packages/gun-utils/src/utils.ts new file mode 100644 index 000000000000..0a5f27ee4f34 --- /dev/null +++ b/packages/gun-utils/src/utils.ts @@ -0,0 +1,80 @@ +import { EventIterator } from 'event-iterator' +import { getGunInstance } from './instance' + +function getGunNodeFromPath(path: string[]) { + const resultNode = path.reduce((gun, path) => gun.get(path as never), getGunInstance()) + return resultNode +} +/** + * Get data from Gun. Equivalent as the following code: + * + * ```ts + * gun.get(path[0]).get(path[1])....get(path[n]).once() + * ``` + */ +export function getGunData(...path: string[]) { + return new Promise<{ [x: string]: unknown } | string | number | undefined>((resolve) => { + getGunNodeFromPath(path).once(resolve) + }) +} + +/** + * Set data on Gun. Equivalent as the following code: + * + * ```ts + * gun.get(path[0]).get(path[1])....get(path[n]).put(data) + * ``` + * @param path graph path on Gun + * @param data data to be stored + */ +export function setGunData(path: string[], data: any) { + getGunNodeFromPath(path).put(data) +} + +/** + * Delete data on Gun. Equivalent as the following code: + * + * ```ts + * gun.get(path[0]).get(path[1])....get(path[n]).put(null!) + * ``` + * @param path graph path on Gun + */ +export function deleteGunData(path: string[]) { + getGunNodeFromPath(path).put(null!) +} + +/** + * Push data to the Gun data Set (Mathematical Set) + * @param path graph path on Gun + * @param value the object to be stored + */ +export function pushToGunDataArray(path: string[], value: object) { + getGunNodeFromPath(path).set(value) +} + +/** + * Subscribe future data on Gun. + * When subscribing a Gun data Set (Mathematical Set), you will not get the immediate result back. + * + * @param path graph path on Gun + * @param isT is the data type T + * @param abortSignal the signal to stop subscribing + */ +export async function* subscribeGunMapData(path: string[], isT: (x: unknown) => x is T, abortSignal: AbortSignal) { + yield* new EventIterator((queue) => { + // gun.off() will remove ALL listener on it + let listenerClosed = false + + abortSignal.addEventListener('abort', () => { + queue.stop() + listenerClosed = true + }) + + const resultNode = getGunNodeFromPath(path) + + resultNode.map().on((data) => { + if (listenerClosed) return + if (isT(data)) queue.push(data) + }) + }) +} diff --git a/packages/gun-utils/tsconfig.json b/packages/gun-utils/tsconfig.json new file mode 100644 index 000000000000..8bcad252c078 --- /dev/null +++ b/packages/gun-utils/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src/", + "outDir": "./dist/", + "tsBuildInfoFile": "./dist/.tsbuildinfo" + }, + "include": ["./src"], + "references": [] +} diff --git a/packages/mask/.webpack/config.ts b/packages/mask/.webpack/config.ts index 335cd0cdad53..36e4cfe92e15 100644 --- a/packages/mask/.webpack/config.ts +++ b/packages/mask/.webpack/config.ts @@ -66,9 +66,12 @@ export function createConfiguration(rawFlags: BuildFlags): Configuration { // we can speed up the compile because there is no need to wait tsc build them to the dist folder. '@masknet/dashboard$': require.resolve('../../dashboard/src/entry.tsx'), '@masknet/injected-script': join(__dirname, '../../injected-script/sdk'), + '@masknet/gun-utils': join(__dirname, '../../gun-utils/src/'), '@masknet/shared': join(__dirname, '../../shared/src/'), '@masknet/shared-base': join(__dirname, '../../shared-base/src/'), '@masknet/theme': join(__dirname, '../../theme/src/'), + '@masknet/typed-message/base': join(__dirname, '../../typed-message/base/'), + '@masknet/typed-message/dom': join(__dirname, '../../typed-message/dom/'), '@masknet/icons': join(__dirname, '../../icons/index.ts'), '@masknet/web3-kit': join(__dirname, '../../web3-kit/src/'), '@masknet/web3-providers': join(__dirname, '../../web3-providers/src'), diff --git a/packages/mask/background/database/persona/consistency.ts b/packages/mask/background/database/persona/consistency.ts deleted file mode 100644 index 0f0200bcad10..000000000000 --- a/packages/mask/background/database/persona/consistency.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { unreachable } from '@dimensiondev/kit' -import { - type IdentifierMap, - ProfileIdentifier, - type PersonaIdentifier, - Identifier, - ECKeyIdentifier, -} from '@masknet/shared-base' -import { restorePrototype } from '../../../utils-pure' -import type { FullPersonaDBTransaction } from './type' - -type ReadwriteFullPersonaDBTransaction = FullPersonaDBTransaction<'readwrite'> - -/** @internal */ -export async function assertPersonaDBConsistency( - behavior: 'fix' | 'throw', - ...[checkRange, t]: Parameters -): Promise { - const diag: Diagnosis[] = [] - for await (const w of checkFullPersonaDBConsistency(checkRange, t)) { - diag.push(w) - } - if (diag.length) { - const warn = 'PersonaDB is in the inconsistency state' - console.warn(warn) - console.info(await t.objectStore('personas').getAll()) - console.info(await t.objectStore('profiles').getAll()) - console.error(...diag) - if (behavior === 'throw') { - t.abort() - throw new Error(warn) - } else if (t.mode === 'readwrite') { - console.warn('Try to fix the inconsistent db') - for (const each of diag) await fixDBInconsistency(each, t).catch(() => {}) - } - } - return diag -} -async function fixDBInconsistency(diagnosis: Diagnosis, t: ReadwriteFullPersonaDBTransaction) { - const personas = t.objectStore('personas') - const profiles = t.objectStore('profiles') - switch (diagnosis.type) { - case Type.Invalid_Persona: - return personas.delete(diagnosis.invalidPersonaKey) - case Type.Invalid_Profile: - return profiles.delete(diagnosis.invalidProfileKey) - case Type.One_Way_Link_In_Persona: - case Type.Invalid_Persona_LinkedProfiles: { - const rec = await personas.get(diagnosis.persona.toText()) - const profileWantToUnlink = - diagnosis.type === Type.One_Way_Link_In_Persona - ? diagnosis.designatedProfile.toText() - : diagnosis.invalidProfile - rec!.linkedProfiles.delete(profileWantToUnlink) - return personas.put(rec!) - } - case Type.One_Way_Link_In_Profile: - case Type.Invalid_Profile_LinkedPersona: { - const rec = await profiles.get(diagnosis.profile.toText()) - delete rec!.linkedPersona - return profiles.put(rec!) - } - default: - return unreachable(diagnosis) - } -} - -async function* checkFullPersonaDBConsistency( - checkRange: 'full check' | IdentifierMap, - t: ReadwriteFullPersonaDBTransaction, -): AsyncGenerator { - for await (const persona of t.objectStore('personas')) { - const personaID = Identifier.fromString(persona.key, ECKeyIdentifier) - if (personaID.err) { - yield { type: Type.Invalid_Persona, invalidPersonaKey: persona.key, _record: persona.value } - continue - } - if (checkRange === 'full check' || checkRange.has(personaID.val)) { - yield* checkPersonaLink(personaID.val, t) - } - } - - for await (const profile of t.objectStore('profiles')) { - const profileID = Identifier.fromString(profile.key, ProfileIdentifier) - if (profileID.err) { - yield { type: Type.Invalid_Profile, invalidProfileKey: profile.key, _record: profile.value } - } else if (checkRange === 'full check' || checkRange.has(profileID.val)) { - yield* checkProfileLink(profileID.val, t) - } - } -} -async function* checkPersonaLink( - personaID: PersonaIdentifier, - t: ReadwriteFullPersonaDBTransaction, -): AsyncGenerator { - const rec = await t.objectStore('personas').get(personaID.toText()) - const linkedProfiles = rec?.linkedProfiles - if (!linkedProfiles) return - for (const each of linkedProfiles) { - const profileID = Identifier.fromString(each[0], ProfileIdentifier) - if (profileID.err) { - yield { type: Type.Invalid_Persona_LinkedProfiles, invalidProfile: each[0], persona: personaID } - continue - } - const profile = await t.objectStore('profiles').get(profileID.val.toText()) - if (!profile?.linkedPersona) { - yield { - type: Type.One_Way_Link_In_Persona, - persona: personaID, - designatedProfile: profileID.val, - profileActuallyLinkedPersona: profile?.linkedPersona, - } - } - } -} -async function* checkProfileLink( - profile: ProfileIdentifier, - t: ReadwriteFullPersonaDBTransaction, -): AsyncGenerator { - const rec = await t.objectStore('profiles').get(profile.toText()) - const invalidLinkedPersona = rec?.linkedPersona - if (!invalidLinkedPersona) return - if (invalidLinkedPersona.type !== 'ec_key') { - yield { type: Type.Invalid_Profile_LinkedPersona, invalidLinkedPersona, profile } - return - } - const designatedPersona = restorePrototype(invalidLinkedPersona, ECKeyIdentifier.prototype) - const persona = await t.objectStore('personas').get(designatedPersona.toText()) - if (!persona) { - yield { type: Type.One_Way_Link_In_Profile, profile, designatedPersona } - } -} - -const enum Type { - Invalid_Persona = 'invalid identifier in persona', - Invalid_Persona_LinkedProfiles = 'invalid identifier in persona.linkedProfiles', - Invalid_Profile = 'invalid identifier in profile', - Invalid_Profile_LinkedPersona = 'invalid identifier in profile.linkedPersona', - One_Way_Link_In_Persona = 'a persona linked to a profile meanwhile the profile is not linked to the persona', - One_Way_Link_In_Profile = 'a profile linked to a persona meanwhile it is not appeared in the persona.linkedProfiles', -} -type Diagnosis = - | { - type: Type.Invalid_Persona - invalidPersonaKey: string - _record: unknown - } - | { - type: Type.Invalid_Persona_LinkedProfiles - persona: PersonaIdentifier - invalidProfile: string - } - | { - type: Type.Invalid_Profile - invalidProfileKey: string - _record: unknown - } - | { - type: Type.Invalid_Profile_LinkedPersona - profile: ProfileIdentifier - invalidLinkedPersona: unknown - } - | { - type: Type.One_Way_Link_In_Persona - persona: PersonaIdentifier - designatedProfile: ProfileIdentifier - profileActuallyLinkedPersona?: unknown - } - | { - type: Type.One_Way_Link_In_Profile - profile: ProfileIdentifier - designatedPersona: PersonaIdentifier - } diff --git a/packages/mask/background/database/persona/helper.ts b/packages/mask/background/database/persona/helper.ts new file mode 100644 index 000000000000..8fde934674a6 --- /dev/null +++ b/packages/mask/background/database/persona/helper.ts @@ -0,0 +1,227 @@ +import { concatArrayBuffer, decodeArrayBuffer } from '@dimensiondev/kit' +import { + AESCryptoKey, + AESJsonWebKey, + ECKeyIdentifier, + ECKeyIdentifierFromJsonWebKey, + EC_Private_JsonWebKey, + EC_Public_CryptoKey, + EC_Public_JsonWebKey, + IdentifierMap, + PersonaIdentifier, + ProfileIdentifier, +} from '@masknet/shared-base' +import type { IDBPSafeTransaction } from '../utils/openDB' +import { + attachProfileDB, + consistentPersonaDBWriteAccess, + createOrUpdatePersonaDB, + createPersonaDB, + LinkedProfileDetails, + PersonaDB, + PersonaRecord, +} from './db' +// TODO: support app +import { createReadonlyPersonaTransaction } from './web' + +// #region Local key helpers +/** + * If has local key of a profile in the database. + * @param id Profile Identifier + */ +export function hasLocalKeyOf( + id: ProfileIdentifier, + tx?: IDBPSafeTransaction, +) { + return getLocalKeyOf(id, tx).then(Boolean) +} + +/** + * Try to decrypt data using local key. + * + * @param authorHint Author of the local key + * @param data Data to be decrypted + * @param iv IV + */ +export async function decryptByLocalKey( + authorHint: ProfileIdentifier | null, + data: Uint8Array, + iv: Uint8Array, +): Promise { + const candidateKeys: AESJsonWebKey[] = [] + search: { + if (!authorHint) break search + const tx = (await createReadonlyPersonaTransaction())('personas', 'profiles') + const key = await getLocalKeyOf(authorHint, tx) + key && candidateKeys.push(key) + // TODO: We may push every local key we owned to the candidate list so we can also decrypt when authorHint is null, but that might be a performance pitfall when localKey field is not indexed. + } + + let check = () => {} + return Promise.any( + candidateKeys.map(async (key): Promise => { + const k = await crypto.subtle.importKey('jwk', key, { name: 'AES-GCM', length: 256 }, false, ['decrypt']) + check() + + const result: Uint8Array = await crypto.subtle.decrypt({ iv, name: 'AES-GCM' }, k, data) + check = abort + return result + }), + ) +} + +async function getLocalKeyOf( + id: ProfileIdentifier, + tx?: IDBPSafeTransaction, +) { + tx ||= (await createReadonlyPersonaTransaction())('personas', 'profiles') + + const profile = await tx.objectStore('profiles').get(id.toText()) + if (!profile) return + if (profile.localKey) return profile.localKey + if (!profile.linkedPersona) return + + const persona = await tx.objectStore('personas').get(profile.linkedPersona.toText()) + return persona?.localKey +} +// #endregion + +// #region ECDH +export async function deriveAESByECDH(pub: EC_Public_CryptoKey, extractable = true) { + const curve = (pub.algorithm as EcKeyAlgorithm).namedCurve || '' + const sameCurvePrivateKeys = new Map() + + db: { + const t = (await createReadonlyPersonaTransaction())('personas') + const hasPriv = await t.objectStore('personas').index('hasPrivateKey').openCursor(IDBKeyRange.only('yes')) + if (hasPriv === null) break db + for await (const { value } of hasPriv) { + if (!value.privateKey) continue + if (value.privateKey.crv !== curve) continue + sameCurvePrivateKeys.set(value.identifier, value.privateKey) + } + } + + const deriveResult = new Map() + const result = await Promise.allSettled( + [...sameCurvePrivateKeys].map(async ([id, key]) => { + const k = await crypto.subtle.importKey( + 'jwk', + key, + { name: 'ECDH', namedCurve: key.crv! } as EcKeyAlgorithm, + false, + ['deriveKey'], + ) + const result = await crypto.subtle.deriveKey( + { name: 'ECDH', public: pub }, + k, + { name: 'AES-GCM', length: 256 }, + extractable, + ['encrypt', 'decrypt'], + ) + deriveResult.set(id, result as AESCryptoKey) + }), + ) + const failed = result.filter((x): x is PromiseRejectedResult => x.status === 'rejected') + if (failed.length) { + console.warn('Failed to ECDH', ...failed.map((x) => x.reason)) + } + return new IdentifierMap(deriveResult, ECKeyIdentifier) +} + +const KEY = decodeArrayBuffer('KEY') +const IV = decodeArrayBuffer('IV') +export async function deriveAESByECDH_version38_or_older( + pub: EC_Public_CryptoKey, + iv: Uint8Array, + extractable = false, +) { + const deriveResult = (await deriveAESByECDH(pub, true)).__raw_map__ + type R = [key: AESCryptoKey, iv: Uint8Array] + const next_map = new Map() + + for (const [id, key] of deriveResult) { + const derivedKeyRaw = await crypto.subtle.exportKey('raw', key) + const _a = concatArrayBuffer(derivedKeyRaw, iv) + const nextAESKeyMaterial = await crypto.subtle.digest('SHA-256', concatArrayBuffer(_a, iv, KEY)) + const iv_pre = new Uint8Array(await crypto.subtle.digest('SHA-256', concatArrayBuffer(_a, iv, IV))) + const nextIV = new Uint8Array(16) + for (let i = 0; i <= 16; i += 1) { + // eslint-disable-next-line no-bitwise + nextIV[i] = iv_pre[i] ^ iv_pre[16 + i] + } + const nextAESKey = await crypto.subtle.importKey( + 'raw', + nextAESKeyMaterial, + { name: 'AES-GCM', length: 256 }, + extractable, + ['encrypt', 'decrypt'], + ) + next_map.set(id, [nextAESKey as AESCryptoKey, nextIV]) + } + + return new IdentifierMap(next_map, ECKeyIdentifier) +} +// #endregion + +// #region normal functions +export async function createPersonaByJsonWebKey(options: { + publicKey: EC_Public_JsonWebKey + privateKey: EC_Private_JsonWebKey + localKey?: AESJsonWebKey + nickname?: string + mnemonic?: PersonaRecord['mnemonic'] + uninitialized?: boolean +}): Promise { + const identifier = ECKeyIdentifierFromJsonWebKey(options.publicKey) + const record: PersonaRecord = { + createdAt: new Date(), + updatedAt: new Date(), + identifier: identifier, + linkedProfiles: new IdentifierMap(new Map(), ProfileIdentifier), + publicKey: options.publicKey, + privateKey: options.privateKey, + nickname: options.nickname, + mnemonic: options.mnemonic, + localKey: options.localKey, + hasLogout: false, + uninitialized: options.uninitialized, + } + await consistentPersonaDBWriteAccess((t) => createPersonaDB(record, t)) + return identifier +} + +export async function createProfileWithPersona( + profileID: ProfileIdentifier, + data: LinkedProfileDetails, + keys: { + nickname?: string + publicKey: EC_Public_JsonWebKey + privateKey?: EC_Private_JsonWebKey + localKey?: AESJsonWebKey + mnemonic?: PersonaRecord['mnemonic'] + }, +): Promise { + const ec_id = ECKeyIdentifierFromJsonWebKey(keys.publicKey) + const rec: PersonaRecord = { + createdAt: new Date(), + updatedAt: new Date(), + identifier: ec_id, + linkedProfiles: new IdentifierMap(new Map(), ProfileIdentifier), + nickname: keys.nickname, + publicKey: keys.publicKey, + privateKey: keys.privateKey, + localKey: keys.localKey, + mnemonic: keys.mnemonic, + hasLogout: false, + } + await consistentPersonaDBWriteAccess(async (t) => { + await createOrUpdatePersonaDB(rec, { explicitUndefinedField: 'ignore', linkedProfiles: 'merge' }, t) + await attachProfileDB(profileID, ec_id, data, t) + }) +} +// #endregion + +function abort() { + throw new Error('Cancelled') +} diff --git a/packages/mask/background/database/persona/web.ts b/packages/mask/background/database/persona/web.ts index 9c07de0168ca..c95745c2f1e8 100644 --- a/packages/mask/background/database/persona/web.ts +++ b/packages/mask/background/database/persona/web.ts @@ -2,7 +2,6 @@ import Fuse from 'fuse.js' import { openDB } from 'idb/with-async-ittr' import { CryptoKeyToJsonWebKey, restorePrototype } from '../../../utils-pure' import { createDBAccessWithAsyncUpgrade, createTransaction } from '../utils/openDB' -import { assertPersonaDBConsistency } from './consistency' import { AESJsonWebKey, ECKeyIdentifier, @@ -144,14 +143,12 @@ export async function createRelationsTransaction() { return createTransaction(database, 'readwrite')('relations') } -// @deprecated Please create a transaction directly +// TODO: rename to holdPersonaEventsWhileTransaction export async function consistentPersonaDBWriteAccess( action: (t: FullPersonaDBTransaction<'readwrite'>) => Promise, - tryToAutoFix = true, ) { - // TODO: collect all changes on this transaction then only perform consistency check on those records. const database = await db() - let t = createTransaction(database, 'readwrite')('profiles', 'personas', 'relations') + const t = createTransaction(database, 'readwrite')('profiles', 'personas', 'relations') let finished = false const finish = () => (finished = true) t.addEventListener('abort', finish) @@ -168,20 +165,10 @@ export async function consistentPersonaDBWriteAccess( if (finished) { console.warn('The transaction ends too early! There MUST be a bug in the program!') console.trace() - // start a new transaction to check consistency - t = createTransaction(database, 'readwrite')('profiles', 'personas', 'relations') - } - try { - await assertPersonaDBConsistency(tryToAutoFix ? 'fix' : 'throw', 'full check', t) - resumeProfile((data) => [data.flat()]) - resumePersona((data) => (data.length ? [undefined] : [])) - resumeRelation((data) => [data.flat()]) - } finally { - // If the consistency check throws, we drop all pending events - resumeProfile(() => []) - resumePersona(() => []) - resumeRelation(() => []) } + resumeProfile((data) => [data.flat()]) + resumePersona((data) => (data.length ? [undefined] : [])) + resumeRelation((data) => [data.flat()]) } } diff --git a/packages/mask/background/network/gun/encryption/queryPostKey.ts b/packages/mask/background/network/gun/encryption/queryPostKey.ts new file mode 100644 index 000000000000..c43cc09b28a7 --- /dev/null +++ b/packages/mask/background/network/gun/encryption/queryPostKey.ts @@ -0,0 +1,186 @@ +import { decodeArrayBuffer, encodeArrayBuffer } from '@dimensiondev/kit' +import type { DecryptStaticECDH_PostKey } from '@masknet/encryption' +import type { EC_Public_CryptoKey, EC_Public_JsonWebKey } from '@masknet/shared-base' +import { CryptoKeyToJsonWebKey } from '../../../../utils-pure' +import { getGunData, pushToGunDataArray, subscribeGunMapData } from '@masknet/gun-utils' +import { EventIterator } from 'event-iterator' +import { noop } from 'lodash-unified' + +// !!! Change how this file access Gun will break the compatibility of v40 payload decryption. +export async function GUN_queryPostKey_version40( + iv: Uint8Array, + whoAmI: string, +): Promise { + // PATH ON GUN: maskbook > posts > iv > userID + const result = await getGunData('maskbook', 'posts', encodeArrayBuffer(iv), whoAmI) + if (!isValidData(result)) return null + return { + encryptedPostKey: new Uint8Array(decodeArrayBuffer(result.encryptedKey)), + postKeyIV: new Uint8Array(decodeArrayBuffer(result.salt)), + } + + type DataOnGun = { encryptedKey: string; salt: string } + function isValidData(x: typeof result): x is DataOnGun { + if (typeof x !== 'object') return false + if (!x) return false + + const { encryptedKey, salt: encryptedKeyIV } = x + if (typeof encryptedKey !== 'string' || typeof encryptedKeyIV !== 'string') return false + return true + } +} + +namespace Version38Or39 { + export async function* GUN_queryPostKey_version39Or38( + version: -38 | -39, + iv: Uint8Array, + minePublicKey: EC_Public_CryptoKey, + networkHint: string, + abortSignal: AbortSignal, + ): AsyncGenerator { + const minePublicKeyJWK = await CryptoKeyToJsonWebKey(minePublicKey) + const { keyHash, postHash } = await calculatePostKeyPartition(version, networkHint, iv, minePublicKeyJWK) + + /* cspell:disable-next-line */ + // ? In this step we get something like ["jzarhbyjtexiE7aB1DvQ", "jzarhuse6xlTAtblKRx9"] + console.log(`[@masknet/encryption] Reading key partition [${postHash}][${keyHash}]`) + const internalNodeNames = Object.keys((await getGunData(postHash, keyHash)) || {}).filter((x) => x !== '_') + // ? In this step we get all keys in this category (gun2[postHash][keyHash]) + const resultPromise = internalNodeNames.map((key) => getGunData(key)) + + const iter = new EventIterator((queue) => { + for (const result of resultPromise) result.then(emit, noop) + + async function main() { + const iter = subscribeGunMapData([postHash], isValidData, abortSignal) + for await (const data of iter) emit(data) + } + + main() + + function emit(result: any) { + if (abortSignal.aborted) return + if (!isValidData(result)) return + queue.push({ + encryptedPostKey: new Uint8Array(decodeArrayBuffer(result.encryptedKey)), + postKeyIV: new Uint8Array(decodeArrayBuffer(result.salt)), + }) + } + }) + yield* iter + } + + export type PublishedAESKeyRecord = { + aesKey: { encryptedKey: string; salt: string } + receiverKey: EC_Public_JsonWebKey + } + + /** + * Publish post keys on the gun + * @param version current payload + * @param postIV Post iv + * @param receiversKeys Keys needs to publish + */ + export async function publishPostAESKey_version39Or38( + version: -39 | -38, + postIV: Uint8Array, + networkHint: string, + receiversKeys: PublishedAESKeyRecord[], + ) { + const postHash = await hashIV(networkHint, postIV) + // Store AES key to gun + receiversKeys.forEach(async ({ aesKey, receiverKey }) => { + const keyHash = await (version === -38 ? hashKey38 : hashKey39)(receiverKey) + console.log(`gun[${postHash}][${keyHash}].push(`, aesKey, ')') + pushToGunDataArray([postHash, keyHash], aesKey) + }) + } + + type DataOnGun = { + encryptedKey: string + salt: string + } + + function isValidData(data: unknown): data is DataOnGun { + if (!data) return false + if (typeof data !== 'object') return false + const { encryptedKey, salt } = data as DataOnGun + if (typeof encryptedKey !== 'string') return false + if (typeof salt !== 'string') return false + return true + } + + async function calculatePostKeyPartition( + version: -38 | -39, + networkHint: string, + iv: Uint8Array, + key: EC_Public_JsonWebKey, + ) { + const postHash = await hashIV(networkHint, iv) + // In version > -39, we will use stable hash to prevent unstable result for key hashing + + const keyHash = version === -39 ? await hashKey39(key) : await hashKey38(key) + return { postHash, keyHash } + } + + async function hashIV(networkHint: string, iv: Uint8Array) { + const hashPair = '9283464d-ee4e-4e8d-a7f3-cf392a88133f' + const N = 2 + + const hash = await work(encodeArrayBuffer(iv), hashPair) + return networkHint + hash.substring(0, N) + } + + // The difference between V38 and V39 is: V39 is not stable (JSON.stringify) + // it's an implementation bug but for backward compatibility, it cannot be changed. + // Therefore we upgraded the version and use a stable hash. + async function hashKey39(key: EC_Public_JsonWebKey) { + const hashPair = '10198a2f-205f-45a6-9987-3488c80113d0' + const N = 2 + + const jwk = JSON.stringify(key) + const hash = await work(jwk, hashPair) + return hash.substring(0, N) + } + + async function hashKey38(jwk: EC_Public_JsonWebKey) { + const hashPair = '10198a2f-205f-45a6-9987-3488c80113d0' + const N = 2 + + const hash = await work(jwk.x! + jwk.y!, hashPair) + return hash.substring(0, N) + } + + // This is a self contained Gun.SEA.work implementation that only contains code path we used. + async function work(data: string, salt: string) { + const key = await crypto.subtle.importKey('raw', new TextEncoder().encode(data), { name: 'PBKDF2' }, false, [ + 'deriveBits', + ]) + const work = await crypto.subtle.deriveBits( + { + name: 'PBKDF2', + iterations: 100000, + salt: new TextEncoder().encode(salt), + hash: { name: 'SHA-256' }, + }, + key, + 512, + ) + const result = arrayBufferToBase64(work) + return result + + function arrayBufferToBase64(buffer: ArrayBuffer) { + let binary = '' + const bytes = new Uint8Array(buffer) + const len = bytes.byteLength + // eslint-disable-next-line no-plusplus + for (let i = 0; i < len; i++) { + binary += String.fromCharCode(bytes[i]) + } + return window.btoa(binary) + } + } +} + +export const { GUN_queryPostKey_version39Or38, publishPostAESKey_version39Or38 } = Version38Or39 +export type PublishedAESKeyRecord_version39Or38 = Version38Or39.PublishedAESKeyRecord diff --git a/packages/mask/background/services/crypto/decryption.ts b/packages/mask/background/services/crypto/decryption.ts new file mode 100644 index 000000000000..10d571ad9cbb --- /dev/null +++ b/packages/mask/background/services/crypto/decryption.ts @@ -0,0 +1,237 @@ +import { encodeArrayBuffer, unreachable } from '@dimensiondev/kit' +import { + decrypt, + parsePayload, + DecryptProgressKind, + PublicKeyAlgorithmEnum, + DecryptProgress, + SocialNetworkEnum, + SocialNetworkEnumToProfileDomain, + AsymmetryCryptoKey, + socialNetworkDecoder, + steganographyDecodeImage, + DecryptError, + ErrorReasons, +} from '@masknet/encryption' +import { + AESCryptoKey, + EC_Public_CryptoKey, + EC_Public_JsonWebKey, + IdentifierMap, + PostIVIdentifier, + ProfileIdentifier, +} from '@masknet/shared-base' +import { noop } from 'lodash-unified' +import { queryPersonaByProfileDB } from '../../database/persona/db' +import { + createProfileWithPersona, + decryptByLocalKey, + deriveAESByECDH, + deriveAESByECDH_version38_or_older, + hasLocalKeyOf, +} from '../../database/persona/helper' +import { queryPostDB } from '../../database/post' +import { savePostKeyToDB } from '../../database/post/helper' +import { GUN_queryPostKey_version39Or38, GUN_queryPostKey_version40 } from '../../network/gun/encryption/queryPostKey' + +export type DecryptionInfo = { + type: DecryptProgressKind.Info + iv?: Uint8Array + claimedAuthor?: ProfileIdentifier + publicShared?: boolean +} +export type DecryptionProgress = DecryptProgress | DecryptionInfo + +export interface DecryptionContext { + currentSocialNetwork: SocialNetworkEnum + currentProfile: ProfileIdentifier | null + authorHint: ProfileIdentifier | null + postURL: string | undefined +} +export type SocialNetworkEncodedPayload = + | { type: 'text'; text: string } + | { type: 'image'; image: Blob } + | { type: 'image-url'; image: string } +const downloadImage = (url: string): Promise => fetch(url).then((x) => x.arrayBuffer()) + +/** + * + * @param encoded If the encoded content is a text, it should only contain 1 payload. Extra payload will be ignored. + * @param context + */ +export async function* decryptionWithSocialNetworkDecoding( + encoded: SocialNetworkEncodedPayload, + context: DecryptionContext, +): AsyncGenerator { + let decoded: string + if (encoded.type === 'text') { + decoded = socialNetworkDecoder(context.currentSocialNetwork, encoded.text)[0] + } else { + if (!context.authorHint || context.authorHint.isUnknown) { + return yield new DecryptError(ErrorReasons.UnrecognizedAuthor, undefined) + } + const result = await steganographyDecodeImage(encoded.image, { + pass: context.authorHint.toText(), + downloadImage, + }) + const val = socialNetworkDecoder(context.currentSocialNetwork, result)[0] + decoded = val[0] + } + + if (!decoded) return yield new DecryptError(ErrorReasons.NoPayloadFound, undefined) + yield* decryption(decoded, context) +} +export async function* decryption(payload: string | Uint8Array, context: DecryptionContext) { + const parse = await parsePayload(payload) + if (parse.err) return null + + const { currentSocialNetwork, postURL } = context + let { currentProfile, authorHint } = context + if (currentProfile?.isUnknown) currentProfile = null + if (authorHint?.isUnknown) authorHint = null + + // #region Identify the PostIdentifier + const iv = parse.val.encryption.unwrapOr(null)?.iv.unwrapOr(null) + { + if (!iv) return null + // iv is required to identify the post and it also used in comment encryption. + const info: DecryptionInfo = { type: DecryptProgressKind.Info, iv } + yield info + } + const id = new PostIVIdentifier( + SocialNetworkEnumToProfileDomain(currentSocialNetwork), + encodeArrayBuffer(iv.buffer), + ) + // #endregion + + // TODO: read in-memory cache to avoid db lookup + + // #region store author public key into the database + try { + const id = parse.unwrap().author.unwrap().unwrap() + const cacheKey = id.toText() + if (!hasStoredAuthorPublicKey.has(cacheKey)) { + storeAuthorPublicKey(id, authorHint, parse.unwrap().authorPublicKey.unwrap().unwrap()).catch(noop) + hasStoredAuthorPublicKey.add(cacheKey) + } + } catch {} + // #endregion + + const progress = decrypt( + { message: parse.val }, + { + getPostKeyCache: getPostKeyCache.bind(null, id), + setPostKeyCache: (key) => { + return savePostKeyToDB(id, key, { + // public post will not call this function. + // and recipients only will be set when posting/appending recipients. + recipients: new IdentifierMap(new Map()), + postBy: + authorHint || + parse.safeUnwrap().author.unwrapOr(null)?.unwrapOr(null) || + ProfileIdentifier.unknown, + url: postURL, + }) + }, + hasLocalKeyOf: hasLocalKeyOf, + decryptByLocalKey: decryptByLocalKey, + async deriveAESKey(pub) { + return Array.from((await deriveAESByECDH(pub)).values()) + }, + async deriveAESKey_version38_or_older(pub, iv) { + return Array.from((await deriveAESByECDH_version38_or_older(pub, iv)).values()) + }, + queryAuthorPublicKey(author, signal) { + return queryPublicKey(author || authorHint, false, signal) + }, + // TODO: get a gun instance + async *queryPostKey_version37() { + throw new Error('TODO') + }, + async *queryPostKey_version38(iv, signal) { + const author = await queryPublicKey(context.currentProfile, true) + if (!author) throw new DecryptError(ErrorReasons.CurrentProfileDoesNotConnectedToPersona, undefined) + yield* GUN_queryPostKey_version39Or38( + -38, + iv, + author, + getNetworkHint(context.currentSocialNetwork), + signal || new AbortController().signal, + ) + }, + async *queryPostKey_version39(iv, signal) { + const author = await queryPublicKey(context.currentProfile, true) + if (!author) throw new DecryptError(ErrorReasons.CurrentProfileDoesNotConnectedToPersona, undefined) + yield* GUN_queryPostKey_version39Or38( + -39, + iv, + author, + getNetworkHint(context.currentSocialNetwork), + signal || new AbortController().signal, + ) + }, + async queryPostKey_version40(iv) { + if (!currentProfile) return null + return GUN_queryPostKey_version40(iv, currentProfile.userId) + }, + }, + ) + + yield* progress + return null +} + +function getNetworkHint(x: SocialNetworkEnum) { + if (x === SocialNetworkEnum.Facebook) return '' + if (x === SocialNetworkEnum.Twitter) return 'twitter-' + if (x === SocialNetworkEnum.Minds) return 'minds-' + if (x === SocialNetworkEnum.Instagram) return 'instagram-' + if (x === SocialNetworkEnum.Unknown) + throw new TypeError('[@masknet/encryption] Current SNS network is not correctly configured.') + unreachable(x) +} + +async function getPostKeyCache(id: PostIVIdentifier) { + const post = await queryPostDB(id) + if (!post?.postCryptoKey) return null + const k = await crypto.subtle.importKey('jwk', post.postCryptoKey, { name: 'AES-GCM', length: 256 }, false, [ + 'decrypt', + ]) + return k as AESCryptoKey +} + +const hasStoredAuthorPublicKey = new Set() +async function storeAuthorPublicKey( + payloadAuthor: ProfileIdentifier, + postAuthor: ProfileIdentifier | null, + pub: AsymmetryCryptoKey, +) { + if (!payloadAuthor.equals(postAuthor)) { + // ! Author detected is not equal to AuthorHint. + // ! Skip store the public key because it might be a security problem. + return + } + if (pub.algr !== PublicKeyAlgorithmEnum.secp256k1) { + throw new Error('TODO: support other curves') + } + return createProfileWithPersona( + payloadAuthor, + { connectionConfirmState: 'confirmed' }, + { + publicKey: (await crypto.subtle.exportKey('jwk', pub.key)) as EC_Public_JsonWebKey, + }, + ) +} + +async function queryPublicKey(author: ProfileIdentifier | null, extractable = false, signal?: AbortSignal) { + if (!author) return null + const persona = await queryPersonaByProfileDB(author) + if (!persona) return null + return (await crypto.subtle.importKey( + 'jwk', + persona.publicKey, + { name: 'ECDH', namedCurve: persona.publicKey.crv! } as EcKeyAlgorithm, + extractable, + ['deriveKey'], + )) as EC_Public_CryptoKey +} diff --git a/packages/mask/background/services/crypto/index.ts b/packages/mask/background/services/crypto/index.ts index 1ef6b67e0fd2..b5dc25c3a910 100644 --- a/packages/mask/background/services/crypto/index.ts +++ b/packages/mask/background/services/crypto/index.ts @@ -1,3 +1 @@ -// import {} from '@masknet/encryption' -// await Promise.resolve() -export {} +export { type DecryptionInfo, type DecryptionProgress, decryption } from './decryption' diff --git a/packages/mask/background/tasks/CleanProfileAndAvatar.ts b/packages/mask/background/tasks/CleanProfileAndAvatar.ts index 3a4934065c9d..f840fc4c897c 100644 --- a/packages/mask/background/tasks/CleanProfileAndAvatar.ts +++ b/packages/mask/background/tasks/CleanProfileAndAvatar.ts @@ -26,7 +26,7 @@ export default async function cleanProfileWithNoLinkedPersona(signal: AbortSigna if (id.ok) cleanedList.set(id.val, undefined) await x.delete() } - }, false) + }) await cleanAvatarDB(cleanedList) await cleanRelationDB(cleanedList) } diff --git a/packages/mask/background/tsconfig.json b/packages/mask/background/tsconfig.json index 140c7b259376..b97bc2510f7c 100644 --- a/packages/mask/background/tsconfig.json +++ b/packages/mask/background/tsconfig.json @@ -10,5 +10,10 @@ "lib": ["ES2021", "WebWorker"] }, "include": ["./"], - "references": [{ "path": "../shared" }, { "path": "../utils-pure" }, { "path": "../../encryption" }] + "references": [ + { "path": "../shared" }, + { "path": "../utils-pure" }, + { "path": "../../encryption" }, + { "path": "../../gun-utils" } + ] } diff --git a/packages/mask/package.json b/packages/mask/package.json index 528c03fd6530..113a85c51725 100644 --- a/packages/mask/package.json +++ b/packages/mask/package.json @@ -17,6 +17,7 @@ "@masknet/dashboard": "workspace:*", "@masknet/encryption": "workspace:^0.0.0", "@masknet/external-plugin-previewer": "workspace:*", + "@masknet/gun-utils": "workspace:*", "@masknet/icons": "workspace:*", "@masknet/injected-script": "workspace:*", "@masknet/plugin-dao": "workspace:*", @@ -24,15 +25,16 @@ "@masknet/plugin-example": "workspace:*", "@masknet/plugin-file-service": "workspace:*", "@masknet/plugin-flow": "workspace:*", + "@masknet/plugin-solana": "workspace:*", "@masknet/plugin-infra": "workspace:*", "@masknet/plugin-rss3": "workspace:*", - "@masknet/plugin-solana": "workspace:*", "@masknet/plugin-wallet": "workspace:*", "@masknet/public-api": "workspace:*", "@masknet/sdk": "workspace:*", "@masknet/shared": "workspace:*", "@masknet/shared-base": "workspace:*", "@masknet/theme": "workspace:*", + "@masknet/typed-message": "workspace:*", "@masknet/web3-contracts": "workspace:*", "@masknet/web3-providers": "workspace:*", "@masknet/web3-shared-base": "workspace:*", @@ -78,7 +80,6 @@ "fuse.js": "^6.5.3", "graphql": "^15.5.1", "graphql-request": "^3.4.0", - "gun": "^0.2020.1234", "history": "^5.2.0", "https-browserify": "^1.0.0", "i18next-browser-languagedetector": "^6.1.3", @@ -89,7 +90,6 @@ "jsbi": "3.1.4", "json-stable-stringify": "^1.0.1", "json2csv": "^5.0.6", - "jsx-jsonml-devtools-renderer": "^1.4.3", "millify": "^4.0.0", "next-tick": "^1.0.0", "opensea-js": "^1.2.7", diff --git a/packages/mask/shared-ui/TypedMessageRender/Components/Text.tsx b/packages/mask/shared-ui/TypedMessageRender/Components/Text.tsx new file mode 100644 index 000000000000..22ba32c71615 --- /dev/null +++ b/packages/mask/shared-ui/TypedMessageRender/Components/Text.tsx @@ -0,0 +1,18 @@ +import type { MessageRenderUIComponentsContext } from '@masknet/typed-message/dom' +import { Typography, Link } from '@mui/material' + +export const Text: MessageRenderUIComponentsContext['Text'] = (props) => ( + +) + +// TODO: provide SNS-aware #hast $link and @mention support +export const Anchor: MessageRenderUIComponentsContext['Link'] = (props) => ( + +) diff --git a/packages/mask/shared-ui/TypedMessageRender/MaskPayload.tsx b/packages/mask/shared-ui/TypedMessageRender/MaskPayload.tsx new file mode 100644 index 000000000000..b03a249f0dc6 --- /dev/null +++ b/packages/mask/shared-ui/TypedMessageRender/MaskPayload.tsx @@ -0,0 +1,26 @@ +import type { TypedMessageMaskPayload } from '@masknet/typed-message/base' +import { TypedMessageRender } from '@masknet/typed-message/dom' +import { styled } from '@mui/material' +import { MaskBlueIcon } from '@masknet/icons' +import { ShadowRootTooltip } from '../shadow-root/ShadowRootComponents' + +export function MaskPayloadRender(props: TypedMessageMaskPayload) { + return ( + + + + + + + ) +} + +const Icon = styled(MaskBlueIcon)` + float: right; + margin-left: 6px; +` +const Round = styled('div')` + border: 1px solid rgb(28, 104, 243); + padding: 0px 6px; + display: inline-block; +` diff --git a/packages/mask/shared-ui/TypedMessageRender/context.tsx b/packages/mask/shared-ui/TypedMessageRender/context.tsx new file mode 100644 index 000000000000..c4ed50f77384 --- /dev/null +++ b/packages/mask/shared-ui/TypedMessageRender/context.tsx @@ -0,0 +1,36 @@ +import { + MessageRenderUIComponentsContext, + MetadataRenderProps, + RenderRegistryContext, + TransformerContext, +} from '@masknet/typed-message/dom' +import { TypedMessageRenderRegistry } from './registry' +import { TypedMessageTransformers } from './transformer' +import { useSubscription } from 'use-subscription' +import { emptyTransformationContext, TransformationContext } from '@masknet/typed-message/base' +import { useMemo } from 'react' +import { Text, Anchor as Link } from './Components/Text' + +export interface TypedMessageRenderContextProps extends React.PropsWithChildren<{}> { + context?: TransformationContext + metadataRender?: React.ComponentType +} + +export function TypedMessageRenderContext(props: TypedMessageRenderContextProps) { + const registry = useSubscription(TypedMessageRenderRegistry.subscription) + const f = useSubscription(TypedMessageTransformers.subscription) + const val = useMemo(() => { + return [f, props.context || emptyTransformationContext] as const + }, [f, props.context]) + const Provider = useMemo((): MessageRenderUIComponentsContext => { + return { Text, Link, Metadata: props.metadataRender } + }, [props.metadataRender]) + + return ( + + + {props.children} + + + ) +} diff --git a/packages/mask/shared-ui/TypedMessageRender/registry.ts b/packages/mask/shared-ui/TypedMessageRender/registry.ts new file mode 100644 index 000000000000..5aa780feb2be --- /dev/null +++ b/packages/mask/shared-ui/TypedMessageRender/registry.ts @@ -0,0 +1,8 @@ +import { createTypedMessageRenderRegistry } from '@masknet/typed-message/dom' +import { MaskPayloadRender } from './MaskPayload' +export const TypedMessageRenderRegistry = createTypedMessageRenderRegistry() +TypedMessageRenderRegistry.registerTypedMessageRender('x-mask-payload', { + component: MaskPayloadRender, + id: Symbol('io-mask.x-mask-payload'), + priority: 1000, +}) diff --git a/packages/mask/shared-ui/TypedMessageRender/transformer.ts b/packages/mask/shared-ui/TypedMessageRender/transformer.ts new file mode 100644 index 000000000000..5da559db0a3a --- /dev/null +++ b/packages/mask/shared-ui/TypedMessageRender/transformer.ts @@ -0,0 +1,22 @@ +import { composeTransformers, FlattenTypedMessage, ParseLinkTransformer } from '@masknet/typed-message/base' + +export enum Order { + Flatten = 1000, + ParseLink = 900, + MaskPayload = 800, + Plugins = 500, +} +/** + * Message transformation order: + * + * sns_parsed_message + * |> flatten + * |> parse links and tags (@user, #tag, $NAME) + * |> Mask Payload parser (installed in SNS Adaptor starts) + * |> plugins + */ +export const TypedMessageTransformers = composeTransformers() +export const TypedMessagePluginTransformers = composeTransformers() +TypedMessageTransformers.addTransformer(FlattenTypedMessage, Order.Flatten) +TypedMessageTransformers.addTransformer(ParseLinkTransformer, Order.ParseLink) +TypedMessageTransformers.addTransformer(TypedMessagePluginTransformers.subscription, Order.Plugins) diff --git a/packages/mask/shared-ui/locales/en-US.json b/packages/mask/shared-ui/locales/en-US.json index 271b259657fe..63dd32e97acf 100644 --- a/packages/mask/shared-ui/locales/en-US.json +++ b/packages/mask/shared-ui/locales/en-US.json @@ -26,10 +26,8 @@ "contract": "Contract", "initializing": "Initializing...", "redirect_alert": "If your browser does not redirect, please click here.", - "typed_message_can_not_be_rendered": "The TypedMessage has a circular structure so it can't be rendered on the screen.", "typed_message_text_alert": "Only TypedMessageText is supported currently.", "badge_renderer_provided_by_plugin": "Provided by plugin", - "add_to_key_store_success": "The public key has been added to the Keystore", "add_token": "Add Token", "add_nft_contract_search_hint": "Search NFT Contract Symbol Name or Address", "applications": "Applications", @@ -62,16 +60,13 @@ "create": "Create", "copied": "Copied", "daily": "Daily", - "unknown": "Unknown", - "message": "Message", "dashboard_tab_collectibles": "Collectibles", "dashboard_no_collectible_found": "No collectible found.", "days": "Every {{days}} days", "decrypted_postbox_add_recipients": "Append recipients", "decrypted_postbox_decrypting": "Mask decrypting…", - "decrypted_postbox_decoding": "Mask decoding…", - "decrypted_postbox_decrypting_finding_person_key": "Mask is looking for the public key of the author…", - "decrypted_postbox_decrypting_finding_post_key": "Mask is retrieving the post key to decrypt this post…", + "decrypted_postbox_decrypting_finding_post_key": "Mask is looking for the key to decrypt this post…", + "decrypted_postbox_decrypting_finding_post_key_long": "Mask is still trying to decrypt this post, but it seems like the post is not shared with you.", "decrypted_postbox_author_mismatch": "Originally posted by {{name}}", "decrypted_postbox_title": "Decrypted by Mask:", "dismiss": "Dismiss", @@ -109,10 +104,6 @@ "no_search_result": "No result", "loading": "Loading...", "unlock": "Unlock", - "payload_bad": "This post seems to be corrupted. Mask cannot decrypt it.", - "payload_incomplete": "This post is incomplete. You need to view the full post to decrypt it.", - "payload_not_found": "Payload not found.", - "payload_throw_in_alpha41": "Support for Alpha41 is deprecated. Tell your friends to upgrade Mask!", "personas": "Personas", "browser_action_enter_dashboard": "Enter Dashboard", "pending": "Pending...", @@ -131,7 +122,6 @@ "post_dialog__title": "Mask: Compose", "post_dialog_enable_paste_auto": "Enable auto paste", "post_modal_hint__button": "Compose encrypted post", - "post_substitute_label": "Mask", "hide": "Hide", "reset": "Reset", "editor": "Editor", @@ -147,12 +137,7 @@ "select_specific_friends_dialog__title": "Select Specific Contacts", "service_decryption_failed": "Decryption failed.", "service_invalid_backup_file": "This does not seem like a backup of Mask.", - "service_not_share_target": "Mask does not find the post key. This post may not be intended to share with you.", - "service_others_key_not_found": "The public key of {{name}} cannot be found!", "service_publish_post_aes_key_failed": "Failed to publish the AES key!", - "service_self_key_decryption_failed": "Decryption failed. Maybe you selected a wrong identity or imported a key that was not used to encrypt this post.", - "service_decode_image_payload_failed": "Decode image failed.", - "service_unknown_payload": "Unknown post version. You may need to update Mask.", "service_username_invalid": "Invalid Username", "settings_enable_debug": "Debug Mode", "settings_enable_debug_desc": "See additional information for debugging.", @@ -161,8 +146,6 @@ "settings_language": "Language", "settings_language_secondary": "Select the language you would like to use.", "settings_choose_eth_network": "Choose Ethereum Network", - "settings_post_replacement": "Substitute Post", - "settings_post_replacement_desc": "All posts on the web-pages will be rendered by Mask, including those not created by Mask.", "settings_launch_page": "Launch Page", "settings_launch_page_secondary": "Select the default page to open when launch the app", "speed_up": "Speed up", diff --git a/packages/mask/shared-ui/locales/ja-JP.json b/packages/mask/shared-ui/locales/ja-JP.json index d3923ecb68ac..c63fc89d5695 100644 --- a/packages/mask/shared-ui/locales/ja-JP.json +++ b/packages/mask/shared-ui/locales/ja-JP.json @@ -1,5 +1,4 @@ { - "add_to_key_store_success": "公開鍵はキーストアに追加されました。", "add_token": "トークンを追加", "additional_post_box__encrypted_post_pre": "#mask_io で復号しましょう! {{encrypted}}", "additional_post_box__steganography_post_pre": "この投稿は #mask_io によって暗号化されています。 📪🔑 mask.io をインストールして復号しましょう! ([I:b]) {{random}}", @@ -23,8 +22,6 @@ "dashboard_no_collectible_found": "コレクションが見つかりません", "decrypted_postbox_add_recipients": "受信者を追加", "decrypted_postbox_decrypting": "Mask が復号しています。", - "decrypted_postbox_decoding": "Mask が解読しています。", - "decrypted_postbox_decrypting_finding_person_key": "Mask は公開鍵を探しています…", "decrypted_postbox_decrypting_finding_post_key": "Mask はこの投稿を復号するために ポストキーを取得しています…", "decrypted_postbox_author_mismatch": "最初の作者は {{name}}", "decrypted_postbox_title": "Mask で暗号化されています:", @@ -41,10 +38,6 @@ "setup_guide_connect_failed": "失敗しました… もう一度お試しください。", "import": "インポート", "no_search_result": "該当なし", - "payload_bad": "この投稿は破損しているため、Mask で復号できません。", - "payload_incomplete": "この投稿は不完全です。全文を見ることにより復号が可能になります。", - "payload_not_found": "ペイロードが見つかりませんでした。", - "payload_throw_in_alpha41": "Alpha41方式は使用できません。Mask をアップデートしてください。", "personas": "ペルソナ", "browser_action_enter_dashboard": "ダッシュボードに入る", "post_dialog__button": "完了", @@ -67,12 +60,7 @@ "select_specific_friends_dialog__title": "特定の連絡先を選ぶ", "service_decryption_failed": "復号に失敗", "service_invalid_backup_file": "これは Mask のバックアップではないかもしれません。", - "service_not_share_target": " Mask は投稿鍵を発見できませんでした。この投稿はあなたに共有されていない可能性があります。", - "service_others_key_not_found": "{{name}} の公開鍵が見つかりません!", "service_publish_post_aes_key_failed": "AES キーを公開するのに失敗しました。", - "service_self_key_decryption_failed": "復号に失敗しました。間違ったIDを選択したか、この投稿の暗号化に使用されていない鍵をインポートしたのかもしれません。", - "service_decode_image_payload_failed": "画像のデコードに失敗しました。", - "service_unknown_payload": "投稿のバージョンが不明です。Mask のアップデートが必要かもしれません。", "service_username_invalid": "無効なユーザー名", "settings_enable_debug": "デバッグモード", "settings_enable_debug_desc": "デバッグのための追加情報を参照してください。", @@ -81,8 +69,6 @@ "settings_language": "言語を設定", "settings_language_secondary": "ご利用になりたい言語をお選びください。", "settings_choose_eth_network": "Ethereum ネットワークを選択してください", - "settings_post_replacement": "代替ポスト", - "settings_post_replacement_desc": "Web ページ上のすべての投稿は、Mask で作成されていない投稿を含め、Mask によってレンダリングされます。", "settings_launch_page": "初期画面", "settings_launch_page_secondary": "アプリを開いたときに最初に開かれる画面を選んでください。", "skip": "スキップ", diff --git a/packages/mask/shared-ui/locales/ko-KR.json b/packages/mask/shared-ui/locales/ko-KR.json index d320e5ac72ad..516492ba5f4d 100644 --- a/packages/mask/shared-ui/locales/ko-KR.json +++ b/packages/mask/shared-ui/locales/ko-KR.json @@ -26,10 +26,8 @@ "contract": "컨트랙트", "initializing": "초기화 중...", "redirect_alert": "브라우저가 리다이렉트하지 않으면 여기 클릭", - "typed_message_can_not_be_rendered": "The TypedMessage has a circular structure so it can't be rendered on the screen.", "typed_message_text_alert": "현재 TypedMessageText만 지원합니다.", "badge_renderer_provided_by_plugin": "플러그인으로 제공", - "add_to_key_store_success": "해당 공개 키가 이미 키스토어에서 추가되었습니다", "add_token": "토큰 추가", "add_nft_contract_search_hint": "NFT 컨트렉트 이름이나 주소를 검색하기", "applications": "어플리케이션", @@ -60,15 +58,11 @@ "create": "만들기", "copied": "복사됨", "daily": "일일", - "unknown": "알 수 없음", - "message": "메시지", "dashboard_tab_collectibles": "수집품", "dashboard_no_collectible_found": "수집품이 없습니다.", "days": "{{days}} 일마다", "decrypted_postbox_add_recipients": "받는사람 추가", "decrypted_postbox_decrypting": "Mask 해독 중", - "decrypted_postbox_decoding": "Mask 디코딩 중", - "decrypted_postbox_decrypting_finding_person_key": "Mask가 상대방의 공개 키를 찾고 있습니다...", "decrypted_postbox_decrypting_finding_post_key": "Mask가 이 게시글의 키를 검색하고 있습니다.", "decrypted_postbox_author_mismatch": "{{name}}님이 이 글을 처음 게시했습니다.", "decrypted_postbox_title": "Mask로 해독되었습니다:", @@ -94,10 +88,6 @@ "no_search_result": "결과 없음", "loading": "로딩 중", "unlock": "언락", - "payload_bad": "이 게시물은 손상된 것 같습니다. Mask가 해독할 수 없습니다.", - "payload_incomplete": "불완전한 게시물입니다. 해독하려면 완전한 게시물이 필요합니다.", - "payload_not_found": "페이로드를 찾을 수 없습니다.", - "payload_throw_in_alpha41": "Alpha41 이미 지원하 않습니다. 상대방에게 Mask를 업그레이드하라고 하세요!", "personas": "페르소나", "browser_action_enter_dashboard": "대시보드로 들어가기", "pending": "대기 중…", @@ -116,7 +106,6 @@ "post_dialog__title": "Mask: 편집", "post_dialog_enable_paste_auto": "자동 붙이기 지원", "post_modal_hint__button": "암호화된 메시지를 편집하기", - "post_substitute_label": "Mask", "hide": "숨기기", "reset": "초기화", "editor": "에디터", @@ -132,12 +121,7 @@ "select_specific_friends_dialog__title": "지정 연락처 선택", "service_decryption_failed": "해독 실패", "service_invalid_backup_file": "Mask의 백업이 아닌 것 같습니다.", - "service_not_share_target": "Mask가 이 게시물의 키를 찾지 못합니다. 이 게시물은 당신에게 공유하는 것이 아닌 것 같습니다.", - "service_others_key_not_found": "찾을 수 없는 {{name}}의 공개 키입니다.", "service_publish_post_aes_key_failed": "AES 키 공유 실패", - "service_self_key_decryption_failed": "해독 실패했습니다. 잘못된 신분이나 키를 불러온 것 같습니다.", - "service_decode_image_payload_failed": "이미지 디코딩 실패.", - "service_unknown_payload": "알 수 없는 게시물 버전입니다. Mask를 업데이트하세요.", "service_username_invalid": "무효한 아이디입니다", "settings_enable_debug": "디버그 모드", "settings_enable_debug_desc": "디버깅에 대한 추가 정보 보기", @@ -146,8 +130,6 @@ "settings_language": "언어", "settings_language_secondary": "이용하고 싶은 언어를 선택하세요.", "settings_choose_eth_network": "이더리움 네트워크를 선택하기", - "settings_post_replacement": "대체 게시물", - "settings_post_replacement_desc": "Mask가 이 웹페이지에 모든 게시물을 렌더링합니다. Mask로 만들지 않는 것도 포함됩니다.", "settings_launch_page": "시작 페이지", "settings_launch_page_secondary": "앱을 열을 때 디폴트 페이지를 선택하세요.", "speed_up": "가속하기", diff --git a/packages/mask/shared-ui/locales/qya-AA.json b/packages/mask/shared-ui/locales/qya-AA.json index ff706fac628c..c5ec77e88587 100644 --- a/packages/mask/shared-ui/locales/qya-AA.json +++ b/packages/mask/shared-ui/locales/qya-AA.json @@ -26,10 +26,8 @@ "contract": "crwdns10109:0crwdne10109:0", "initializing": "crwdns10111:0crwdne10111:0", "redirect_alert": "crwdns10113:0crwdne10113:0", - "typed_message_can_not_be_rendered": "crwdns10115:0crwdne10115:0", "typed_message_text_alert": "crwdns10117:0crwdne10117:0", "badge_renderer_provided_by_plugin": "crwdns10119:0crwdne10119:0", - "add_to_key_store_success": "crwdns3981:0crwdne3981:0", "add_token": "crwdns3983:0crwdne3983:0", "add_nft_contract_search_hint": "crwdns8123:0crwdne8123:0", "applications": "crwdns9513:0crwdne9513:0", @@ -60,15 +58,11 @@ "create": "crwdns4047:0crwdne4047:0", "copied": "crwdns9361:0crwdne9361:0", "daily": "crwdns4057:0crwdne4057:0", - "unknown": "crwdns10121:0crwdne10121:0", - "message": "crwdns10123:0crwdne10123:0", "dashboard_tab_collectibles": "crwdns4063:0crwdne4063:0", "dashboard_no_collectible_found": "crwdns4105:0crwdne4105:0", "days": "crwdns4107:0{{days}}crwdne4107:0", "decrypted_postbox_add_recipients": "crwdns4109:0crwdne4109:0", "decrypted_postbox_decrypting": "crwdns4111:0crwdne4111:0", - "decrypted_postbox_decoding": "crwdns4113:0crwdne4113:0", - "decrypted_postbox_decrypting_finding_person_key": "crwdns4115:0crwdne4115:0", "decrypted_postbox_decrypting_finding_post_key": "crwdns4117:0crwdne4117:0", "decrypted_postbox_author_mismatch": "crwdns4119:0{{name}}crwdne4119:0", "decrypted_postbox_title": "crwdns4121:0crwdne4121:0", @@ -96,10 +90,6 @@ "no_search_result": "crwdns4217:0crwdne4217:0", "loading": "crwdns8031:0crwdne8031:0", "unlock": "crwdns8033:0crwdne8033:0", - "payload_bad": "crwdns4227:0crwdne4227:0", - "payload_incomplete": "crwdns4229:0crwdne4229:0", - "payload_not_found": "crwdns4231:0crwdne4231:0", - "payload_throw_in_alpha41": "crwdns4233:0crwdne4233:0", "personas": "crwdns4237:0crwdne4237:0", "browser_action_enter_dashboard": "crwdns4247:0crwdne4247:0", "pending": "crwdns9391:0crwdne9391:0", @@ -118,7 +108,6 @@ "post_dialog__title": "crwdns4275:0crwdne4275:0", "post_dialog_enable_paste_auto": "crwdns10129:0crwdne10129:0", "post_modal_hint__button": "crwdns4277:0crwdne4277:0", - "post_substitute_label": "crwdns4279:0crwdne4279:0", "hide": "crwdns4293:0crwdne4293:0", "reset": "crwdns4301:0crwdne4301:0", "editor": "crwdns10131:0crwdne10131:0", @@ -134,12 +123,7 @@ "select_specific_friends_dialog__title": "crwdns4341:0crwdne4341:0", "service_decryption_failed": "crwdns4343:0crwdne4343:0", "service_invalid_backup_file": "crwdns4345:0crwdne4345:0", - "service_not_share_target": "crwdns4347:0crwdne4347:0", - "service_others_key_not_found": "crwdns4349:0{{name}}crwdne4349:0", "service_publish_post_aes_key_failed": "crwdns4351:0crwdne4351:0", - "service_self_key_decryption_failed": "crwdns4353:0crwdne4353:0", - "service_decode_image_payload_failed": "crwdns4355:0crwdne4355:0", - "service_unknown_payload": "crwdns4357:0crwdne4357:0", "service_username_invalid": "crwdns4359:0crwdne4359:0", "settings_enable_debug": "crwdns4427:0crwdne4427:0", "settings_enable_debug_desc": "crwdns4429:0crwdne4429:0", @@ -148,8 +132,6 @@ "settings_language": "crwdns4441:0crwdne4441:0", "settings_language_secondary": "crwdns4443:0crwdne4443:0", "settings_choose_eth_network": "crwdns4445:0crwdne4445:0", - "settings_post_replacement": "crwdns4447:0crwdne4447:0", - "settings_post_replacement_desc": "crwdns4449:0crwdne4449:0", "settings_launch_page": "crwdns4457:0crwdne4457:0", "settings_launch_page_secondary": "crwdns4459:0crwdne4459:0", "speed_up": "crwdns9393:0crwdne9393:0", diff --git a/packages/mask/shared-ui/locales/zh-CN.json b/packages/mask/shared-ui/locales/zh-CN.json index 92520ca4745f..f3598abda4bd 100644 --- a/packages/mask/shared-ui/locales/zh-CN.json +++ b/packages/mask/shared-ui/locales/zh-CN.json @@ -26,10 +26,8 @@ "contract": "合约", "initializing": "初始化中...", "redirect_alert": "如果您的浏览器没有重新跳转,请 点击这里。", - "typed_message_can_not_be_rendered": "输入的消息存在循环结构,因此无法在屏幕上呈现。", "typed_message_text_alert": "当前只支持输入消息文本。", "badge_renderer_provided_by_plugin": "插件提供:", - "add_to_key_store_success": "公钥已添加到密钥库", "add_token": "添加代币", "add_nft_contract_search_hint": "搜索 NFT 合约名称或地址", "applications": "应用程序", @@ -60,15 +58,11 @@ "create": "创建", "copied": "已复制", "daily": "每日", - "unknown": "未知", - "message": "信息", "dashboard_tab_collectibles": "收藏品", "dashboard_no_collectible_found": "未找到任何收藏品", "days": "每隔 {{days}} 天", "decrypted_postbox_add_recipients": "追加收件人", "decrypted_postbox_decrypting": "Mask正在解密中…", - "decrypted_postbox_decoding": "Mask正在解码中…", - "decrypted_postbox_decrypting_finding_person_key": "Mask 正在寻找作者的公钥…", "decrypted_postbox_decrypting_finding_post_key": "Mask 正在获取贴文密钥以解密此贴文…", "decrypted_postbox_author_mismatch": "最初发布于 {{name}}", "decrypted_postbox_title": "由Mask解密:", @@ -95,10 +89,6 @@ "no_search_result": "没有任何结果。", "loading": "加载中", "unlock": "解锁", - "payload_bad": "这个贴文似乎已损坏。Mask无法解密它。", - "payload_incomplete": "此贴文不完整。您需要查看完整贴文才能解密。", - "payload_not_found": "未找到Payload。", - "payload_throw_in_alpha41": "不支持Alpha41 。告诉您的朋友升级Mask!", "personas": "身份", "browser_action_enter_dashboard": "进入控制面板", "pending": "待定中...", @@ -117,7 +107,6 @@ "post_dialog__title": "Mask:编辑", "post_dialog_enable_paste_auto": "启用自动粘贴", "post_modal_hint__button": "编辑加密贴文", - "post_substitute_label": "Mask", "hide": "隐藏", "reset": "重置", "editor": "编辑器", @@ -133,12 +122,7 @@ "select_specific_friends_dialog__title": "选择特定联系人", "service_decryption_failed": "解密失败", "service_invalid_backup_file": "这似乎不是Mask的备份。", - "service_not_share_target": "Mask没有找到该贴文的密钥。这个贴文可能没有分享给您查看。", - "service_others_key_not_found": "无法找到 {{name}} 的公钥 !", "service_publish_post_aes_key_failed": "AES密钥发布失败!", - "service_self_key_decryption_failed": "贴文解密失败。或许您选择了错误的身份或者导入的是未用于加密此贴文的密钥。", - "service_decode_image_payload_failed": "图片解码失败。", - "service_unknown_payload": "未知的贴文版本。您可能需要更新Mask。", "service_username_invalid": "无效的用户名", "settings_enable_debug": "调试模式", "settings_enable_debug_desc": "查看更多信息进行调试。", @@ -147,8 +131,6 @@ "settings_language": "语言", "settings_language_secondary": "选择您要使用的语言.", "settings_choose_eth_network": "选择以太坊网络", - "settings_post_replacement": "替换贴文", - "settings_post_replacement_desc": "所有网页上的贴文将由Mask提供,包括不是由Mask创建的贴文。", "settings_launch_page": "启动页面", "settings_launch_page_secondary": "选择启动应用程序时要打开的默认页面", "speed_up": "加速", diff --git a/packages/mask/shared-ui/locales/zh-TW.json b/packages/mask/shared-ui/locales/zh-TW.json index 49c53f73fb82..4867ba830082 100644 --- a/packages/mask/shared-ui/locales/zh-TW.json +++ b/packages/mask/shared-ui/locales/zh-TW.json @@ -17,7 +17,6 @@ "contract": "合約", "initializing": "初始化中...", "redirect_alert": "如果你的瀏覽器沒有跳轉, 請點擊此處.", - "add_to_key_store_success": "公鑰已添加到密鑰庫", "add_token": "新增代幣", "add_nft_contract_search_hint": "檢索NFT合約名稱或地址", "applications": "應用", @@ -45,13 +44,10 @@ "connecting": "正在連接…", "create": "建立", "copied": "已複製", - "message": "訊息", "dashboard_tab_collectibles": "收藏", "dashboard_no_collectible_found": "找不到收藏品", "decrypted_postbox_add_recipients": "新增收件人", "decrypted_postbox_decrypting": "Mask 正在解密…", - "decrypted_postbox_decoding": "Mask 正在解碼…", - "decrypted_postbox_decrypting_finding_person_key": "Mask 正在尋找這個作者的公鑰…", "decrypted_postbox_decrypting_finding_post_key": "Mask 正在取得貼文金鑰以解密此貼文…", "decrypted_postbox_author_mismatch": "最初由 {{name}} 發佈", "decrypted_postbox_title": "已由 Mask 解密:", @@ -70,10 +66,6 @@ "user_guide_tip_connected": "已成功連接此帳號", "import": "導入", "no_search_result": "沒有結果", - "payload_bad": "這篇貼文似乎被破壞了。Mask 無法解密它。", - "payload_incomplete": "這篇貼文不完整。你需要查看全文才能解密。", - "payload_not_found": "找不到貼文。", - "payload_throw_in_alpha41": "不推薦使用 Alpha41。告訴你的朋友升級Mask!", "personas": "角色", "browser_action_enter_dashboard": "進入儀錶板", "post_dialog__button": "完成", @@ -99,12 +91,7 @@ "select_specific_friends_dialog__title": "選擇特定聯絡人", "service_decryption_failed": "解密失敗。", "service_invalid_backup_file": "這不是一個 Mask 的備份檔。", - "service_not_share_target": "Mask 無發找到貼文金鑰。 這篇文章或許不是要分享給你的。", - "service_others_key_not_found": "無法找到 {{name}} 的公鑰!", "service_publish_post_aes_key_failed": "發佈 AES 金鑰失敗!", - "service_self_key_decryption_failed": "解密失敗。可能您選擇了錯誤的身分或導入了一個不用於加密此貼文的金鑰。", - "service_decode_image_payload_failed": "圖片解碼失敗", - "service_unknown_payload": "未知的貼文版本。您或許需要升級 Mask。", "service_username_invalid": "錯誤的使用者名稱", "settings_enable_debug": "除錯模式", "settings_enable_debug_desc": "請參考有關除錯的附加資訊", @@ -113,8 +100,6 @@ "settings_language": "語言", "settings_language_secondary": "選擇你想使用的語言。", "settings_choose_eth_network": "選擇乙太坊網路", - "settings_post_replacement": "取代貼文", - "settings_post_replacement_desc": "網頁上的所有貼文都將通過 Mask 呈現,包括那些不是由 Mask 建立的貼文。", "settings_launch_page": "啟動頁面", "settings_launch_page_secondary": "選擇啟動程式時要打開的預設頁面", "speed_up": "加速", diff --git a/packages/mask/src/utils/shadow-root/ShadowRootComponents.tsx b/packages/mask/shared-ui/shadow-root/ShadowRootComponents.tsx similarity index 100% rename from packages/mask/src/utils/shadow-root/ShadowRootComponents.tsx rename to packages/mask/shared-ui/shadow-root/ShadowRootComponents.tsx diff --git a/packages/mask/shared-ui/tsconfig.json b/packages/mask/shared-ui/tsconfig.json index 2981983f40a4..9dc25225efe0 100644 --- a/packages/mask/shared-ui/tsconfig.json +++ b/packages/mask/shared-ui/tsconfig.json @@ -9,5 +9,12 @@ "resolveJsonModule": true }, "include": ["./", "./**/*.json"], - "references": [{ "path": "../../shared-base" }, { "path": "../../shared/" }] + "references": [ + { "path": "../utils-pure" }, + { "path": "../../shared-base" }, + { "path": "../../shared/" }, + { "path": "../../typed-message/base" }, + { "path": "../../typed-message/dom" }, + { "path": "../../theme" } + ] } diff --git a/packages/mask/src/components/CompositionDialog/BadgeRenderer.tsx b/packages/mask/src/components/CompositionDialog/BadgeRenderer.tsx index b7870dfb4910..60cfb4cc42ea 100644 --- a/packages/mask/src/components/CompositionDialog/BadgeRenderer.tsx +++ b/packages/mask/src/components/CompositionDialog/BadgeRenderer.tsx @@ -1,6 +1,6 @@ import { useActivatedPluginsSNSAdaptor, Plugin } from '@masknet/plugin-infra' import { makeStyles } from '@masknet/theme' -import type { TypedMessage } from '@masknet/shared-base' +import type { TypedMessage } from '@masknet/typed-message/base' import { Box, Chip } from '@mui/material' import { usePluginI18NField } from '../../plugin-infra/I18NFieldRender' import { ShadowRootTooltip, useI18N } from '../../utils' diff --git a/packages/mask/src/components/CompositionDialog/CompositionUI.tsx b/packages/mask/src/components/CompositionDialog/CompositionUI.tsx index 83cb81f519c3..b2b4e643c15d 100644 --- a/packages/mask/src/components/CompositionDialog/CompositionUI.tsx +++ b/packages/mask/src/components/CompositionDialog/CompositionUI.tsx @@ -1,7 +1,7 @@ import { forwardRef, useImperativeHandle, useMemo, useRef, useState, startTransition, useCallback } from 'react' import { Typography, Chip, Button } from '@mui/material' import { LoadingButton } from '@mui/lab' -import type { TypedMessage } from '@masknet/shared-base' +import type { TypedMessage } from '@masknet/typed-message/base' import { useValueRef } from '@masknet/shared' import { makeStyles } from '@masknet/theme' import { ImagePayloadIcon } from '@masknet/icons' diff --git a/packages/mask/src/components/CompositionDialog/TypedMessageEditor.tsx b/packages/mask/src/components/CompositionDialog/TypedMessageEditor.tsx index 801716b65111..89a5d9a84344 100644 --- a/packages/mask/src/components/CompositionDialog/TypedMessageEditor.tsx +++ b/packages/mask/src/components/CompositionDialog/TypedMessageEditor.tsx @@ -4,7 +4,7 @@ import { makeTypedMessageText, TypedMessage, editTypedMessageMeta, -} from '@masknet/shared-base' +} from '@masknet/typed-message/base' import { makeStyles } from '@masknet/theme' import { InputBase, Alert, Button } from '@mui/material' import { useCallback, useImperativeHandle, useState, useRef, forwardRef, memo } from 'react' diff --git a/packages/mask/src/components/CompositionDialog/useSubmit.ts b/packages/mask/src/components/CompositionDialog/useSubmit.ts index 6f6c7ee6b9ad..84b3f689e53f 100644 --- a/packages/mask/src/components/CompositionDialog/useSubmit.ts +++ b/packages/mask/src/components/CompositionDialog/useSubmit.ts @@ -11,6 +11,7 @@ import type { SubmitComposition } from './CompositionUI' import { unreachable } from '@dimensiondev/kit' import { useLastRecognizedIdentity } from '../DataSource/useActivatedUI' import { isFacebook } from '../../social-network-adaptor/facebook.com/base' +import { socialNetworkEncoder } from '@masknet/encryption' export function useSubmit(onClose: () => void) { const { t } = useI18N() @@ -27,12 +28,13 @@ export function useSubmit(onClose: () => void) { unreachable('Cannot figure out current profile' as never), ) - const [encrypted, token] = await Services.Crypto.encryptTo( + const [_encrypted, token] = await Services.Crypto.encryptTo( content, target === 'Everyone' ? [] : target.map((x) => x.identifier), whoAmI?.identifier ?? currentProfile, target === 'Everyone', ) + const encrypted = socialNetworkEncoder(activatedSocialNetworkUI.network, _encrypted) const redPacketPreText = isTwitter(activatedSocialNetworkUI) || isFacebook(activatedSocialNetworkUI) ? t('additional_post_box__encrypted_post_pre_red_packet_twitter_official_account', { diff --git a/packages/mask/src/components/DataSource/usePostInfo.ts b/packages/mask/src/components/DataSource/usePostInfo.ts index 51e502f65e66..7f5854c999ad 100644 --- a/packages/mask/src/components/DataSource/usePostInfo.ts +++ b/packages/mask/src/components/DataSource/usePostInfo.ts @@ -1,17 +1,11 @@ import { activatedSocialNetworkUI } from '../../social-network' import { usePostInfoDetails } from '@masknet/plugin-infra' -import type { ProfileIdentifier } from '@masknet/shared-base' -export { usePostInfo, PostInfoProvider, usePostInfoDetails, usePostInfoSharedPublic } from '@masknet/plugin-infra' +export { usePostInfo, PostInfoProvider, usePostInfoDetails } from '@masknet/plugin-infra' export function usePostLink() { - const id = usePostInfoDetails.snsID() + const url = usePostInfoDetails.url() const identifier = usePostInfoDetails.identifier() - if (!id || !identifier) return '' + if (url) return url.toString() + if (!identifier) return '' return activatedSocialNetworkUI.utils.getPostURL?.(identifier) ?? '' } -export function usePostClaimedAuthor(): ProfileIdentifier | undefined { - const payload = usePostInfoDetails.containingMaskPayload().unwrapOr(undefined) - if (!payload) return undefined - if (payload.version !== -38) return undefined - return payload.authorUserID -} diff --git a/packages/mask/src/components/DebugModeUI/DebugList.tsx b/packages/mask/src/components/DebugModeUI/DebugList.tsx deleted file mode 100644 index cf503db43779..000000000000 --- a/packages/mask/src/components/DebugModeUI/DebugList.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Fragment } from 'react' - -type AcceptableDebuggerType = string | number | undefined | boolean -function F({ content, hint }: { hint: string; content: AcceptableDebuggerType }) { - return String(content).length > 50 ? ( -
- {hint}: - {String(content)} -
- ) : ( -
  • - {hint}: - {String(content)} -
  • - ) -} -export function DebugList(props: { items: readonly (readonly [string, AcceptableDebuggerType] | JSX.Element)[] }) { - return ( -
    - {props.items.map((x, key) => ( - {Array.isArray(x) ? : x} - ))} -
    - ) -} diff --git a/packages/mask/src/components/DebugModeUI/PostHashDialog.tsx b/packages/mask/src/components/DebugModeUI/PostHashDialog.tsx deleted file mode 100644 index 259b873a3074..000000000000 --- a/packages/mask/src/components/DebugModeUI/PostHashDialog.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { useState } from 'react' -import { useAsync } from 'react-use' -import Button from '@mui/material/Button' -import List from '@mui/material/List' -import ListItem from '@mui/material/ListItem' -import ListItemAvatar from '@mui/material/ListItemAvatar' -import ListItemText from '@mui/material/ListItemText' -import { useFriendsList } from '../DataSource/useActivatedUI' -import { Avatar } from '../../utils/components/Avatar' -import type { Profile } from '../../database' -import Services from '../../extension/service' -import { PostIVIdentifier } from '@masknet/shared-base' -import { deconstructPayload } from '../../utils/type-transform/Payload' -import { DialogContent, DialogContentText } from '@mui/material' -import { InjectedDialog } from '../shared/InjectedDialog' - -export interface SimpleDialogProps { - open: boolean - onClose: () => void - friends: Profile[] - hashMap: [string, string, string][] -} - -function PostHashDialog(props: SimpleDialogProps) { - const { open } = props - - const map = new Map() - for (const [id, magicCode, fingerprint] of props.hashMap) { - map.set(id, [magicCode, fingerprint]) - } - - return ( - - - - Appear in this list is not related to if you have shared this post to someone or not. - - - The "Magic Code" and the Fingerprint should be the same on your friend's Mask and your Mask. - - - If Fingerprint is not the same, it means at least one of Mask doesn't get the correct key of the - receiver. - - - If MagicCode is not the same, it means at least one of Mask calculate the post hash wrong. - - - {props.friends.map((one) => { - const [magicCode, fingerprint] = map.get(one.identifier.toText()) || ['Unknown', 'Unknown'] - return ( - - - - - - Magic code: {magicCode || 'Unknown'} -
    - Their fingerprint: {fingerprint} - - } - /> -
    - ) - })} -
    -
    -
    - ) -} - -export function DebugModeUI_PostHashDialog(props: { post: string; network: string }) { - const [open, setOpen] = useState(false) - const payload = deconstructPayload(props.post, null) - const friends = useFriendsList() - const { value: hashMap = [] } = useAsync(async () => { - if (!payload.ok) return [] - const ivID = new PostIVIdentifier(props.network, payload.val.iv) - return Services.Crypto.debugShowAllPossibleHashForPost(ivID, payload.val.version) - }, [props.post]) - const shouldHide = payload.map((x) => x.version === -38 && !!x.sharedPublic).unwrapOr(true) - if (shouldHide) return null - return ( - <> - - setOpen(false)} /> - - ) -} diff --git a/packages/mask/src/components/InjectedComponents/AddToKeyStore.tsx b/packages/mask/src/components/InjectedComponents/AddToKeyStore.tsx deleted file mode 100644 index d1f5a519fcdb..000000000000 --- a/packages/mask/src/components/InjectedComponents/AddToKeyStore.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { useAsync } from 'react-use' -import { createElement, memo } from 'react' -import { useI18N } from '../../utils' -import { AdditionalContent, AdditionalContentProps } from './AdditionalPostContent' -import Services from '../../extension/service' -import type { ProfileIdentifier } from '@masknet/shared-base' - -export interface AddToKeyStoreProps { - provePost: string - postBy: ProfileIdentifier - completeComponentProps?: Partial - completeComponent?: React.ComponentType<{ data: boolean }> | null -} -export function AddToKeyStore({ provePost, postBy, ...props }: AddToKeyStoreProps) { - const state = useAsync(() => Services.Crypto.verifyOthersProve(provePost, postBy), [provePost, postBy]) - const { completeComponent: Success, completeComponentProps } = props - if (state.value) return render(Success, AddToKeyStoreUI.success, completeComponentProps) - else return null - function render(outer: React.ComponentType | null | undefined, def: React.ComponentType, props?: {}) { - if (outer === null) return null - return createElement(outer || def, props) - } -} -type SuccessProps = Partial -export const AddToKeyStoreUI = { - success: memo((props: SuccessProps) => { - const { t } = useI18N() - return - }), -} diff --git a/packages/mask/src/components/InjectedComponents/AdditionalPostContent.tsx b/packages/mask/src/components/InjectedComponents/AdditionalPostContent.tsx index 1706c80ee31b..fe6c2fa927e6 100644 --- a/packages/mask/src/components/InjectedComponents/AdditionalPostContent.tsx +++ b/packages/mask/src/components/InjectedComponents/AdditionalPostContent.tsx @@ -1,8 +1,9 @@ import { Typography, Card, Box, CircularProgress, CircularProgressProps } from '@mui/material' -import { makeStyles, useStylesExtends } from '@masknet/theme' +import { makeStyles } from '@masknet/theme' import classNames from 'classnames' -import { TypedMessage, makeTypedMessageText } from '@masknet/shared-base' -import { TypedMessageRendererProps, DefaultTypedMessageRenderer } from './TypedMessageRenderer' +import { TypedMessage, makeTypedMessageText } from '@masknet/typed-message/base' +import { TypedMessageRender, MetadataRenderProps } from '@masknet/typed-message/dom' +import { TypedMessageRenderContext } from '../../../shared-ui/TypedMessageRender/context' import CheckIcon from '@mui/icons-material/Check' import CloseIcon from '@mui/icons-material/Close' import green from '@mui/material/colors/green' @@ -13,9 +14,7 @@ export enum AdditionalIcon { check = 'check', error = 'error', } -export interface AdditionalContentProps - extends withClasses, - Omit, 'message'> { +export interface AdditionalContentProps { title: string titleIcon?: keyof typeof AdditionalIcon headerActions?: React.ReactNode @@ -34,7 +33,7 @@ const useStyles = makeStyles()((theme) => ({ })) export const AdditionalContent = memo(function AdditionalContent(props: AdditionalContentProps): JSX.Element { - const classes = useStylesExtends(useStyles(), props) + const { classes } = useStyles() const stop = useCallback((ev: React.MouseEvent) => ev.stopPropagation(), []) const { progress, title, message } = props const ProgressJSX = !progress ? null : progress === true ? ( @@ -76,7 +75,9 @@ export const AdditionalContent = memo(function AdditionalContent(props: Addition
    {header}
    {message ? (
    - + + +
    ) : null} diff --git a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostAwaiting.tsx b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostAwaiting.tsx index bd8a964fe434..26216a434348 100644 --- a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostAwaiting.tsx +++ b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostAwaiting.tsx @@ -1,11 +1,12 @@ import { memo } from 'react' import { useI18N } from '../../../utils' import { AdditionalContent } from '../AdditionalPostContent' -import type { DecryptionProgress } from '../../../extension/background-script/CryptoServices/decryptFrom' import type { ProfileIdentifier } from '@masknet/shared-base' import { wrapAuthorDifferentMessage } from './authorDifferentMessage' +import { DecryptIntermediateProgressKind, DecryptIntermediateProgress } from '@masknet/encryption' +import { useTimeout } from 'react-use' export interface DecryptPostAwaitingProps { - type?: DecryptionProgress + type?: DecryptIntermediateProgress /** The author in the payload */ author?: ProfileIdentifier /** The author of the encrypted post */ @@ -14,21 +15,21 @@ export interface DecryptPostAwaitingProps { export const DecryptPostAwaiting = memo(function DecryptPostAwaiting(props: DecryptPostAwaitingProps) { const { author, postedBy, type } = props const { t } = useI18N() - const key = { - finding_post_key: t('decrypted_postbox_decrypting_finding_post_key'), - finding_person_public_key: t('decrypted_postbox_decrypting_finding_person_key'), - init: t('decrypted_postbox_decrypting'), - decode_post: t('decrypted_postbox_decoding'), - iv_decrypted: t('decrypted_postbox_decoding'), - payload_decrypted: t('decrypted_postbox_decoding'), - intermediate_success: 'unreachable case. it should display success UI', - undefined: t('decrypted_postbox_decrypting'), - } as const + + const [isReady] = useTimeout(5000) + + let text = t('decrypted_postbox_decrypting') + if (type?.event === DecryptIntermediateProgressKind.TryDecryptByE2E) { + text = t('decrypted_postbox_decrypting_finding_post_key') + if (isReady()) text = t('decrypted_postbox_decrypting_finding_post_key_long') + } + + const shouldShowProgress = type?.event !== DecryptIntermediateProgressKind.TryDecryptByE2E || !isReady() return ( ) }) diff --git a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx index 849d15a05539..33967cdf68f4 100644 --- a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx +++ b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx @@ -1,7 +1,7 @@ import { memo } from 'react' import { useI18N } from '../../../utils' import { AdditionalContent } from '../AdditionalPostContent' -import { DecryptFailedReason } from '../../../utils/constants' +import { ErrorReasons } from '@masknet/encryption' import type { ProfileIdentifier } from '@masknet/shared-base' import { wrapAuthorDifferentMessage } from './authorDifferentMessage' import MaskPluginWrapper from '../../../plugins/MaskPluginWrapper' @@ -17,7 +17,7 @@ export const DecryptPostFailed = memo(function DecryptPostFailed(props: DecryptP const { author, postedBy, error } = props const { t } = useI18N() - if (error?.message === DecryptFailedReason.MyCryptoKeyNotFound) { + if (error?.message === ErrorReasons.CurrentProfileDoesNotConnectedToPersona) { return } return ( diff --git a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPost.tsx b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPost.tsx deleted file mode 100644 index 86fb0fca1cd9..000000000000 --- a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPost.tsx +++ /dev/null @@ -1,252 +0,0 @@ -import { Fragment, useEffect, useMemo, useReducer, useState } from 'react' -import { - delay, - makeTypedMessageTuple, - TypedMessageTuple, - type ProfileIdentifier, - type Payload, -} from '@masknet/shared-base' -import { or } from '@masknet/theme' -import { unreachable } from '@dimensiondev/kit' - -import { ServicesWithProgress } from '../../../extension/service' -import type { Profile } from '../../../database' -import type { - DecryptionProgress, - FailureDecryption, - SuccessDecryption, -} from '../../../extension/background-script/CryptoServices/decryptFrom' -import { DecryptPostSuccess, DecryptPostSuccessProps } from './DecryptedPostSuccess' -import { DecryptPostAwaiting, DecryptPostAwaitingProps } from './DecryptPostAwaiting' -import { DecryptPostFailed, DecryptPostFailedProps } from './DecryptPostFailed' -import { DecryptedPostDebug } from './DecryptedPostDebug' -import { - usePostClaimedAuthor, - usePostInfoDetails, - usePostInfoSharedPublic, - usePostInfo, -} from '../../DataSource/usePostInfo' -import { asyncIteratorWithResult } from '../../../utils/type-transform/asyncIteratorHelpers' - -function progressReducer( - state: { key: string; progress: SuccessDecryption | FailureDecryption | DecryptionProgress }[], - payload: { - type: 'refresh' - key: string - progress: SuccessDecryption | FailureDecryption | DecryptionProgress - }, -) { - const { key, progress } = payload - const currentProgressIndex = state.findIndex((x) => x.key === key) - if (currentProgressIndex === -1) { - return [ - ...state, - { - key, - progress, - }, - ] - } - const currentProgress = state[currentProgressIndex].progress - if (currentProgress && currentProgress.type !== 'progress' && progress.type === 'progress') return state - state[currentProgressIndex] = { - key, - progress, - } - return [...state] -} - -export interface DecryptPostProps { - onDecrypted: (post: TypedMessageTuple) => void - whoAmI: ProfileIdentifier - profiles: Profile[] - alreadySelectedPreviously: Profile[] - requestAppendRecipients?(to: Profile[]): Promise - successComponent?: React.ComponentType - successComponentProps?: Partial - waitingComponent?: React.ComponentType - waitingComponentProps?: Partial - failedComponent?: React.ComponentType - failedComponentProps?: Partial -} -export function DecryptPost(props: DecryptPostProps) { - const { whoAmI, profiles, alreadySelectedPreviously, onDecrypted } = props - const deconstructedPayload = usePostInfoDetails.containingMaskPayload() - const authorInPayload = usePostClaimedAuthor() - const current = usePostInfo()! - const currentPostBy = usePostInfoDetails.author() - const decryptedPayloadForImage = usePostInfoDetails.decryptedPayloadForImage() - const postBy = or(authorInPayload, currentPostBy) - const postMetadataImages = usePostInfoDetails.postMetadataImages() - const Success = props.successComponent || DecryptPostSuccess - const Awaiting = props.waitingComponent || DecryptPostAwaiting - const Failed = props.failedComponent || DecryptPostFailed - - const requestAppendRecipientsWrapped = useMemo(() => { - if (!postBy.equals(whoAmI)) return undefined - if (!props.requestAppendRecipients) return undefined - return async (people: Profile[]) => { - await props.requestAppendRecipients!(people) - await delay(1500) - } - }, [props.requestAppendRecipients, postBy, whoAmI]) - - // #region Debug info - const [debugHash, setDebugHash] = useState('Unknown') - // #endregion - - // #region Progress - const [progress, dispatch] = useReducer(progressReducer, []) - // #endregion - - // #region decrypt - - // pass 1: - // decrypt post content and image attachments - const decryptedPayloadForImageAlpha38 = decryptedPayloadForImage?.version === -38 ? decryptedPayloadForImage : null - const sharedPublic = usePostInfoSharedPublic() || decryptedPayloadForImageAlpha38?.sharedPublic || false - - useEffect(() => { - const signal = new AbortController() - async function makeProgress( - key: string, - decryptionProcess: ReturnType, - ) { - const refreshProgress = (progress: SuccessDecryption | FailureDecryption | DecryptionProgress) => - dispatch({ - type: 'refresh', - key, - progress, - }) - for await (const process of asyncIteratorWithResult(decryptionProcess)) { - if (signal.signal.aborted) - return decryptionProcess.return?.({ type: 'error', internal: true, error: 'aborted' }) - if (process.done) { - if (process.value.type === 'success') { - current.iv.value = process.value.iv - current.decryptedPayloadForImage.value = process.value.decryptedPayloadForImage - } - return refreshProgress(process.value) - } - const status = process.value - if (status.type === 'debug') { - switch (status.debug) { - case 'debug_finding_hash': - setDebugHash(status.hash.join('-')) - break - default: - unreachable(status.debug) - } - } else refreshProgress(status) - if (status.type === 'progress') { - if (status.progress === 'intermediate_success') refreshProgress(status.data) - else if (status.progress === 'iv_decrypted') current.iv.value = status.iv - else if (status.progress === 'payload_decrypted') - current.decryptedPayloadForImage.value = status.decryptedPayloadForImage - } - } - } - - const postURL = current.url.getCurrentValue()?.toString() - if (deconstructedPayload.ok) - makeProgress( - 'post text', - ServicesWithProgress.decryptFromText(deconstructedPayload.val, postBy, whoAmI.network, whoAmI, postURL), - ) - postMetadataImages.forEach((url) => { - if (signal.signal.aborted) return - makeProgress(url, ServicesWithProgress.decryptFromImageUrl(url, postBy, whoAmI.network, whoAmI, postURL)) - }) - return () => signal.abort() - }, [ - current.iv, - deconstructedPayload.ok, - (deconstructedPayload.val as Payload)?.encryptedText, - postBy.toText(), - postMetadataImages.join(), - whoAmI.toText(), - ]) - - // pass 2: - // decrypt rest attachments which depend on post content - // const decryptedPostContent = progress.find((p) => p.key === postContent) - // useEffect(() => { - // if (decryptedPostContent?.progress.type !== 'success') return - // // TODO: - // // decrypt shuffled image here - // }, [decryptedPostContent]) - - // pass 3: - // invoke callback - const firstSucceedDecrypted = progress.find((p) => p.progress.type === 'success') - useEffect(() => { - if (firstSucceedDecrypted?.progress.type !== 'success') return - onDecrypted(makeTypedMessageTuple([firstSucceedDecrypted.progress.content])) - }, [firstSucceedDecrypted, onDecrypted]) - // #endregion - - // it's not a secret post - if (!deconstructedPayload.ok && progress.every((x) => x.progress.internal)) return null - return ( - <> - {progress - // the internal progress should not display to the end-user - .filter(({ progress }) => !progress.internal) - .map(({ progress }, index) => ( - {renderProgress(progress)} - ))} - - ) - - function renderProgress(progress: SuccessDecryption | FailureDecryption | DecryptionProgress) { - const render = () => { - switch (progress.type) { - case 'success': - return ( - - ) - case 'error': - return ( - - ) - case 'progress': - return ( - - ) - default: - return null - } - } - const rendered = render() - if (!rendered) return null - return ( - <> - {rendered} - - - ) - } -} diff --git a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostDebug.tsx b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostDebug.tsx deleted file mode 100644 index 38ee4293616a..000000000000 --- a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostDebug.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { Environment, isEnvironment } from '@dimensiondev/holoflows-kit' -import { useValueRef } from '@masknet/shared' -import type { ProfileIdentifier, PayloadAlpha38 } from '@masknet/shared-base' -import { useMemo } from 'react' -import type { - FailureDecryption, - SuccessDecryption, -} from '../../../extension/background-script/CryptoServices/decryptFrom' -import { debugModeSetting } from '../../../settings/settings' -import { deconstructPayload } from '../../../utils/type-transform/Payload' -import { usePostInfoDetails } from '../../DataSource/usePostInfo' -import { DebugList } from '../../DebugModeUI/DebugList' -import { DebugModeUI_PostHashDialog } from '../../DebugModeUI/PostHashDialog' - -interface DebugDisplayProps { - whoAmI: ProfileIdentifier - debugHash: string - decryptedResult: SuccessDecryption | FailureDecryption | null -} -export function DecryptedPostDebug(props: Partial) { - const postBy = usePostInfoDetails.author() - const postContent = usePostInfoDetails.postContent() - const payloadResult = useMemo(() => deconstructPayload(postContent), [postContent]) - const setting = useValueRef(debugModeSetting) - const isDebugging = isEnvironment(Environment.ManifestOptions) ? true : setting - - const { debugHash, decryptedResult, whoAmI } = props - if (!isDebugging) return null - const postByMyself = - if (payloadResult.err) - return ( - - ) - const payload = payloadResult.val - const ownersAESKeyEncrypted = payload.version === -38 ? payload.AESKeyEncrypted : payload.ownersAESKeyEncrypted - return ( - - ) -} diff --git a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx index 40ae0dd9c48a..0cd2358fc3f4 100644 --- a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx +++ b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx @@ -5,33 +5,10 @@ import { useShareMenu } from '../SelectPeopleDialog' import { makeStyles, useStylesExtends } from '@masknet/theme' import { Link } from '@mui/material' import type { Profile } from '../../../database' -import { extractTextFromTypedMessage } from '@masknet/shared-base' -import type { TypedMessage, ProfileIdentifier } from '@masknet/shared-base' +import type { TypedMessage } from '@masknet/typed-message/base' +import type { ProfileIdentifier } from '@masknet/shared-base' import { wrapAuthorDifferentMessage } from './authorDifferentMessage' -import { createInjectHooksRenderer, useActivatedPluginsSNSAdaptor } from '@masknet/plugin-infra' -import type { MetadataRendererProps } from '../TypedMessageRenderer' -import { - useDisabledPluginSuggestionFromMeta, - useDisabledPluginSuggestionFromPost, - PossiblePluginSuggestionUI, -} from '../DisabledPluginSuggestion' -const PluginRenderer = createInjectHooksRenderer( - useActivatedPluginsSNSAdaptor.visibility.useNotMinimalMode, - (x) => x.DecryptedInspector, -) -function PluginRendererWithSuggestion(props: MetadataRendererProps) { - const a = useDisabledPluginSuggestionFromMeta(props.metadata || new Map()) - const b = useDisabledPluginSuggestionFromPost(extractTextFromTypedMessage(props.message), []) - - const suggest = Array.from(new Set(a.concat(b))) - return ( - <> - - - - ) -} export interface DecryptPostSuccessProps extends withClasses { data: { content: TypedMessage } requestAppendRecipients?(to: Profile[]): Promise @@ -76,7 +53,6 @@ export const DecryptPostSuccess = memo(function DecryptPostSuccess(props: Decryp <> {shareMenu.ShareMenu} x.DecryptedInspector, +) +export function PluginRendererWithSuggestion(props: MetadataRenderProps) { + const a = useDisabledPluginSuggestionFromMeta(props.metadata) + const b = useDisabledPluginSuggestionFromPost(extractTextFromTypedMessage(props.message), []) + + const suggest = Array.from(new Set(a.concat(b))) + return ( + <> + + + + ) +} diff --git a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx index 59ec3d778954..ad7dbb81f6cd 100644 --- a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx +++ b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx @@ -5,7 +5,7 @@ import { Option, Plugin, } from '@masknet/plugin-infra' -import { extractTextFromTypedMessage } from '@masknet/shared-base' +import { extractTextFromTypedMessage } from '@masknet/typed-message/base' import { Switch } from '@mui/material' import Services from '../../extension/service' import MaskPluginWrapper from '../../plugins/MaskPluginWrapper' @@ -32,8 +32,9 @@ export function useDisabledPluginSuggestionFromPost(postContent: Option, return matches } -export function useDisabledPluginSuggestionFromMeta(meta: ReadonlyMap) { +export function useDisabledPluginSuggestionFromMeta(meta: undefined | ReadonlyMap) { const disabled = useDisabledPlugins().filter((x) => x.contribution?.metadataKeys) + if (!meta) return [] const keys = [...meta.keys()] const matches = disabled.filter((x) => { diff --git a/packages/mask/src/components/InjectedComponents/PayloadReplacer.tsx b/packages/mask/src/components/InjectedComponents/PayloadReplacer.tsx deleted file mode 100644 index a963f5e8b300..000000000000 --- a/packages/mask/src/components/InjectedComponents/PayloadReplacer.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Typography, Link } from '@mui/material' -import { makeStyles } from '@masknet/theme' -import { useI18N } from '../../utils' -const useStyle = makeStyles()((theme) => ({ - text: { - fontSize: 'inherit', - marginLeft: theme.spacing(0.5), - marginRight: theme.spacing(0.5), - }, -})) - -export interface PayloadReplacerProps { - payload: string -} - -export function PayloadReplacer({ payload }: PayloadReplacerProps) { - const { t } = useI18N() - const { classes } = useStyle() - return ( - - - {t('post_substitute_label')} - - - ) -} diff --git a/packages/mask/src/components/InjectedComponents/PostComments.tsx b/packages/mask/src/components/InjectedComponents/PostComments.tsx index c6168fad225e..88d339d577e6 100644 --- a/packages/mask/src/components/InjectedComponents/PostComments.tsx +++ b/packages/mask/src/components/InjectedComponents/PostComments.tsx @@ -6,9 +6,7 @@ import type { ChipProps } from '@mui/material/Chip' import Lock from '@mui/icons-material/Lock' import { useEffect } from 'react' import { useAsync } from 'react-use' -import Services from '../../extension/service' -import { extractTextFromTypedMessage } from '@masknet/shared-base' -import { usePostInfoDetails } from '../DataSource/usePostInfo' +import { usePostInfo } from '../DataSource/usePostInfo' const useStyle = makeStyles()({ root: { @@ -46,18 +44,13 @@ export interface PostCommentProps { export function PostComment(props: PostCommentProps) { const { needZip } = props const comment = useValueRef(props.comment) - const postContent = usePostInfoDetails.rawMessagePiped() - const containingPayload = usePostInfoDetails.containingMaskPayload() - const iv = usePostInfoDetails.iv() - const postIV = containingPayload.map((x) => x.iv).unwrapOr(iv) + const { decryptPostComment } = usePostInfo()! const dec = useAsync(async () => { - const decryptedText = extractTextFromTypedMessage(postContent).unwrap() - if (!postIV || !decryptedText) throw new Error('Decrypt comment failed') - const result = await Services.Crypto.decryptComment(postIV, decryptedText, comment) + const result = await decryptPostComment(comment) if (result === null) throw new Error('Decrypt result empty') return result - }, [postIV, postContent, comment]) + }, [comment]) useEffect(() => void (dec.value && needZip()), [dec.value, needZip]) if (dec.value) return {dec.value} diff --git a/packages/mask/src/components/InjectedComponents/PostInspector.tsx b/packages/mask/src/components/InjectedComponents/PostInspector.tsx index 15667c9b1eb0..d630e7fb8db3 100644 --- a/packages/mask/src/components/InjectedComponents/PostInspector.tsx +++ b/packages/mask/src/components/InjectedComponents/PostInspector.tsx @@ -1,21 +1,4 @@ -import { useState, useEffect, useMemo } from 'react' -import { useAsync } from 'react-use' -import { DecryptPost } from './DecryptedPost/DecryptedPost' -import { AddToKeyStore } from './AddToKeyStore' -import Services from '../../extension/service' -import { - ProfileIdentifier, - type TypedMessageTuple, - type PayloadAlpha40_Or_Alpha39, - type PayloadAlpha38, -} from '@masknet/shared-base' -import type { Profile } from '../../database' -import { useCurrentIdentity, useFriendsList } from '../DataSource/useActivatedUI' -import { useValueRef } from '@masknet/shared' -import { debugModeSetting } from '../../settings/settings' -import { DebugList } from '../DebugModeUI/DebugList' import { usePostInfoDetails } from '../DataSource/usePostInfo' -import { decodePublicKeyUI } from '../../social-network/utils/text-payload-ui' import { createInjectHooksRenderer, useActivatedPluginsSNSAdaptor } from '@masknet/plugin-infra' import { PossiblePluginSuggestionPostInspector } from './DisabledPluginSuggestion' @@ -24,100 +7,16 @@ const PluginHooksRenderer = createInjectHooksRenderer( (plugin) => plugin.PostInspector, ) -export interface PostInspectorProps { - onDecrypted(post: TypedMessageTuple): void - needZip(): void - /** @default 'before' */ - slotPosition?: 'before' | 'after' -} -export function PostInspector(props: PostInspectorProps) { +export function PostInspector() { const postBy = usePostInfoDetails.author() - const postContent = usePostInfoDetails.postContent() - const encryptedPost = usePostInfoDetails.containingMaskPayload() - const postId = usePostInfoDetails.identifier() - const decryptedPayloadForImage = usePostInfoDetails.decryptedPayloadForImage() - const postImages = usePostInfoDetails.postMetadataImages() - const isDebugging = useValueRef(debugModeSetting) - const whoAmI = useCurrentIdentity() - const friends = useFriendsList() - const [alreadySelectedPreviously, setAlreadySelectedPreviously] = useState([]) - const provePost = useMemo(() => decodePublicKeyUI(postContent), [postContent]) - - const { value: sharedListOfPost } = useAsync(async () => { - if (!whoAmI || !whoAmI.identifier.equals(postBy) || !encryptedPost.ok) return [] - const { iv, version } = encryptedPost.val - return Services.Crypto.getPartialSharedListOfPost(version, iv, postBy) - }, [postBy, whoAmI, encryptedPost]) - useEffect(() => setAlreadySelectedPreviously(sharedListOfPost ?? []), [sharedListOfPost]) - - const debugInfo = isDebugging ? ( - - ) : null - - if (encryptedPost.ok || postImages.length) { - if (!isDebugging) props.needZip() - return withAdditionalContent( - { - const val = (postImages ? decryptedPayloadForImage : encryptedPost.val) as - | PayloadAlpha40_Or_Alpha39 - | PayloadAlpha38 - - const { iv, version } = val - const ownersAESKeyEncrypted = - val.version === -38 ? val.AESKeyEncrypted : val.ownersAESKeyEncrypted - setAlreadySelectedPreviously(alreadySelectedPreviously.concat(profile)) - return Services.Crypto.appendShareTarget( - version, - ownersAESKeyEncrypted, - iv, - profile.map((x) => x.identifier), - whoAmI!.identifier, - { type: 'direct', at: new Date() }, - ) - } - : undefined - } - alreadySelectedPreviously={alreadySelectedPreviously} - profiles={friends} - whoAmI={whoAmI ? whoAmI.identifier : ProfileIdentifier.unknown} - />, - ) - } else if (provePost.length) { - return withAdditionalContent() - } - return withAdditionalContent(null) - function withAdditionalContent(x: JSX.Element | null) { - const slot = encryptedPost.ok ? null : - return ( - <> - {process.env.NODE_ENV === 'development' && postBy.isUnknown ? ( -

    Please fix me. Post author is $unknown

    - ) : null} - {props.slotPosition !== 'after' && slot} - {x} - - - {debugInfo} - {props.slotPosition !== 'before' && slot} - - ) - } + return ( + <> + {process.env.NODE_ENV === 'development' && postBy.isUnknown ? ( +

    Please fix me. Post author is $unknown

    + ) : null} + + + + ) } diff --git a/packages/mask/src/components/InjectedComponents/PostReplacer.tsx b/packages/mask/src/components/InjectedComponents/PostReplacer.tsx index 2d3145494b9a..7d739ffddb3a 100644 --- a/packages/mask/src/components/InjectedComponents/PostReplacer.tsx +++ b/packages/mask/src/components/InjectedComponents/PostReplacer.tsx @@ -1,17 +1,12 @@ -import { useActivatedPluginsSNSAdaptor } from '@masknet/plugin-infra' -import { useValueRef } from '@masknet/shared' -import { - isTypedMessagePromise, - isTypedMessageTuple, - isWellKnownTypedMessages, - makeTypedMessageTuple, -} from '@masknet/shared-base' import { makeStyles } from '@masknet/theme' import { useEffect, useMemo } from 'react' -import { Result } from 'ts-results' -import { allPostReplacementSettings } from '../../settings/settings' import { usePostInfoDetails } from '../DataSource/usePostInfo' -import { DefaultTypedMessageRenderer } from './TypedMessageRenderer' +import { TypedMessageRender, useTransformedValue } from '@masknet/typed-message/dom' +import { TypedMessageRenderContext } from '../../../shared-ui/TypedMessageRender/context' +import type { TransformationContext, TypedMessage } from '@masknet/typed-message/base' +import { useCurrentIdentity } from '../DataSource/useActivatedUI' +import { PluginRendererWithSuggestion } from './DecryptedPostMetadataRender' + const useStyles = makeStyles()({ root: { overflowWrap: 'break-word', @@ -26,30 +21,18 @@ export interface PostReplacerProps { export function PostReplacer(props: PostReplacerProps) { const { classes } = useStyles() const postMessage = usePostInfoDetails.rawMessage() - const postPayload = usePostInfoDetails.containingMaskPayload() - const allPostReplacement = useValueRef(allPostReplacementSettings) + const author = usePostInfoDetails.author() + const currentProfile = useCurrentIdentity()?.identifier + const url = usePostInfoDetails.url() - const plugins = useActivatedPluginsSNSAdaptor(false) - const processedPostMessage = useMemo( - () => - plugins.reduce((x, plugin) => { - const result = Result.wrap(() => plugin.typedMessageTransformer?.(x) ?? x).unwrapOr(x) - if (isTypedMessageTuple(result)) return result - console.warn( - '[TypedMessage] typedMessageTransformer that return a non TypedMessageTuple is not supported yet. This transform is ignored', - result, - ) - return x - }, postMessage), - [plugins.map((x) => x.ID).join(), postMessage], - ) - const shouldReplacePost = - // replace all posts - allPostReplacement || - // replace posts which enhanced by plugins - processedPostMessage.items.some((x) => !isWellKnownTypedMessages(x)) || - // replace posts which encrypted by Mask - postPayload.ok + const shouldReplacePost = true + const initialTransformationContext = useMemo((): TransformationContext => { + return { + authorHint: author, + currentProfile, + postURL: url?.toString(), + } + }, [author, currentProfile, url]) // zip/unzip original post useEffect(() => { @@ -59,9 +42,15 @@ export function PostReplacer(props: PostReplacerProps) { return shouldReplacePost ? ( - !isTypedMessagePromise(x)))} - /> + + + ) : null } +function Transformer(props: { message: TypedMessage }) { + const after = useTransformedValue(props.message) + return +} diff --git a/packages/mask/src/components/InjectedComponents/SetupGuide.tsx b/packages/mask/src/components/InjectedComponents/SetupGuide.tsx index 033f2076367f..332dc08cbd3e 100644 --- a/packages/mask/src/components/InjectedComponents/SetupGuide.tsx +++ b/packages/mask/src/components/InjectedComponents/SetupGuide.tsx @@ -8,13 +8,8 @@ import { useI18N, MaskMessages } from '../../utils' import { activatedSocialNetworkUI, SocialNetworkUI } from '../../social-network' import { currentSetupGuideStatus, dismissPinExtensionTip, userGuideStatus } from '../../settings/settings' import type { SetupGuideCrossContextStatus } from '../../settings/types' -import { - PersonaIdentifier, - ProfileIdentifier, - Identifier, - ECKeyIdentifier, - makeTypedMessageText, -} from '@masknet/shared-base' +import { PersonaIdentifier, ProfileIdentifier, Identifier, ECKeyIdentifier } from '@masknet/shared-base' +import { makeTypedMessageText } from '@masknet/typed-message/base' import Services from '../../extension/service' import { useLastRecognizedIdentity } from '../DataSource/useActivatedUI' import { MaskIcon } from '../../resources/MaskIcon' diff --git a/packages/mask/src/components/InjectedComponents/TypedMessageRenderer.tsx b/packages/mask/src/components/InjectedComponents/TypedMessageRenderer.tsx deleted file mode 100644 index 9980572d87b9..000000000000 --- a/packages/mask/src/components/InjectedComponents/TypedMessageRenderer.tsx +++ /dev/null @@ -1,286 +0,0 @@ -import { Fragment, memo, createElement } from 'react' -import { Typography, Link } from '@mui/material' -import { makeStyles } from '@masknet/theme' -import anchorme from 'anchorme' -import classNames from 'classnames' -import { - TypedMessage, - TypedMessageText, - TypedMessageAnchor, - TypedMessageImage, - TypedMessageTuple, - TypedMessageUnknown, - TypedMessagePromise, - TypedMessageEmpty, - makeTypedMessageText, -} from '@masknet/shared-base' -import { Image } from '../shared/Image' -import { useAsync } from 'react-use' -import { getRendererOfTypedMessage, registerTypedMessageRenderer } from '../../protocols/typed-message' -import { deconstructPayload } from '../../utils/type-transform/Payload' -import { PayloadReplacer } from './PayloadReplacer' -import { useI18N } from '../../utils' - -export interface MetadataRendererProps { - metadata: TypedMessage['meta'] - message: TypedMessage -} -export interface TypedMessageRendererProps { - /** - * The TypedMessage - */ - message: T - allowTextEnlarge?: boolean - afterPreviousMetadata?: React.ReactNode - beforeLatterMetadata?: React.ReactNode - metadataRenderer?: { - before?: React.ComponentType - after?: React.ComponentType - } -} - -export const DefaultTypedMessageRenderer = memo(function DefaultTypedMessageRenderer( - props: TypedMessageRendererProps, -) { - const Renderer = getRendererOfTypedMessage(props.message)[0]?.component || DefaultTypedMessageUnknownRenderer - return -}) - -export const DefaultTypedMessageTextRenderer = memo(function DefaultTypedMessageTextRenderer( - props: TypedMessageRendererProps, -) { - const { content } = props.message - const deconstructed = deconstructPayload(content, null) - return renderWithMetadata( - props, - - {deconstructed.ok ? ( - - ) : ( - - )} - , - ) -}) -registerTypedMessageRenderer('text', { - component: DefaultTypedMessageTextRenderer, - id: 'mask.text', - priority: 0, -}) - -export const DefaultTypedMessageAnchorRenderer = memo(function DefaultTypedMessageAnchorRenderer( - props: TypedMessageRendererProps, -) { - const { content, href } = props.message - const deconstructed = deconstructPayload(content, null) - return renderWithMetadata( - props, - - {deconstructed.ok ? ( - - ) : ( - // TODO: shrink link size - - {content} - - )} - , - ) -}) -registerTypedMessageRenderer('x-anchor', { - component: DefaultTypedMessageAnchorRenderer, - id: 'mask.anchor', - priority: 0, -}) - -export const DefaultTypedMessageImageRenderer = memo(function DefaultTypedMessageImageRenderer( - props: TypedMessageRendererProps, -) { - const { image, width, height } = props.message - return renderWithMetadata( - props, - - - , - ) -}) -registerTypedMessageRenderer('image', { - component: DefaultTypedMessageImageRenderer, - id: 'mask.image', - priority: 0, -}) - -export const DefaultTypedMessageTupleRenderer = memo(function DefaultTypedMessageTupleRenderer( - props: TypedMessageRendererProps, -) { - const { t } = useI18N() - try { - JSON.stringify(props.message.items) - } catch (error) { - if (error instanceof Error && error.message.includes('circular structure')) { - return {t('typed_message_can_not_be_rendered')} - } - } - return ( - <> - {props.message.items.map((x, index) => ( - - ))} - - ) -}) -registerTypedMessageRenderer('tuple', { - component: DefaultTypedMessageTupleRenderer, - id: 'mask.compound', - priority: 0, -}) - -export const DefaultTypedMessageEmptyRenderer = memo(function DefaultTypedMessageEmptyRenderer( - props: TypedMessageRendererProps, -) { - return renderWithMetadata(props, null) -}) -registerTypedMessageRenderer('empty', { - component: DefaultTypedMessageEmptyRenderer, - id: 'mask.empty', - priority: 0, -}) - -export const DefaultTypedMessageUnknownRenderer = memo(function DefaultTypedMessageUnknownRenderer( - props: TypedMessageRendererProps, -) { - const { t } = useI18N() - - return renderWithMetadata( - props, - - {t('unknown')} {t('message')} - , - ) -}) -registerTypedMessageRenderer('unknown', { - component: DefaultTypedMessageUnknownRenderer, - id: 'mask.unknown', - priority: 0, -}) - -export const DefaultTypedMessageSuspendedRenderer = memo(function DefaultTypedMessageSuspendedRenderer( - props: TypedMessageRendererProps, -) { - const { promise } = props.message - const { loading, error, value } = useAsync(() => promise, [promise]) - - return renderWithMetadata( - props, - loading ? ( - - ) : error ? ( - - ) : ( - - ), - ) -}) -registerTypedMessageRenderer('promise', { - component: DefaultTypedMessageSuspendedRenderer, - id: 'mask.suspended', - priority: 0, -}) - -function DefaultMetadataRender() { - return null -} - -function renderWithMetadata(props: TypedMessageRendererProps, jsx: React.ReactNode) { - const Before = props.metadataRenderer?.before || DefaultMetadataRender - const After = props.metadataRenderer?.after || DefaultMetadataRender - return ( - <> - - {props.afterPreviousMetadata} - {jsx} - {props.beforeLatterMetadata} - - - ) -} - -const RenderText = memo(function RenderText(props: { text: string; allowTextEnlarge: boolean }) { - return createElement(Fragment, {}, ...parseText(props.text, props.allowTextEnlarge)) -}) - -interface ParseTextProps { - text: string - fontSize: number -} - -interface ParseTextLinkProps extends ParseTextProps { - link: string -} - -const useStyle = makeStyles()((theme, fontSize) => ({ - link: { - color: theme.palette.primary.main, - }, - text: { - fontSize: Number(fontSize) + 'rem', - }, -})) - -const ParseTextLink = memo(function ParseTextLink({ link, text, fontSize }: ParseTextLinkProps) { - const { classes } = useStyle(fontSize) - return ( - - {text} - - ) -}) - -const ParseText = memo(function ParseText({ text, fontSize }: ParseTextProps) { - const { classes } = useStyle(fontSize) - return {text} -}) - -function parseText(string: string, allowTextEnlarge: boolean) { - const links = anchorme.list(string) - let current = string - const fontSize = - allowTextEnlarge && Array.from(current).length < 45 - ? 1.5 - : allowTextEnlarge && Array.from(current).length < 85 - ? 1.2 - : 1 - - const result = [] - while (current.length) { - const search1 = current.indexOf('\n') - const search2 = links[0] ? current.indexOf(links[0].string) : -1 - // ? if rest is normal - if (search1 === -1 && search2 === -1) { - result.push() - break - } - // ? if rest have \n but no links - if ((search1 < search2 && search1 !== -1) || search2 === -1) { - result.push(,
    ) - current = current.substring(search1 + 1) - } - // ? if rest have links but no \n - if ((search2 < search1 && search2 !== -1) || search1 === -1) { - let link = links[0].string - if (!links[0].protocol) link = 'http://' + link - result.push( - , - , - ) - current = current.substring(search2 + links[0].string.length) - links.shift() - } - } - return result -} diff --git a/packages/mask/src/components/shared/DebugMetadataInspector.tsx b/packages/mask/src/components/shared/DebugMetadataInspector.tsx index 14981f00ae7d..f1726902b013 100644 --- a/packages/mask/src/components/shared/DebugMetadataInspector.tsx +++ b/packages/mask/src/components/shared/DebugMetadataInspector.tsx @@ -14,8 +14,8 @@ import { } from '@mui/material' import ExpandMoreIcon from '@mui/icons-material/ExpandMore' import { InjectedDialog } from './InjectedDialog' -import { isDataMatchJSONSchema, getKnownMetadataKeys, getMetadataSchema } from '@masknet/shared-base' -import { ShadowRootPopper } from '../../utils/shadow-root/ShadowRootComponents' +import { isDataMatchJSONSchema, getKnownMetadataKeys, getMetadataSchema } from '@masknet/typed-message/base' +import { ShadowRootPopper } from '../../../shared-ui/shadow-root/ShadowRootComponents' import { useState } from 'react' import { useI18N } from '../../utils' diff --git a/packages/mask/src/crypto/crypto-alpha-38.ts b/packages/mask/src/crypto/crypto-alpha-38.ts index d690293aea41..a94d8c46642e 100644 --- a/packages/mask/src/crypto/crypto-alpha-38.ts +++ b/packages/mask/src/crypto/crypto-alpha-38.ts @@ -1,16 +1,16 @@ /* eslint @dimensiondev/unicode-specific-set: ["error", { "only": "code" }] */ -import { TypedMessage, makeTypedMessageText, isTypedMessageText, type AESJsonWebKey } from '@masknet/shared-base' +import { TypedMessage, isTypedMessageText } from '@masknet/typed-message/base' +import type { AESJsonWebKey } from '@masknet/shared-base' export * from './crypto-alpha-39' -// @ts-ignore -export const publicSharedAESKey: AESJsonWebKey = { +export const publicSharedAESKey = { alg: 'A256GCM', ext: true, /* cspell:disable-next-line */ k: '3Bf8BJ3ZPSMUM2jg2ThODeLuRRD_-_iwQEaeLdcQXpg', key_ops: ['encrypt', 'decrypt'], kty: 'oct', -} +} as AESJsonWebKey /** * With plugin: {"payload": "data"}🧩My message * Without plugin: My message @@ -24,13 +24,3 @@ export function typedMessageStringify(x: TypedMessage) { return JSON.stringify(obj) + '\u{1F9E9}' + x.content } -export function typedMessageParse(x: string) { - const [maybeMetadata, ...end] = x.split('\u{1F9E9}') - try { - const json: unknown = JSON.parse(maybeMetadata) - if (typeof json !== 'object' || json === null || Object.keys(json).length === 0) - throw new Error('Not a metadata') - return makeTypedMessageText(end.join('\u{1F9E9}'), new Map(Object.entries(json))) - } catch {} - return makeTypedMessageText(x) -} diff --git a/packages/mask/src/crypto/crypto-alpha-39.ts b/packages/mask/src/crypto/crypto-alpha-39.ts index 58f8bfcddb62..d6d3df0430cc 100644 --- a/packages/mask/src/crypto/crypto-alpha-39.ts +++ b/packages/mask/src/crypto/crypto-alpha-39.ts @@ -79,8 +79,8 @@ export async function encrypt1ToN(info: { } } -export { encrypt1To1, decryptMessage1To1 } from './crypto-alpha-40' -export { decryptMessage1ToNByOther, decryptMessage1ToNByMyself, extractAESKeyInMessage } from './crypto-alpha-40' +export { encrypt1To1 } from './crypto-alpha-40' +export { extractAESKeyInMessage } from './crypto-alpha-40' export { encryptWithAES, decryptWithAES } from './crypto-alpha-40' export { encryptComment, decryptComment } from './crypto-alpha-40' -export { typedMessageStringify, typedMessageParse } from './crypto-alpha-40' +export { typedMessageStringify } from './crypto-alpha-40' diff --git a/packages/mask/src/crypto/crypto-alpha-40.ts b/packages/mask/src/crypto/crypto-alpha-40.ts index d5293eddf7ff..361881b94760 100644 --- a/packages/mask/src/crypto/crypto-alpha-40.ts +++ b/packages/mask/src/crypto/crypto-alpha-40.ts @@ -5,9 +5,8 @@ */ import { encodeText, encodeArrayBuffer, decodeArrayBuffer, decodeText, concatArrayBuffer } from '@dimensiondev/kit' import { memoizePromise } from '../../utils-pure' -import { i18n } from '../../shared-ui/locales_legacy' import { CryptoWorker } from '../modules/workers' -import { EC_Private_JsonWebKey, EC_Public_JsonWebKey, AESJsonWebKey, makeTypedMessageText } from '@masknet/shared-base' +import type { EC_Private_JsonWebKey, EC_Public_JsonWebKey, AESJsonWebKey } from '@masknet/shared-base' import { derive_AES_GCM_256_Key_From_PBKDF2, derive_AES_GCM_256_Key_From_ECDH_256k1_Keys, @@ -157,59 +156,7 @@ export async function encrypt1ToN(info: { return { encryptedContent, iv, version: -40, ownersAESKeyEncrypted, othersAESKeyEncrypted, postAESKey: AESKey } } // #endregion -// #region decrypt text -/** - * Decrypt 1 to 1 - */ -export async function decryptMessage1To1(info: { - version: -40 | -39 | -38 - encryptedContent: string | ArrayBuffer - salt: string | ArrayBuffer - /** Your private key */ - privateKeyECDH: EC_Private_JsonWebKey - /** If you are the author, this should be the receiver's public key. - * Otherwise, this should be the author's public key */ - anotherPublicKeyECDH: EC_Public_JsonWebKey -}): Promise { - const { anotherPublicKeyECDH, version, salt, encryptedContent, privateKeyECDH } = info - const encrypted = typeof encryptedContent === 'string' ? decodeArrayBuffer(encryptedContent) : encryptedContent - - const { iv, key } = await deriveAESKey(privateKeyECDH, anotherPublicKeyECDH, salt) - return CryptoWorker.decrypt_aes_gcm(key, iv, encrypted) -} -/** - * Decrypt 1 to N message that send by other - */ -export async function decryptMessage1ToNByOther(info: { - version: -40 | -39 | -38 - encryptedContent: string | ArrayBuffer - privateKeyECDH: EC_Private_JsonWebKey - authorsPublicKeyECDH: EC_Public_JsonWebKey - AESKeyEncrypted: PublishedAESKey | PublishedAESKey[] - iv: ArrayBuffer | string -}): Promise<[ArrayBuffer, AESJsonWebKey]> { - const { encryptedContent, privateKeyECDH, authorsPublicKeyECDH, iv } = info - const AESKeyEncrypted = Array.isArray(info.AESKeyEncrypted) ? info.AESKeyEncrypted : [info.AESKeyEncrypted] - let resolvedAESKey: string | null = null - await Promise.all( - AESKeyEncrypted.map(async (key) => { - try { - const result = await decryptMessage1To1({ - version: -40, - salt: key.salt, - encryptedContent: key.encryptedKey, - anotherPublicKeyECDH: authorsPublicKeyECDH, - privateKeyECDH: privateKeyECDH, - }) - resolvedAESKey = decodeText(result) - } catch {} - }), - ) - if (resolvedAESKey === null) throw new Error(i18n.t('service_not_share_target')) - const aesKey: AESJsonWebKey = JSON.parse(resolvedAESKey) - return [await decryptWithAES({ aesKey, iv, encrypted: encryptedContent }), aesKey] -} export async function extractAESKeyInMessage( version: -40 | -39 | -38, encodedEncryptedKey: string | ArrayBuffer, @@ -224,22 +171,7 @@ export async function extractAESKeyInMessage( ) return decryptedAESKeyJWK } -/** - * Decrypt 1 to N message that send by myself - */ -export async function decryptMessage1ToNByMyself(info: { - version: -40 | -39 | -38 - encryptedContent: string | ArrayBuffer - /** This should be included in the message */ - encryptedAESKey: string | ArrayBuffer - myLocalKey: AESJsonWebKey - iv: string | ArrayBuffer -}): Promise<[ArrayBuffer, AESJsonWebKey]> { - const { encryptedContent, myLocalKey, iv, encryptedAESKey } = info - const decryptedAESKey = await extractAESKeyInMessage(-40, encryptedAESKey, iv, myLocalKey) - const post = await decryptWithAES({ aesKey: decryptedAESKey, encrypted: encryptedContent, iv }) - return [post, decryptedAESKey] -} + /** * Decrypt the content encrypted by AES */ @@ -324,6 +256,3 @@ export async function decryptComment( export function typedMessageStringify(x: any) { throw new Error('Not supported typed message in version older than v39.') } -export function typedMessageParse(x: string) { - return makeTypedMessageText(x) -} diff --git a/packages/mask/src/database/Persona/helpers.ts b/packages/mask/src/database/Persona/helpers.ts index cca56b4c76b7..8c14a9f365e4 100644 --- a/packages/mask/src/database/Persona/helpers.ts +++ b/packages/mask/src/database/Persona/helpers.ts @@ -1,4 +1,5 @@ import type { Profile, Persona } from './types' +import { createPersonaByJsonWebKey } from '../../../background/database/persona/helper' import { ProfileRecord, queryProfilesDB, @@ -10,12 +11,8 @@ import { deletePersonaDB, safeDeletePersonaDB, queryPersonaByProfileDB, - createPersonaDB, - attachProfileDB, - LinkedProfileDetails, consistentPersonaDBWriteAccess, updatePersonaDB, - createOrUpdatePersonaDB, queryProfilesPagedDB, } from '../../../background/database/persona/db' import { queryAvatarDataURL } from '../../../background/database/avatar-cache/avatar' @@ -32,7 +29,6 @@ import { type EC_Public_JsonWebKey, type EC_Private_JsonWebKey, type AESJsonWebKey, - ECKeyIdentifierFromJsonWebKey, } from '@masknet/shared-base' export async function profileRecordToProfile(record: ProfileRecord): Promise { @@ -229,61 +225,6 @@ export async function createPersonaByMnemonicV2(mnemonicWord: string, nickname: }) } -export async function createPersonaByJsonWebKey(options: { - publicKey: EC_Public_JsonWebKey - privateKey: EC_Private_JsonWebKey - localKey?: AESJsonWebKey - nickname?: string - mnemonic?: PersonaRecord['mnemonic'] - uninitialized?: boolean -}): Promise { - const identifier = ECKeyIdentifierFromJsonWebKey(options.publicKey) - const record: PersonaRecord = { - createdAt: new Date(), - updatedAt: new Date(), - identifier: identifier, - linkedProfiles: new IdentifierMap(new Map(), ProfileIdentifier), - publicKey: options.publicKey, - privateKey: options.privateKey, - nickname: options.nickname, - mnemonic: options.mnemonic, - localKey: options.localKey, - hasLogout: false, - uninitialized: options.uninitialized, - } - await consistentPersonaDBWriteAccess((t) => createPersonaDB(record, t)) - return identifier -} -export async function createProfileWithPersona( - profileID: ProfileIdentifier, - data: LinkedProfileDetails, - keys: { - nickname?: string - publicKey: EC_Public_JsonWebKey - privateKey?: EC_Private_JsonWebKey - localKey?: AESJsonWebKey - mnemonic?: PersonaRecord['mnemonic'] - }, -): Promise { - const ec_id = ECKeyIdentifierFromJsonWebKey(keys.publicKey) - const rec: PersonaRecord = { - createdAt: new Date(), - updatedAt: new Date(), - identifier: ec_id, - linkedProfiles: new IdentifierMap(new Map(), ProfileIdentifier), - nickname: keys.nickname, - publicKey: keys.publicKey, - privateKey: keys.privateKey, - localKey: keys.localKey, - mnemonic: keys.mnemonic, - hasLogout: false, - } - await consistentPersonaDBWriteAccess(async (t) => { - await createOrUpdatePersonaDB(rec, { explicitUndefinedField: 'ignore', linkedProfiles: 'merge' }, t) - await attachProfileDB(profileID, ec_id, data, t) - }) -} - export async function queryLocalKey(i: ProfileIdentifier | PersonaIdentifier): Promise { if (i instanceof ProfileIdentifier) { const profile = await queryProfileDB(i) @@ -295,8 +236,3 @@ export async function queryLocalKey(i: ProfileIdentifier | PersonaIdentifier): P return (await queryPersonaDB(i))?.localKey ?? null } } -function cover_ECDH_256k1_KeyPair_ByMnemonicWord( - password: string, -): { key: any; mnemonicRecord: any } | PromiseLike<{ key: any; mnemonicRecord: any }> { - throw new Error('Function not implemented.') -} diff --git a/packages/mask/src/extension/background-script/CryptoService.ts b/packages/mask/src/extension/background-script/CryptoService.ts index 5dbe116ec82d..34b5aec1ce7e 100644 --- a/packages/mask/src/extension/background-script/CryptoService.ts +++ b/packages/mask/src/extension/background-script/CryptoService.ts @@ -7,14 +7,7 @@ export { encryptComment, decryptComment } from '../../crypto/crypto-alpha-40' export { encryptTo, publishPostAESKey } from './CryptoServices/encryptTo' export { appendShareTarget } from './CryptoServices/appendShareTarget' export { getPartialSharedListOfPost } from './CryptoServices/getPartialSharedListOfPost' -export { verifyOthersProve } from './CryptoServices/verifyOthersProve' export function steganographyEncodeImage(buf: ArrayBuffer, options: Omit) { return __steganographyEncodeImage(buf, { ...options, downloadImage: steganographyDownloadImage }) } - -import type { debugShowAllPossibleHashForPost as orig } from './CryptoServices/debugShowAllPossibleHashForPost' -// This module requires lazy loading otherwise it will load gun -export async function debugShowAllPossibleHashForPost(...args: Parameters) { - return (await import('./CryptoServices/debugShowAllPossibleHashForPost')).debugShowAllPossibleHashForPost(...args) -} diff --git a/packages/mask/src/extension/background-script/CryptoServices/appendShareTarget.ts b/packages/mask/src/extension/background-script/CryptoServices/appendShareTarget.ts index c0cfddbef48a..f18e5032fad2 100644 --- a/packages/mask/src/extension/background-script/CryptoServices/appendShareTarget.ts +++ b/packages/mask/src/extension/background-script/CryptoServices/appendShareTarget.ts @@ -1,5 +1,4 @@ import * as Alpha39 from '../../../crypto/crypto-alpha-39' -import { GunAPI as Gun2 } from '../../../network/gun/' import { ProfileIdentifier, PostIVIdentifier, @@ -12,6 +11,8 @@ import { cryptoProviderTable } from './cryptoProviderTable' import { updatePostDB, RecipientDetail, RecipientReason } from '../../../../background/database/post' import { getNetworkWorkerUninitialized } from '../../../social-network/worker' import { queryPrivateKey, queryLocalKey } from '../../../database' +import { publishPostAESKey_version39Or38 } from '../../../../background/network/gun/encryption/queryPostKey' +import { decodeArrayBuffer } from '@dimensiondev/kit' export async function appendShareTarget( version: -40 | -39 | -38, postAESKey: string | AESJsonWebKey, @@ -40,7 +41,13 @@ export async function appendShareTarget( Array.from(toKey.values()), ) const gunHint = getNetworkWorkerUninitialized(whoAmI)?.gunNetworkHint - gunHint && Gun2.publishPostAESKeyOnGun2(version, iv, gunHint, othersAESKeyEncrypted) + gunHint && + publishPostAESKey_version39Or38( + version, + new Uint8Array(decodeArrayBuffer(iv)), + gunHint, + othersAESKeyEncrypted, + ) updatePostDB( { identifier: new PostIVIdentifier(whoAmI.network, iv), diff --git a/packages/mask/src/extension/background-script/CryptoServices/debugShowAllPossibleHashForPost.ts b/packages/mask/src/extension/background-script/CryptoServices/debugShowAllPossibleHashForPost.ts deleted file mode 100644 index 93fdb4b2c5c3..000000000000 --- a/packages/mask/src/extension/background-script/CryptoServices/debugShowAllPossibleHashForPost.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { PostIVIdentifier } from '@masknet/shared-base' -import { hashPostSalt, hashCryptoKey, hashCryptoKeyUnstable } from '../../../network/gun/version.2/hash' -import { queryProfilesWithQuery, queryPublicKey } from '../../../database' -import { getNetworkWorkerUninitialized } from '../../../social-network/worker' - -export async function debugShowAllPossibleHashForPost(post: PostIVIdentifier, payloadVersion: -38 | -39 | -40) { - const friends = await queryProfilesWithQuery({ network: post.network }) - const gunHint = getNetworkWorkerUninitialized(post.network)?.gunNetworkHint - return Promise.all( - friends - .filter((x) => x.linkedPersona) - .map( - async (x) => - [ - x.identifier.toText(), - (await hashPostSalt(post.postIV, gunHint ?? '')) + - '-' + - (await (payloadVersion <= -39 ? hashCryptoKeyUnstable : hashCryptoKey)( - (await queryPublicKey(x.identifier))!, - )), - x.linkedPersona?.fingerprint!, - ] as [identifier: string, postHash: string, fingerPrint: string], - ), - ) -} diff --git a/packages/mask/src/extension/background-script/CryptoServices/decryptFrom.ts b/packages/mask/src/extension/background-script/CryptoServices/decryptFrom.ts deleted file mode 100644 index 28530d8abbb3..000000000000 --- a/packages/mask/src/extension/background-script/CryptoServices/decryptFrom.ts +++ /dev/null @@ -1,422 +0,0 @@ -import * as Alpha40 from '../../../crypto/crypto-alpha-40' -import * as Alpha39 from '../../../crypto/crypto-alpha-39' -import { GunAPI as Gun2, GunAPISubscribe as Gun2Subscribe, GunWorker, GunAPI } from '../../../network/gun/' -import { decodeText } from '@dimensiondev/kit' -import { deconstructPayload } from '../../../utils/type-transform/Payload' -import { i18n } from '../../../../shared-ui/locales_legacy' -import { queryPersonaRecord, queryLocalKey } from '../../../database' -import { ProfileIdentifier, PostIVIdentifier, delay } from '@masknet/shared-base' -import { PostRecord, queryPostDB, updatePostDB } from '../../../../background/database/post' -import { getNetworkWorker, getNetworkWorkerUninitialized } from '../../../social-network/worker' -import { cryptoProviderTable } from './cryptoProviderTable' -import type { PersonaRecord } from '../../../../background/database/persona/db' -import { verifyOthersProve } from './verifyOthersProve' -import { publicSharedAESKey } from '../../../crypto/crypto-alpha-38' -import { DecryptFailedReason } from '../../../utils/constants' -import { asyncIteratorWithResult, memorizeAsyncGenerator } from '../../../utils/type-transform/asyncIteratorHelpers' -import { steganographyDecodeImageUrl } from '@masknet/encryption' -import type { TypedMessage, AESJsonWebKey, Payload } from '@masknet/shared-base' -import stringify from 'json-stable-stringify' -import type { SharedAESKeyGun2 } from '../../../network/gun/version.2' -import { MaskMessages } from '../../../utils/messages' -import { Err, Ok, Result } from 'ts-results' -import { decodeTextPayloadWorker } from '../../../social-network/utils/text-payload-worker' -import { steganographyDownloadImage } from './utils' - -type Progress = ( - | { progress: 'finding_person_public_key' | 'finding_post_key' | 'init' | 'decode_post' } - | { progress: 'intermediate_success'; data: Success } - | { progress: 'iv_decrypted'; iv: string } - | { progress: 'payload_decrypted'; decryptedPayloadForImage: Payload } -) & { - type: 'progress' - /** if this is true, this progress should not cause UI change. */ - internal: boolean -} -type DebugInfo = { - debug: 'debug_finding_hash' - hash: [string, string] - type: 'debug' -} -type SuccessThrough = 'author_key_not_found' | 'post_key_cached' | 'normal_decrypted' -type Success = { - type: 'success' - iv: string - decryptedPayloadForImage: Payload - content: TypedMessage - through: SuccessThrough[] - internal: boolean -} -type Failure = { - error: string - type: 'error' - internal: boolean -} -export type SuccessDecryption = Success -export type FailureDecryption = Failure -export type DecryptionProgress = Progress -type ReturnOfDecryptPostContentWithProgress = AsyncGenerator - -const successDecryptionCache = new Map() -const makeSuccessResultF = - ( - cacheKey: string, - iv: string, - decryptedPayloadForImage: Payload, - cryptoProvider: typeof cryptoProviderTable[keyof typeof cryptoProviderTable], - ) => - (rawEncryptedContent: string, through: Success['through']): Success => { - const success: Success = { - through, - iv, - decryptedPayloadForImage, - content: cryptoProvider.typedMessageParse(rawEncryptedContent), - type: 'success', - internal: false, - } - successDecryptionCache.set(cacheKey, success) - return success - } - -function makeProgress( - progress: Exclude | Success, - internal = false, -): Progress { - if (typeof progress === 'string') return { type: 'progress', progress, internal } - return { type: 'progress', progress: 'intermediate_success', data: progress, internal } -} -function makeError(error: string | Error, internal = false): Failure { - if (typeof error === 'string') return { type: 'error', error, internal } - return makeError(error.message, internal) -} -/** - * Decrypt message from a user - * @param post post - * @param author Post by - * @param authorNetworkHint When the author is unknown, the decryption (to public) won't die - * @param whoAmI My username - * @param publicShared Is this post public shared - * - * @description - * The decrypt process: - * - * ## Prepare - * a. if unknown payload, throw - * b. if unknown payload version, throw - * - * ## Decrypt for version -38, -39 and -40 - * a. read the cache `cachedPostResult` - * b. find author's public key (See: `findAuthorPublicKey` function) - * 0. if it is in the payload, use the key in the payload. - * 1. if there is cache, return the cache - * 2. if try N times but not finding the key, throw - * c. if there is cache, return the cache - * d. try to decrypt by `author` with `decryptAsAuthor` - * e. try to decrypt by `whoAmI` with `decryptAsAuthor` - * f. if `author` === `whoAmI`, throw - * g. find key for `whoAmI` on Gun - * h. try to decrypt by the key on Gun - * i. return a Promise - * 0. if version === -40, throws - * 1. listen to future new keys on Gun - * 2. try to decrypt with that key - */ -async function* decryptFromPayloadWithProgress_raw( - post: Payload, - author: ProfileIdentifier, - authorNetworkHint: string, - whoAmI: ProfileIdentifier, - discoverURL: string | undefined, -): ReturnOfDecryptPostContentWithProgress { - const cacheKey = stringify(post) - if (successDecryptionCache.has(cacheKey)) return successDecryptionCache.get(cacheKey)! - yield makeProgress('init') - - const authorNetworkWorker = Result.wrap(() => - getNetworkWorkerUninitialized(author.isUnknown ? authorNetworkHint : author.network), - ).andThen((x) => (x ? Ok(x) : Err(new Error('Worker not found')))) - if (authorNetworkWorker.err) return makeError(authorNetworkWorker.val as Error) - - const data = post - const { version } = data - const sharePublic = data.version === -38 ? data.sharedPublic ?? false : false - - if (version === -40 || version === -39 || version === -38) { - const { encryptedText, iv, version } = data - const cryptoProvider = cryptoProviderTable[version] - const makeSuccessResult = makeSuccessResultF(cacheKey, iv, data, cryptoProvider) - const ownersAESKeyEncrypted = data.version === -38 ? data.AESKeyEncrypted : data.ownersAESKeyEncrypted - - yield { type: 'progress', progress: 'payload_decrypted', decryptedPayloadForImage: data, internal: true } - yield { type: 'progress', progress: 'iv_decrypted', iv: iv, internal: true } - // ? Early emit the cache. - const [cachedPostResult, setPostCache] = await decryptFromCache(data, author, discoverURL) - if (cachedPostResult) { - yield makeProgress(makeSuccessResult(cachedPostResult, ['post_key_cached'])) - } - - // ? If the author's key is in the payload, store it. - if (data.version === -38 && data.authorPublicKey && !author.isUnknown) { - await verifyOthersProve({ raw: data.authorPublicKey }, author).catch(console.error) - } - // ? Find author's public key. - let authorPersona!: PersonaRecord - for await (const _ of asyncIteratorWithResult(findAuthorPublicKey(author, !!cachedPostResult))) { - if (author.isUnknown) break - if (!_.done) { - yield _.value - continue - } - const result = _.value - if (result === 'out of chance') - return makeError(i18n.t('service_others_key_not_found', { name: author.userId })) - else if (result === 'use cache') - return makeSuccessResult(cachedPostResult!, ['author_key_not_found', 'post_key_cached']) - else authorPersona = result - } - - // ? Get my public & private key. - const queryWhoAmI = () => queryPersonaRecord(whoAmI) - const mine = await queryWhoAmI().then((x) => x || delay(1000).then(queryWhoAmI)) - if (!mine?.privateKey) return makeError(DecryptFailedReason.MyCryptoKeyNotFound) - - const { publicKey: minePublic, privateKey: minePrivate } = mine - const networkWorker = getNetworkWorkerUninitialized(whoAmI) - try { - // eslint-disable-next-line - if (version === -40) throw '' - const gunNetworkHint = networkWorker!.gunNetworkHint - const { keyHash, postHash } = await ( - await import('../../../network/gun/version.2/hash') - ).calculatePostKeyPartition(version, iv, minePublic, gunNetworkHint) - yield { type: 'debug', debug: 'debug_finding_hash', hash: [postHash, keyHash] } - } catch {} - if (cachedPostResult) return makeSuccessResult(cachedPostResult, ['post_key_cached']) - - let lastError: unknown - /** - * ? try to decrypt as I am the author - * ? then try to decrypt as whoAmI - * ? then try to go through a normal decrypt process - */ - try { - const a = decryptAsAuthor(author) - const b = decryptAsAuthor(whoAmI) - // ! Don't remove the await - return await a.catch(() => b) - } catch (error) { - lastError = error - } - - if (author.equals(whoAmI)) { - // if the decryption process goes here, - // that means it is failed to decrypt by local identities. - // If remove this if block, Mask will search the key - // for the post even that post by myself. - if (lastError instanceof DOMException) return handleDOMException(lastError) - console.error(lastError) - return makeError(i18n.t('service_self_key_decryption_failed')) - } - - yield makeProgress('finding_post_key') - const aesKeyEncrypted: Array = [] - if (version === -40) { - // Deprecated payload - // eslint-disable-next-line import/no-deprecated - const result = await GunAPI.queryVersion1PostAESKey(iv, whoAmI.userId) - if (result === undefined) return makeError(i18n.t('service_not_share_target')) - aesKeyEncrypted.push(result) - } else if (version === -39 || version === -38) { - const keys = await Gun2.queryPostKeysOnGun2(version, iv, minePublic, authorNetworkWorker.val.gunNetworkHint) - aesKeyEncrypted.push(...keys) - } - // If we can decrypt with current info, just do it. - try { - // ! Do not remove the await here. - return await decryptWith(aesKeyEncrypted) - } catch (error) { - if (error instanceof Error && error.message === i18n.t('service_not_share_target')) { - console.debug(error) - // TODO: Replace this error with: - // You do not have the necessary private key to decrypt this message. - // What to do next: You can ask your friend to visit your profile page, so that their Mask extension will detect and add you to recipients. - // ? after the auto-share with friends is done. - yield makeError(error) - } else { - return handleDOMException(error) - } - } - - // Failed, we have to wait for the future info from gun. - if (version === -40) return makeError(i18n.t('service_not_share_target')) - const subscription = Gun2Subscribe.subscribePostKeysOnGun2( - version, - iv, - minePublic, - authorNetworkWorker.val.gunNetworkHint, - ) - GunWorker?.onTerminated(() => subscription.return?.()) - for await (const aes of subscription) { - console.log('New key received, trying', aes) - try { - return await decryptWith(aes) - } catch (error) { - console.debug(error) - } - } - return makeError(i18n.t('service_not_share_target')) - - async function decryptWith( - key: - | Alpha39.PublishedAESKey - | Alpha40.PublishedAESKey - | Array, - ): Promise { - const [contentArrayBuffer, postAESKey] = await cryptoProvider.decryptMessage1ToNByOther({ - version, - AESKeyEncrypted: key, - authorsPublicKeyECDH: authorPersona.publicKey, - encryptedContent: encryptedText, - privateKeyECDH: minePrivate!, - iv, - }) - - // Store the key to speed up next time decrypt - setPostCache(postAESKey) - const content = decodeText(contentArrayBuffer) - return makeSuccessResult(content, ['normal_decrypted']) - } - - async function decryptAsAuthor(authorIdentifier: ProfileIdentifier) { - const localKey = sharePublic ? publicSharedAESKey : await queryLocalKey(authorIdentifier) - if (!localKey) throw new Error(`Local key for identity ${authorIdentifier.toText()} not found`) - const [contentArrayBuffer, postAESKey] = await cryptoProvider.decryptMessage1ToNByMyself({ - version, - encryptedAESKey: ownersAESKeyEncrypted, - encryptedContent: encryptedText, - myLocalKey: localKey, - iv, - }) - // Store the key to speed up next time decrypt - setPostCache(postAESKey) - const content = decodeText(contentArrayBuffer) - return makeSuccessResult(content, ['normal_decrypted']) - } - } - return makeError(i18n.t('service_unknown_payload')) -} - -async function* decryptFromImageUrlWithProgress_raw( - url: string, - author: ProfileIdentifier, - authorNetworkHint: string, - whoAmI: ProfileIdentifier, - discoverURL: string | undefined, -): ReturnOfDecryptPostContentWithProgress { - if (successDecryptionCache.has(url)) return successDecryptionCache.get(url)! - yield makeProgress('decode_post', true) - const post = await steganographyDecodeImageUrl(url, { - pass: author.toText(), - downloadImage: steganographyDownloadImage, - }) - if (!post.startsWith('\u{1F3BC}') && !/https:\/\/.+\..+\/(\?PostData_v\d=)?%20(.+)%40/.test(post)) - return makeError(i18n.t('service_decode_image_payload_failed'), true) - const worker = await Result.wrapAsync(() => getNetworkWorker(author)) - if (worker.err) return makeError(worker.val as Error) - const payload = deconstructPayload(post, await decodeTextPayloadWorker(author)) - if (payload.err) return makeError(payload.val) - return yield* decryptFromText(payload.val, author, authorNetworkHint, whoAmI, discoverURL) -} - -export const decryptFromText = memorizeAsyncGenerator( - decryptFromPayloadWithProgress_raw, - (encrypted, author, _, whoAmI) => - JSON.stringify([encrypted.iv, encrypted.encryptedText, author.toText(), whoAmI.toText()]), - 1000 * 30, -) - -export const decryptFromImageUrl = memorizeAsyncGenerator( - decryptFromImageUrlWithProgress_raw, - (url, author, _, whoAmI) => JSON.stringify([url, author.toText(), whoAmI.toText()]), - 1000 * 30, -) - -function handleDOMException(e: unknown) { - if (e instanceof DOMException) { - return makeError(i18n.t('service_decryption_failed')) - } else throw e -} -async function* findAuthorPublicKey( - by: ProfileIdentifier, - hasCache: boolean, - maxIteration = 10, -): AsyncGenerator { - let author = await queryPersonaRecord(by) - let iterations = 0 - while (!author?.publicKey) { - iterations += 1 - if (iterations < maxIteration) yield makeProgress('finding_person_public_key') - else return 'out of chance' as const - - author = await queryPersonaRecord(by).catch(() => null) - - if (!author?.publicKey) { - if (hasCache) return 'use cache' as const - const abort = new AbortController() - const databasePromise = new Promise((resolve, reject) => { - abort.signal.addEventListener('abort', () => { - undo() - reject() - }) - const undo = MaskMessages.events.profilesChanged.on((data) => { - for (const x of data) { - if (x.reason === 'delete') continue - if (x.of.equals(by)) { - undo() - resolve() - break - } - } - }) - }) - await Promise.race([databasePromise]) - .then(() => abort.abort()) - .catch(() => null) - } - } - if (author?.publicKey) return author - return 'out of chance' -} - -async function decryptFromCache(postPayload: Payload, by: ProfileIdentifier, discoverURL: string | undefined) { - const { encryptedText, iv, version } = postPayload - const cryptoProvider = version === -40 ? Alpha40 : Alpha39 - - const postIdentifier = new PostIVIdentifier(by.network, iv) - const cachedKey = await queryPostDB(postIdentifier) - if (cachedKey && !cachedKey.url && discoverURL) { - await updatePostDB({ identifier: postIdentifier, url: discoverURL }, 'append') - } - const setCache = (postAESKey: AESJsonWebKey) => { - const postUpdate: Partial & Pick = { - identifier: postIdentifier, - postCryptoKey: postAESKey, - postBy: by, - } - if (discoverURL) postUpdate.url = discoverURL - updatePostDB(postUpdate, 'append') - } - if (cachedKey?.postCryptoKey) { - try { - const result = decodeText( - await cryptoProvider.decryptWithAES({ - aesKey: cachedKey.postCryptoKey, - encrypted: encryptedText, - iv: iv, - }), - ) - return [result, setCache] as const - } catch {} - } - return [undefined, setCache] as const -} diff --git a/packages/mask/src/extension/background-script/CryptoServices/encryptTo.ts b/packages/mask/src/extension/background-script/CryptoServices/encryptTo.ts index 61abcfdc4918..2e41d73112c0 100644 --- a/packages/mask/src/extension/background-script/CryptoServices/encryptTo.ts +++ b/packages/mask/src/extension/background-script/CryptoServices/encryptTo.ts @@ -1,23 +1,23 @@ import * as Alpha38 from '../../../crypto/crypto-alpha-38' -import { GunAPI as Gun2 } from '../../../network/gun' -import { encodeArrayBuffer } from '@dimensiondev/kit' -import { constructAlpha38 } from '../../../utils/type-transform/Payload' +import { decodeArrayBuffer, encodeArrayBuffer } from '@dimensiondev/kit' import { queryPrivateKey, queryLocalKey, queryProfile } from '../../../database' -import { - ProfileIdentifier, - PostIVIdentifier, - isTypedMessageText, - TypedMessage, - TypedMessageText, - PayloadLatest, - compressSecp256k1Key, -} from '@masknet/shared-base' +import { ProfileIdentifier, PostIVIdentifier } from '@masknet/shared-base' +import { isTypedMessageText, type TypedMessage, type TypedMessageText } from '@masknet/typed-message/base' import { prepareRecipientDetail } from './prepareRecipientDetail' import { getNetworkWorker } from '../../../social-network/worker' import { createPostDB, PostRecord } from '../../../../background/database/post' import { queryPersonaByProfileDB } from '../../../../background/database/persona/db' import { i18n } from '../../../../shared-ui/locales_legacy' -import { encodeTextPayloadWorker } from '../../../social-network/utils/text-payload-worker' +import { publishPostAESKey_version39Or38 } from '../../../../background/network/gun/encryption/queryPostKey' +import { + PayloadWellFormed, + PublicKeyAlgorithmEnum, + importAsymmetryKeyFromJsonWebKeyOrSPKI, + AESAlgorithmEnum, + importAESFromJWK, + encodePayload, +} from '@masknet/encryption' +import { None, Some } from 'ts-results' type EncryptedText = string type OthersAESKeyEncryptedToken = string @@ -67,26 +67,53 @@ export async function encryptTo( iv: crypto.getRandomValues(new Uint8Array(16)), }) - const payload: PayloadLatest = { - AESKeyEncrypted: encodeArrayBuffer(ownersAESKeyEncrypted), - encryptedText: encodeArrayBuffer(encryptedText), - iv: encodeArrayBuffer(iv), - signature: '', - sharedPublic: publicShared, - version: -38, - authorUserID: whoAmI, - } + let authorPublicKey: PayloadWellFormed.Payload['authorPublicKey'] = None try { const publicKey = (await queryPersonaByProfileDB(whoAmI))?.publicKey - if (publicKey) payload.authorPublicKey = compressSecp256k1Key(publicKey) + if (publicKey) { + authorPublicKey = Some({ + algr: PublicKeyAlgorithmEnum.secp256k1, + key: ( + await importAsymmetryKeyFromJsonWebKeyOrSPKI(publicKey, PublicKeyAlgorithmEnum.secp256k1) + ).unwrap(), + }) + } } catch { // ignore } - payload.signature = '_' + const postCryptoKey = (await importAESFromJWK(postAESKey, AESAlgorithmEnum.A256GCM)).unwrap() + let encryption: PayloadWellFormed.EndToEndEncryption | PayloadWellFormed.PublicEncryption + if (publicShared) { + encryption = { + type: 'public', + iv: new Uint8Array(iv), + AESKey: { + algr: AESAlgorithmEnum.A256GCM, + key: postCryptoKey, + }, + } + } else { + encryption = { + type: 'E2E', + iv: new Uint8Array(iv), + ephemeralPublicKey: new Map(), + ownersAESKeyEncrypted: new Uint8Array(ownersAESKeyEncrypted), + } + } + + const payload: PayloadWellFormed.Payload = { + version: -38, + author: Some(whoAmI), + encryption, + encrypted: new Uint8Array(encryptedText), + authorPublicKey, + // not supported + signature: None, + } const newPostRecord: PostRecord = { - identifier: new PostIVIdentifier(whoAmI.network, payload.iv), + identifier: new PostIVIdentifier(whoAmI.network, encodeArrayBuffer(iv)), postBy: whoAmI, postCryptoKey: postAESKey, recipients: publicShared ? 'everyone' : recipients, @@ -102,7 +129,9 @@ export async function encryptTo( const postAESKeyToken = encodeArrayBuffer(iv) const worker = await getNetworkWorker(whoAmI)! OthersAESKeyEncryptedMap.set(postAESKeyToken, [worker.gunNetworkHint, othersAESKeyEncrypted]) - return [constructAlpha38(payload, await encodeTextPayloadWorker(whoAmI)), postAESKeyToken] + const payloadEncoded = (await encodePayload.NoSign(payload)).unwrap() + if (typeof payloadEncoded !== 'string') throw new TypeError('') + return [payloadEncoded, postAESKeyToken] } /** @@ -115,7 +144,7 @@ export async function publishPostAESKey(iv: string) { if (!info) throw new Error(i18n.t('service_publish_post_aes_key_failed')) if (!info[1].length) return // Use the latest payload version here since we do not accept new post for older version. - return Gun2.publishPostAESKeyOnGun2(-38, iv, ...info) + return publishPostAESKey_version39Or38(-38, new Uint8Array(decodeArrayBuffer(iv)), ...info) } const SUMMARY_MAX_LENGTH = 40 diff --git a/packages/mask/src/extension/background-script/CryptoServices/getPartialSharedListOfPost.ts b/packages/mask/src/extension/background-script/CryptoServices/getPartialSharedListOfPost.ts index c2fe3462ae42..5dfd305d161b 100644 --- a/packages/mask/src/extension/background-script/CryptoServices/getPartialSharedListOfPost.ts +++ b/packages/mask/src/extension/background-script/CryptoServices/getPartialSharedListOfPost.ts @@ -1,9 +1,6 @@ import { Profile, queryProfile } from '../../../database' import { ProfileIdentifier, Identifier, PostIVIdentifier } from '@masknet/shared-base' import { queryPostDB } from '../../../../background/database/post' -import { GunAPI } from '../../../network/gun' -// #endregion -// #region Append Recipients in future /** * Get already shared target of the post * @param postSalt @@ -18,15 +15,6 @@ export async function getPartialSharedListOfPost( if (nameInDB === 'everyone') return [] if (!nameInDB) return [] nameInDB.forEach((_, x) => ids.add(x.toText())) - if (version === -40) { - // eslint-disable-next-line import/no-deprecated - const post = await GunAPI.getVersion1PostByHash(postSalt) - if (!post) return [] - delete post._ - const nameInGun = Object.keys(post) - // ? version 40 is for old facebook only - nameInGun.forEach((x) => ids.add(new ProfileIdentifier('facebook.com', x).toText())) - } return Promise.all( Array.from(ids) .map((x) => Identifier.fromString(x, ProfileIdentifier)) diff --git a/packages/mask/src/extension/background-script/CryptoServices/verifyOthersProve.ts b/packages/mask/src/extension/background-script/CryptoServices/verifyOthersProve.ts deleted file mode 100644 index 47745da75604..000000000000 --- a/packages/mask/src/extension/background-script/CryptoServices/verifyOthersProve.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { type ProfileIdentifier, decompressSecp256k1Key, ECKeyIdentifierFromJsonWebKey } from '@masknet/shared-base' -import { decodePublicKeyWorker } from '../../../social-network/utils/text-payload-worker' -import { createProfileWithPersona, queryPersonaRecord } from '../../../database' - -export async function verifyOthersProve(bio: string | { raw: string }, others: ProfileIdentifier): Promise { - const compressedX = typeof bio === 'string' ? (await decodePublicKeyWorker(others.network))(bio) : [bio.raw] - if (!compressedX) return false - const publicKey = compressedX - .map((x) => { - try { - return decompressSecp256k1Key(x) - } catch { - return null - } - }) - .filter((x) => x)[0] - if (!publicKey) return false - // TODO: use json schema / other ways to verify the JWK - // or - // throw new Error(i18n.t('service_key_parse_failed')) - // if privateKey, we should possibly not recreate it - const hasPrivate = - (await queryPersonaRecord(ECKeyIdentifierFromJsonWebKey(publicKey)))?.privateKey || - (await queryPersonaRecord(others))?.privateKey - if (!hasPrivate) await createProfileWithPersona(others, { connectionConfirmState: 'pending' }, { publicKey }) - // TODO: unhandled case: if the profile is connected but a different key. - return true -} diff --git a/packages/mask/src/extension/background-script/IdentityService.ts b/packages/mask/src/extension/background-script/IdentityService.ts index d68718dd774c..f3ace1762d11 100644 --- a/packages/mask/src/extension/background-script/IdentityService.ts +++ b/packages/mask/src/extension/background-script/IdentityService.ts @@ -2,8 +2,8 @@ import * as bip39 from 'bip39' import { validateMnemonic } from 'bip39' import { decode, encode } from '@msgpack/msgpack' import { blobToArrayBuffer, decodeArrayBuffer, decodeText, encodeArrayBuffer } from '@dimensiondev/kit' +import { createPersonaByJsonWebKey } from '../../../background/database/persona/helper' import { - createPersonaByJsonWebKey, loginPersona, personaRecordToPersona, queryAvatarDataURL, diff --git a/packages/mask/src/extension/background-script/WelcomeService.ts b/packages/mask/src/extension/background-script/WelcomeService.ts index 4ef43878ca32..cdf6e0cc9a00 100644 --- a/packages/mask/src/extension/background-script/WelcomeService.ts +++ b/packages/mask/src/extension/background-script/WelcomeService.ts @@ -1,7 +1,7 @@ import { encodeText } from '@dimensiondev/kit' import { delay, type DashboardRoutes, PopupRoutes } from '@masknet/shared-base' import { recover_ECDH_256k1_KeyPair_ByMnemonicWord } from '../../utils/mnemonic-code' -import { createPersonaByJsonWebKey } from '../../database' +import { createPersonaByJsonWebKey } from '../../../background/database/persona/helper' import { attachProfileDB, LinkedProfileDetails } from '../../../background/database/persona/db' import { deriveLocalKeyFromECDHKey } from '../../utils/mnemonic-code/localKeyGenerate' import type { PersonaIdentifier, ProfileIdentifier, AESJsonWebKey } from '@masknet/shared-base' diff --git a/packages/mask/src/extension/service-generator.ts b/packages/mask/src/extension/service-generator.ts index d49953d0cdd9..8daf0b9125b8 100644 --- a/packages/mask/src/extension/service-generator.ts +++ b/packages/mask/src/extension/service-generator.ts @@ -1 +1 @@ -export { decryptFromText, decryptFromImageUrl } from './background-script/CryptoServices/decryptFrom' +export { decryptionWithSocialNetworkDecoding } from '../../background/services/crypto/decryption' diff --git a/packages/mask/src/network/gun/gun-worker.patch.ts b/packages/mask/src/network/gun/gun-worker.patch.ts deleted file mode 100644 index 008ec6c4cf08..000000000000 --- a/packages/mask/src/network/gun/gun-worker.patch.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Gun need a "window" available -import '../../setup.worker' -// @ts-ignore -globalThis.window = globalThis -export {} diff --git a/packages/mask/src/network/gun/index.ts b/packages/mask/src/network/gun/index.ts deleted file mode 100644 index aa28aa7a4aea..000000000000 --- a/packages/mask/src/network/gun/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { AsyncCall, AsyncCallOptions, AsyncGeneratorCall } from 'async-call-rpc/full' -import { WorkerChannel } from 'async-call-rpc/utils/web/worker' -import { serializer } from '@masknet/shared-base' -import { OnDemandWorker } from '../../../utils-pure' -import type { _AsyncVersionOf, _AsyncGeneratorVersionOf } from 'async-call-rpc/full' - -export let GunWorker: OnDemandWorker | undefined -if (process.env.architecture) { - GunWorker = new OnDemandWorker(new URL('./worker.ts', import.meta.url), { name: 'Gun' }) - // we're in webpack bundle -} -const options: AsyncCallOptions = { - channel: new WorkerChannel(GunWorker), - serializer, -} -export const GunAPI: _AsyncVersionOf = AsyncCall({}, options) -export const GunAPISubscribe: _AsyncGeneratorVersionOf = - AsyncGeneratorCall({}, options) diff --git a/packages/mask/src/network/gun/version.1/index.ts b/packages/mask/src/network/gun/version.1/index.ts deleted file mode 100644 index b2c679f57923..000000000000 --- a/packages/mask/src/network/gun/version.1/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* eslint import/no-deprecated: 0 */ -import Gun from 'gun' -import 'gun/lib/then' -import type { PublishedAESKey } from '../../../crypto/crypto-alpha-40' -import { gun2 } from '../version.2' - -/** - * @deprecated // ! This version will leak post targets ! // - * - * This version should be readonly now. - * - * Use exchange v2 instead! - */ -interface ApplicationStateInGunVersion1 { - maskbook: { - // This section is no longer used but we leave the type here to avoid future collisions - // users: { - // [userID: string]: { - // /** @deprecated if you want to read it, cast it to string */ - // provePostId: never - // } - // } - posts: { - // Post salt - [salt: string]: { - // ! This will leak post targets. (But keys are safe) - [receiversUsername: string]: PublishedAESKey - } - } - } -} - -function typeHelper() { - return new Gun() -} -/** @deprecated */ -export const gun1 = (gun2 as any as ReturnType).get('maskbook') -/** - * @param salt The salt of this post - * @param myUsername My username of this post - * @deprecated Do not use in new code - */ -export async function queryVersion1PostAESKey(salt: string, myUsername: string) { - const result = await gun1 - .get('posts') - .get(salt) - // @ts-expect-error - .get(myUsername).then!() - if (result?.encryptedKey && result.salt) return result - return undefined -} -export async function getVersion1PostByHash(postSalt: string) { - return ( - gun1 - .get('posts') - // @ts-expect-error - .get(postSalt).then!() - ) -} diff --git a/packages/mask/src/network/gun/version.2/gun.patch.ts b/packages/mask/src/network/gun/version.2/gun.patch.ts deleted file mode 100644 index ed339e0711ac..000000000000 --- a/packages/mask/src/network/gun/version.2/gun.patch.ts +++ /dev/null @@ -1,11 +0,0 @@ -import Gun from 'gun' -Object.assign(globalThis, { Gun }) - -// @ts-ignore -if (typeof importScripts !== 'function') { - console.warn('Loading gun in main frame is deprecated. Please load it in a OnDemandWorker') -} - -if (typeof location === 'object' && !location.protocol.includes('extension')) { - console.warn('Loading gun in SNS is deprecated. Please use RPC and run gun in the background.') -} diff --git a/packages/mask/src/network/gun/version.2/gun2.ts b/packages/mask/src/network/gun/version.2/gun2.ts deleted file mode 100644 index 532ed47c9c4d..000000000000 --- a/packages/mask/src/network/gun/version.2/gun2.ts +++ /dev/null @@ -1,28 +0,0 @@ -import Gun from 'gun/gun' -import { gunServers } from '../../gun-servers' - -export type PersonOnGun2 = { - /** @deprecated if you want to use it, cast it to string. */ - // provePostId?: unknown - __notInGunButABrand__DO_NOT_USE_THIS__?: never -} - -export type SharedAESKeyGun2 = { - encryptedKey: string - salt: string -} - -export interface PostOnGun2 { - [cutNBitsFromFront_hash_ReceiversPublicKey: string]: SharedAESKeyGun2[] -} - -export interface ApplicationStateInGunVersion2 { - [sha512_base64_ProfileIdentifier_OR_sha512_base64_PostSalt: string]: PersonOnGun2 | PostOnGun2 -} - -export const gun2 = new Gun({ - peers: gunServers as any, - localStorage: false, - radisk: true, -}) -gun2.opt({ retry: Number.POSITIVE_INFINITY }) diff --git a/packages/mask/src/network/gun/version.2/hash.ts b/packages/mask/src/network/gun/version.2/hash.ts deleted file mode 100644 index 98c2043177c8..000000000000 --- a/packages/mask/src/network/gun/version.2/hash.ts +++ /dev/null @@ -1,62 +0,0 @@ -/** This file should not contain active gun instances. Only static methods on gun is allowed. */ -/** - * @see https://github.com/DimensionDev/Maskbook/wiki/Data-structure-on-Gun-version-2 - */ -import type { EC_Public_JsonWebKey } from '@masknet/shared-base' -import Gun from 'gun' -import 'gun/sea' -import { memoizePromise } from '../../../../utils-pure' - -/** - * @param version current payload version - * @param postIV Post iv - * @param partitionByCryptoKey Public key of the current user (receiver) - * @param networkHint The network specific string - */ -export async function calculatePostKeyPartition( - version: -39 | -38, - postIV: string, - partitionByCryptoKey: EC_Public_JsonWebKey, - networkHint: string, -) { - const postHash = await hashPostSalt(postIV, networkHint) - // In version > -39, we will use stable hash to prevent unstable result for key hashing - const keyHash = await (version <= -39 ? hashCryptoKeyUnstable : hashCryptoKey)(partitionByCryptoKey) - return { postHash, keyHash } -} - -export const hashPostSalt = memoizePromise( - async function (postSalt: string, networkHint: string) { - const hashPair = '9283464d-ee4e-4e8d-a7f3-cf392a88133f' - const N = 2 - - const hash = (await Gun.SEA.work(postSalt, hashPair))! - return networkHint + hash.substring(0, N) - }, - (x, y) => x + y, -) - -/** - * @param key - The key need to be hashed - */ -export const hashCryptoKeyUnstable = memoizePromise(async function (key: EC_Public_JsonWebKey) { - const hashPair = '10198a2f-205f-45a6-9987-3488c80113d0' - const N = 2 - - const jwk = JSON.stringify(key) - const hash = (await Gun.SEA.work(jwk, hashPair))! - return hash.substring(0, N) -}, undefined) - -/** - * @param key - The key need to be hashed - */ -export const hashCryptoKey = memoizePromise(async function (key: EC_Public_JsonWebKey) { - const hashPair = '10198a2f-205f-45a6-9987-3488c80113d0' - const N = 2 - - const jwk = key - if (!jwk.x || !jwk.y) throw new Error('Invalid key') - const hash = (await Gun.SEA.work(jwk.x! + jwk.y!, hashPair))! - return hash.substring(0, N) -}, undefined) diff --git a/packages/mask/src/network/gun/version.2/index.ts b/packages/mask/src/network/gun/version.2/index.ts deleted file mode 100644 index 1d0f584f809b..000000000000 --- a/packages/mask/src/network/gun/version.2/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import './gun.patch' -import 'gun/sea' -import 'gun/lib/radix' -import 'gun/lib/radisk' -import 'gun/lib/store' -import 'gun/lib/rindexed' - -export * from './post' -export * from './gun2' diff --git a/packages/mask/src/network/gun/version.2/post.ts b/packages/mask/src/network/gun/version.2/post.ts deleted file mode 100644 index 2fbcaa1beb20..000000000000 --- a/packages/mask/src/network/gun/version.2/post.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { gun2, SharedAESKeyGun2 } from './gun2' -import { hashPostSalt, hashCryptoKey, hashCryptoKeyUnstable, calculatePostKeyPartition } from './hash' -import type { PublishedAESKeyRecordV39OrV38 } from '../../../crypto/crypto-alpha-38' -import type { EC_Public_JsonWebKey } from '@masknet/shared-base' -import { EventIterator } from 'event-iterator' - -/** - * Query all possible keys stored on the gun - * @param version current payload version - * @param postIV Post iv - * @param partitionByCryptoKey Public key of the current user (receiver) - */ -export async function queryPostKeysOnGun2( - version: -39 | -38, - postIV: string, - partitionByCryptoKey: EC_Public_JsonWebKey, - networkHint: string, -): Promise { - const { postHash, keyHash } = await calculatePostKeyPartition(version, postIV, partitionByCryptoKey, networkHint) - - // ? here we get the internal node names of gun2[postHash][keyHash] - // ? where gun2[postHash][keyHash] is a list - const internalNodes: Record = - (await gun2 - .get(postHash) - // @ts-ignore - .get(keyHash).then!()) || {} - /* cspell:disable-next-line */ - // ? In this step we get something like ["jzarhbyjtexiE7aB1DvQ", "jzarhuse6xlTAtblKRx9"] - const internalKeys = Object.keys(internalNodes).filter((x) => x !== '_') - // ? In this step we get all keys in this category (gun2[postHash][keyHash]) - const resultPromise = internalKeys.map((key) => - gun2 - // @ts-expect-error - .get(key).then!(), - ) - const result = (await Promise.all(resultPromise)) as SharedAESKeyGun2[] - console.info(`await gun2[${postHash}][${keyHash}]\n`, result) - return result -} - -/** - * Listen on the changes of all possible keys on the gun - * @param version current payload version - * @param postSalt Post iv - * @param partitionByCryptoKey Public key of the current user (receiver) - */ -export async function* subscribePostKeysOnGun2( - version: -39 | -38, - postSalt: string, - partitionByCryptoKey: EC_Public_JsonWebKey, - networkHint: string, -) { - const iter = new EventIterator(({ push: callback }) => { - hashPostSalt(postSalt, networkHint).then((postHash) => { - // In version > -39, we will use stable hash to prevent unstable result for key hashing - ;(version <= -39 ? hashCryptoKeyUnstable : hashCryptoKey)(partitionByCryptoKey).then((keyHash) => { - gun2.get(postHash) - // @ts-ignore - .get(keyHash) - .map() - // @ts-ignore - .on((data: SharedAESKeyGun2) => { - // @ts-ignore - const { _, ...data2 } = Object.assign({}, data) - callback(data2) - }) - }) - }) - }) - yield* iter -} - -/** - * Publish post keys on the gun - * @param version current payload - * @param postSalt Post iv - * @param receiversKeys Keys needs to publish - */ -export async function publishPostAESKeyOnGun2( - version: -39 | -38, - postSalt: string, - networkHint: string, - receiversKeys: PublishedAESKeyRecordV39OrV38[], -) { - const postHash = await hashPostSalt(postSalt, networkHint) - // Store AES key to gun - receiversKeys.forEach(async ({ aesKey, receiverKey }) => { - const keyHash = await (version <= -39 ? hashCryptoKeyUnstable : hashCryptoKey)(receiverKey) - console.log(`gun[${postHash}][${keyHash}].push(`, aesKey, ')') - gun2.get(postHash) - // @ts-ignore - .get(keyHash) - // @ts-ignore - .set(aesKey) - }) -} diff --git a/packages/mask/src/network/gun/worker-implementation-subscribe.ts b/packages/mask/src/network/gun/worker-implementation-subscribe.ts deleted file mode 100644 index e9d7cf1b21e3..000000000000 --- a/packages/mask/src/network/gun/worker-implementation-subscribe.ts +++ /dev/null @@ -1 +0,0 @@ -export { subscribePostKeysOnGun2 } from './version.2/post' diff --git a/packages/mask/src/network/gun/worker-implementation.ts b/packages/mask/src/network/gun/worker-implementation.ts deleted file mode 100644 index 3f8ff74076c4..000000000000 --- a/packages/mask/src/network/gun/worker-implementation.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { queryVersion1PostAESKey, getVersion1PostByHash } from './version.1' -export { publishPostAESKeyOnGun2, queryPostKeysOnGun2 } from './version.2' diff --git a/packages/mask/src/network/gun/worker.ts b/packages/mask/src/network/gun/worker.ts deleted file mode 100644 index a59bff8ee9fc..000000000000 --- a/packages/mask/src/network/gun/worker.ts +++ /dev/null @@ -1,13 +0,0 @@ -import './gun-worker.patch' -import { AsyncGeneratorCall, AsyncCall, AsyncCallOptions } from 'async-call-rpc/full' -import { WorkerChannel } from 'async-call-rpc/utils/web/worker' -import { serializer } from '@masknet/shared-base' -import * as Impl from './worker-implementation' -import * as Impl2 from './worker-implementation-subscribe' -const options: AsyncCallOptions = { - channel: new WorkerChannel(), - strict: { methodNotFound: false }, - serializer, -} -AsyncCall(Impl, options) -AsyncGeneratorCall(Impl2, options) diff --git a/packages/mask/src/plugins/Avatar/Services/bind.ts b/packages/mask/src/plugins/Avatar/Services/bind.ts index 13c78f53e04a..7a3a07895137 100644 --- a/packages/mask/src/plugins/Avatar/Services/bind.ts +++ b/packages/mask/src/plugins/Avatar/Services/bind.ts @@ -3,10 +3,9 @@ import { NetworkPluginID } from '@masknet/plugin-infra' import addSeconds from 'date-fns/addSeconds' import { KeyValue } from '@masknet/web3-providers' import { NFT_AVATAR_DB_NAME, NFT_AVATAR_DB_NAME_STORAGE } from '../constants' -import { gun2 } from '../../../network/gun/version.2' +import { getGunData } from '@masknet/gun-utils' import { delay } from '@masknet/shared-base' -const NFTAvatarGUN = gun2.get(NFT_AVATAR_DB_NAME) const READ_GUN_RETRIES = 10 const NFTAvatarDB = (network: string) => KeyValue.createJSON_Storage(NFT_AVATAR_DB_NAME + '_' + network) @@ -15,12 +14,9 @@ const NFTAvatarDBStorage = (network: string) => KeyValue.createJSON_Storage(NFT_ const cache = new Map, number]>() async function getUserAddressFromGUN(userId: string): Promise { - // eslint-disable-next-line no-plusplus - for (let i = 0; i < READ_GUN_RETRIES; i++) { - const result = await NFTAvatarGUN - // @ts-expect-error - .get(userId).then!() - if (result) return result + for (let i = 0; i < READ_GUN_RETRIES; i += 1) { + const result = await getGunData(NFT_AVATAR_DB_NAME, userId) + if (typeof result === 'string') return result await delay(500) } return diff --git a/packages/mask/src/plugins/Collectible/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Collectible/SNSAdaptor/index.tsx index be67a0935d55..146412b195de 100644 --- a/packages/mask/src/plugins/Collectible/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Collectible/SNSAdaptor/index.tsx @@ -6,9 +6,9 @@ import { base } from '../base' import type { CollectibleJSON_Payload } from '../types' import { checkUrl, getAssetInfoFromURL, getRelevantUrl } from '../utils' import { PLUGIN_NAME, PLUGIN_ID } from '../constants' -import { getTypedMessageContent } from '../../../protocols/typed-message' import { NFTPage } from './NFTPage' import { AddressName, AddressNameType } from '@masknet/web3-shared-evm' +import { extractTextFromTypedMessage } from '@masknet/typed-message/base' const sns: Plugin.SNSAdaptor.Definition = { ...base, @@ -21,7 +21,7 @@ const sns: Plugin.SNSAdaptor.Definition = { return asset ? renderPostInspector(asset) : null }, DecryptedInspector: function Component(props) { - const collectibleUrl = getRelevantUrl(getTypedMessageContent(props.message)) + const collectibleUrl = getRelevantUrl(extractTextFromTypedMessage(props.message).unwrapOr('')) const asset = getAssetInfoFromURL(collectibleUrl) return asset ? renderPostInspector(asset) : null }, diff --git a/packages/mask/src/plugins/Collectible/helpers.ts b/packages/mask/src/plugins/Collectible/helpers.ts index 45bb0d869b7f..bd65ce115285 100644 --- a/packages/mask/src/plugins/Collectible/helpers.ts +++ b/packages/mask/src/plugins/Collectible/helpers.ts @@ -1,5 +1,5 @@ import type { Asset, WyvernSchemaName } from 'opensea-js/lib/types' -import { createRenderWithMetadata, createTypedMessageMetadataReader } from '@masknet/shared-base' +import { createRenderWithMetadata, createTypedMessageMetadataReader } from '@masknet/typed-message/base' import { PLUGIN_META_KEY } from './constants' import type { CollectibleJSON_Payload, CollectibleToken } from './types' import schema from './schema.json' diff --git a/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/index.tsx b/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/index.tsx index cdf689f9f321..584187643f03 100644 --- a/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/CryptoartAI/SNSAdaptor/index.tsx @@ -6,7 +6,7 @@ import { base } from '../base' import { checkUrl, getAssetInfoFromURL, getRelevantUrl } from '../utils' import { PLUGIN_NAME } from '../constants' import type { PayloadType } from '../types' -import { getTypedMessageContent } from '../../../protocols/typed-message' +import { extractTextFromTypedMessage } from '@masknet/typed-message/base' const sns: Plugin.SNSAdaptor.Definition = { ...base, @@ -20,7 +20,7 @@ const sns: Plugin.SNSAdaptor.Definition = { return asset ? renderPostInspector(asset) : null }, DecryptedInspector: function Component(props) { - const collectibleUrl = getRelevantUrl(getTypedMessageContent(props.message)) + const collectibleUrl = getRelevantUrl(extractTextFromTypedMessage(props.message).unwrapOr('')) const asset = getAssetInfoFromURL(collectibleUrl) return asset ? renderPostInspector(asset) : null }, diff --git a/packages/mask/src/plugins/External/SNSAdaptor/index.tsx b/packages/mask/src/plugins/External/SNSAdaptor/index.tsx index ddc825389186..a99b63cdaf91 100644 --- a/packages/mask/src/plugins/External/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/External/SNSAdaptor/index.tsx @@ -7,7 +7,7 @@ import { ThirdPartyPluginCompositionEntry } from '../components/CompositionEntry import { ExternalPluginMessages } from '../messages' import { isLocalContext } from '../sns-context' import { MaskMessages } from '../../../utils' -import { makeTypedMessageText } from '@masknet/shared-base' +import { makeTypedMessageText } from '@masknet/typed-message/base' const sns: Plugin.SNSAdaptor.Definition = { ...base, diff --git a/packages/mask/src/plugins/External/messages.ts b/packages/mask/src/plugins/External/messages.ts index 650bc6c25a79..661678cd0404 100644 --- a/packages/mask/src/plugins/External/messages.ts +++ b/packages/mask/src/plugins/External/messages.ts @@ -1,5 +1,6 @@ import { createPluginMessage } from '@masknet/plugin-infra' -import { TypedMessage, serializer } from '@masknet/shared-base' +import type { TypedMessage } from '@masknet/typed-message/base' +import { serializer } from '@masknet/shared-base' import type { MaskSDK_SNS_ContextIdentifier } from './sns-context' // Make TS happy diff --git a/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx b/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx index 9b918545dc64..a6ec83d3fe8d 100644 --- a/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/FindTruman/SNSAdaptor/index.tsx @@ -5,7 +5,8 @@ import { Skeleton } from '@mui/material' import { makeStyles } from '@masknet/theme' import MaskPluginWrapper from '../../MaskPluginWrapper' import { usePostInfoDetails } from '@masknet/plugin-infra' -import { extractTextFromTypedMessage, parseURL } from '@masknet/shared-base' +import { parseURL } from '@masknet/shared-base' +import { extractTextFromTypedMessage } from '@masknet/typed-message/base' import { PostInspector } from './PostInspector' const useStyles = makeStyles()((theme) => { diff --git a/packages/mask/src/plugins/Furucombo/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Furucombo/SNSAdaptor/index.tsx index a927b6dbe652..41d99e732364 100644 --- a/packages/mask/src/plugins/Furucombo/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Furucombo/SNSAdaptor/index.tsx @@ -2,7 +2,8 @@ import { Suspense, useMemo } from 'react' import { Plugin, usePostInfoDetails } from '@masknet/plugin-infra' import { SnackbarContent } from '@mui/material' import { base } from '../base' -import { extractTextFromTypedMessage, parseURL } from '@masknet/shared-base' +import { parseURL } from '@masknet/shared-base' +import { extractTextFromTypedMessage } from '@masknet/typed-message/base' import MaskPluginWrapper from '../../MaskPluginWrapper' import { FurucomboView } from '../UI/FurucomboView' import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' diff --git a/packages/mask/src/plugins/Gitcoin/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Gitcoin/SNSAdaptor/index.tsx index 9d21abb9cc52..f96c7c0b5b3c 100644 --- a/packages/mask/src/plugins/Gitcoin/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Gitcoin/SNSAdaptor/index.tsx @@ -3,7 +3,8 @@ import { ChainId } from '@masknet/web3-shared-evm' import { NetworkPluginID, Plugin, useChainId } from '@masknet/plugin-infra' import { SnackbarContent } from '@mui/material' import MaskPluginWrapper from '../../MaskPluginWrapper' -import { extractTextFromTypedMessage, parseURL } from '@masknet/shared-base' +import { extractTextFromTypedMessage } from '@masknet/typed-message/base' +import { parseURL } from '@masknet/shared-base' import { usePostInfoDetails } from '../../../components/DataSource/usePostInfo' import { PreviewCard } from './PreviewCard' import { base } from '../base' diff --git a/packages/mask/src/plugins/GoodGhosting/SNSAdaptor/index.tsx b/packages/mask/src/plugins/GoodGhosting/SNSAdaptor/index.tsx index 64be79561831..f9544f915fae 100644 --- a/packages/mask/src/plugins/GoodGhosting/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/GoodGhosting/SNSAdaptor/index.tsx @@ -2,7 +2,8 @@ import { Suspense, useMemo } from 'react' import type { Plugin } from '@masknet/plugin-infra' import { SnackbarContent } from '@mui/material' import MaskPluginWrapper from '../../MaskPluginWrapper' -import { extractTextFromTypedMessage, parseURL } from '@masknet/shared-base' +import { extractTextFromTypedMessage } from '@masknet/typed-message/base' +import { parseURL } from '@masknet/shared-base' import { usePostInfoDetails } from '../../../components/DataSource/usePostInfo' import { PreviewCard } from '../UI/PreviewCard' import { ChainId } from '@masknet/web3-shared-evm' diff --git a/packages/mask/src/plugins/ITO/SNSAdaptor/helpers.ts b/packages/mask/src/plugins/ITO/SNSAdaptor/helpers.ts index 172c80e7bfb2..b2accbde72a5 100644 --- a/packages/mask/src/plugins/ITO/SNSAdaptor/helpers.ts +++ b/packages/mask/src/plugins/ITO/SNSAdaptor/helpers.ts @@ -2,7 +2,11 @@ import { omit } from 'lodash-unified' import type BigNumber from 'bignumber.js' import type { Result } from 'ts-results' import { ChainId, isNativeTokenAddress } from '@masknet/web3-shared-evm' -import { createRenderWithMetadata, createTypedMessageMetadataReader, type TypedMessage } from '@masknet/shared-base' +import { + createRenderWithMetadata, + createTypedMessageMetadataReader, + type TypedMessage, +} from '@masknet/typed-message/base' import { ITO_MetaKey_1, ITO_MetaKey_2 } from '../constants' import type { JSON_PayloadInMask, JSON_PayloadOutMask } from '../types' import schemaV1 from '../schema-v1.json' diff --git a/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx b/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx index e1d10b384dbd..c944d7bc07ae 100644 --- a/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx @@ -2,7 +2,8 @@ import { Suspense, useMemo } from 'react' import { Plugin, usePostInfoDetails } from '@masknet/plugin-infra' import { SnackbarContent } from '@mui/material' import { base } from '../base' -import { extractTextFromTypedMessage, parseURL } from '@masknet/shared-base' +import { extractTextFromTypedMessage } from '@masknet/typed-message/base' +import { parseURL } from '@masknet/shared-base' import { EthereumChainBoundary } from '../../../web3/UI/EthereumChainBoundary' import { PreviewCard } from './components/PreviewCard' import MaskPluginWrapper from '../../MaskPluginWrapper' diff --git a/packages/mask/src/plugins/Pets/SNSAdaptor/PetDialog.tsx b/packages/mask/src/plugins/Pets/SNSAdaptor/PetDialog.tsx index 659d3b629886..5d2724a3a6f3 100644 --- a/packages/mask/src/plugins/Pets/SNSAdaptor/PetDialog.tsx +++ b/packages/mask/src/plugins/Pets/SNSAdaptor/PetDialog.tsx @@ -12,7 +12,7 @@ import { PreviewBox } from './PreviewBox' import { PetMetaDB, FilterContract, OwnerERC721TokenInfo, ImageType } from '../types' import { useUser, useNFTs, useNFTsExtra } from '../hooks' import { useI18N } from '../../../utils' -import { ShadowRootPopper } from '../../../utils/shadow-root/ShadowRootComponents' +import { ShadowRootPopper } from '../../../../shared-ui/shadow-root/ShadowRootComponents' import { ImageLoader } from './ImageLoader' import type { Constant } from '@masknet/web3-shared-evm/constants/utils' diff --git a/packages/mask/src/plugins/Polls/SNSAdaptor/PollsInPost.tsx b/packages/mask/src/plugins/Polls/SNSAdaptor/PollsInPost.tsx index 635998a92bf2..1400b41aabd8 100644 --- a/packages/mask/src/plugins/Polls/SNSAdaptor/PollsInPost.tsx +++ b/packages/mask/src/plugins/Polls/SNSAdaptor/PollsInPost.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' import MaskPluginWrapper from '../../MaskPluginWrapper' -import type { TypedMessage } from '@masknet/shared-base' +import type { TypedMessage } from '@masknet/typed-message/base' import { PluginPollRPC } from '../messages' import { renderWithPollMetadata, PollMetadataReader } from '../helpers' import type { PollGunDB } from '../Services' diff --git a/packages/mask/src/plugins/Polls/Services.ts b/packages/mask/src/plugins/Polls/Services.ts index f1b746476e6b..836a9f9775b0 100644 --- a/packages/mask/src/plugins/Polls/Services.ts +++ b/packages/mask/src/plugins/Polls/Services.ts @@ -1,8 +1,8 @@ import { first } from 'lodash-unified' import '../../network/gun/gun-worker.patch' -import { gun2 } from '../../network/gun/version.2' +import { setGunData, getGunData } from '@masknet/gun-utils' import type { PollMetaData } from './types' -import { PollGunServer } from './constants' +import { PollGunRootNode } from './constants' import { WorkerChannel } from 'async-call-rpc/utils/web/worker' import { AsyncCall } from 'async-call-rpc' @@ -11,8 +11,6 @@ setTimeout(() => { AsyncCall(self, { channel: new WorkerChannel() }) }, 0) -const PollGun = gun2.get(PollGunServer) - const defaultPoll: PollGunDB = { key: '', sender: '', @@ -47,18 +45,25 @@ export async function createNewPoll(poll: NewPollProps) { end_time: end_time.getTime(), } - // @ts-ignore - const key = `${id}_${Gun.time.is()}_${Gun.text.random(4)}` - - await PollGun - // @ts-ignore - .get(key) - // @ts-ignore - .put(poll_item).then!() + const key = `${id}_${+new Date().getTime()}_${GunTextRandom(4)}` + setGunData([PollGunRootNode, key], poll_item) return poll } +/** Implementation of deprecated Gun.text.random */ +function GunTextRandom(l: number) { + let s = '' + l = l || 24 // you are not going to make a 0 length random number, so no need to check type + /* cspell:disable-next-line */ + const c = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXZabcdefghijklmnopqrstuvwxyz' + while (l > 0) { + s += c.charAt(Math.floor(Math.random() * c.length)) + l -= 1 + } + return s +} + export type PollGunDB = PollMetaData interface voteProps { @@ -68,30 +73,19 @@ interface voteProps { export async function vote(props: voteProps) { const { poll, index } = props - let results = [0, 0] - PollGun - // @ts-ignore - .get(poll.key) - // @ts-ignore - .get('results') - .on((item) => { - // @ts-ignore - delete item._ - results = Object.values(item) - }) + const data = await getGunData(PollGunRootNode, poll.key, 'results') + if (typeof data === 'object') delete data._ + else throw new TypeError('Invalid vote node.') + + const results = Object.values(data) + if (!results.every((x): x is number => typeof x === 'number')) throw new TypeError('Invalid vote node.') const count = results[index] + 1 const newResults = { ...results, [index]: count, } - PollGun - // @ts-ignore - .get(poll.key) - // @ts-ignore - .get('results') - // @ts-ignore - .put(newResults) + setGunData([PollGunRootNode, poll.key, 'results'], newResults) return { ...poll, @@ -101,59 +95,51 @@ export async function vote(props: voteProps) { export async function getPollByKey(props: { key: string }) { const keys = props.key.split('_') - let poll: PollGunDB = { + + const node = await getGunData(PollGunRootNode, props.key) + if (typeof node !== 'object' || !isPollGunDB(node)) throw new TypeError('Invalid vote node.') + const data = node + const poll: PollGunDB = { ...defaultPoll, - key: props.key, id: first(keys), + key: props.key, + sender: data.sender, + question: data.question, + start_time: data.start_time, + end_time: data.end_time, + } + if (data.options) { + const options = await getGunData(PollGunRootNode, props.key, 'options') + if (typeof options === 'object') { + delete options._ + data.options = Object.values(options) as any + } + } + if (data.results) { + const results = await getGunData(PollGunRootNode, props.key, 'results') + if (typeof results === 'object') { + delete results._ + data.results = Object.values(results) as any + } } - - PollGun - // @ts-ignore - .get(props.key) - // @ts-ignore - .on((data: PollGunDB) => { - poll = { - ...poll, - sender: data.sender, - question: data.question, - start_time: data.start_time, - end_time: data.end_time, - } - if (data.options) { - PollGun - // @ts-ignore - .get(props.key) - // @ts-ignore - .get('options') - .on((options) => { - // @ts-ignore - delete options._ - poll.options = Object.values(options) - }) - } - if (data.results) { - PollGun - // @ts-ignore - .get(props.key) - // @ts-ignore - .get('results') - .on((results) => { - // @ts-ignore - delete results._ - poll.results = Object.values(results) - }) - } - }) return poll } +function isPollGunDB(x: object): x is PollGunDB { + const { end_time } = x as PollGunDB + if (typeof end_time !== 'number') return false + return true +} + export async function getAllExistingPolls() { const polls: PollGunDB[] = [] - PollGun.map().on(async (data, key) => { - const poll = await getPollByKey({ key }) - polls.push(poll) - }) - + const allNodes = await getGunData(PollGunRootNode) + if (typeof allNodes !== 'object') return [] + await Promise.allSettled( + Object.keys(allNodes).map(async (key) => { + polls.push(await getPollByKey({ key })) + }), + ) return polls } diff --git a/packages/mask/src/plugins/Polls/constants.ts b/packages/mask/src/plugins/Polls/constants.ts index 89eba2685dbf..68dd37b504bd 100644 --- a/packages/mask/src/plugins/Polls/constants.ts +++ b/packages/mask/src/plugins/Polls/constants.ts @@ -1,6 +1,6 @@ import { PluginId } from '@masknet/plugin-infra' -export const PollGunServer = 'com.maskbook.plugin.polls' +export const PollGunRootNode = 'com.maskbook.plugin.polls' export const PLUGIN_META_KEY = `${PluginId.Poll}:1` export const PLUGIN_ID = PluginId.Poll diff --git a/packages/mask/src/plugins/Polls/helpers.ts b/packages/mask/src/plugins/Polls/helpers.ts index 9a2e2d4c98d2..c3f2b390f0f6 100644 --- a/packages/mask/src/plugins/Polls/helpers.ts +++ b/packages/mask/src/plugins/Polls/helpers.ts @@ -1,4 +1,4 @@ -import { createTypedMessageMetadataReader, createRenderWithMetadata } from '@masknet/shared-base' +import { createTypedMessageMetadataReader, createRenderWithMetadata } from '@masknet/typed-message/base' import type { PollMetaData } from './types' import { PLUGIN_META_KEY } from './constants' import schema from './schema.json' diff --git a/packages/mask/src/plugins/PoolTogether/SNSAdaptor/index.tsx b/packages/mask/src/plugins/PoolTogether/SNSAdaptor/index.tsx index 3afd64bb8b58..b56ffc11b061 100644 --- a/packages/mask/src/plugins/PoolTogether/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/PoolTogether/SNSAdaptor/index.tsx @@ -1,6 +1,7 @@ import { Suspense, useMemo } from 'react' import { Plugin, usePostInfoDetails } from '@masknet/plugin-infra' -import { extractTextFromTypedMessage, parseURL } from '@masknet/shared-base' +import { extractTextFromTypedMessage } from '@masknet/typed-message/base' +import { parseURL } from '@masknet/shared-base' import { ChainId } from '@masknet/web3-shared-evm' import { SnackbarContent } from '@mui/material' import { base } from '../base' diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/helpers.ts b/packages/mask/src/plugins/RedPacket/SNSAdaptor/helpers.ts index 1bb748a2330c..861d3ca59f01 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/helpers.ts +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/helpers.ts @@ -1,4 +1,4 @@ -import { createRenderWithMetadata, createTypedMessageMetadataReader } from '@masknet/shared-base' +import { createRenderWithMetadata, createTypedMessageMetadataReader } from '@masknet/typed-message/base' import { RedPacketMetaKey, RedPacketNftMetaKey } from '../constants' import type { RedPacketJSONPayload, RedPacketNftJSONPayload } from '../types' import schema from '../schema.json' diff --git a/packages/mask/src/plugins/Snapshot/SNSAdaptor/index.tsx b/packages/mask/src/plugins/Snapshot/SNSAdaptor/index.tsx index 0324b7d1d693..dd4c26351ca3 100644 --- a/packages/mask/src/plugins/Snapshot/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/Snapshot/SNSAdaptor/index.tsx @@ -6,7 +6,8 @@ import { makeStyles } from '@masknet/theme' import MaskPluginWrapper from '../../MaskPluginWrapper' import { PostInspector } from './PostInspector' import { usePostInfoDetails } from '../../../components/DataSource/usePostInfo' -import { extractTextFromTypedMessage, parseURL } from '@masknet/shared-base' +import { extractTextFromTypedMessage } from '@masknet/typed-message/base' +import { parseURL } from '@masknet/shared-base' const useStyles = makeStyles()((theme) => { return { diff --git a/packages/mask/src/plugins/Trader/SNSAdaptor/trending/CoinMenu.tsx b/packages/mask/src/plugins/Trader/SNSAdaptor/trending/CoinMenu.tsx index 93386557cabf..4fc0664fcc40 100644 --- a/packages/mask/src/plugins/Trader/SNSAdaptor/trending/CoinMenu.tsx +++ b/packages/mask/src/plugins/Trader/SNSAdaptor/trending/CoinMenu.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' import { Typography, MenuItem } from '@mui/material' import { makeStyles } from '@masknet/theme' -import { ShadowRootMenu } from '../../../../utils/shadow-root/ShadowRootComponents' +import { ShadowRootMenu } from '../../../../../shared-ui/shadow-root/ShadowRootComponents' import type { Coin } from '../../types' const useStyles = makeStyles()((theme) => ({ diff --git a/packages/mask/src/plugins/Trader/base-deferred.ts b/packages/mask/src/plugins/Trader/base-deferred.ts index c7e987101372..b2fece99db5b 100644 --- a/packages/mask/src/plugins/Trader/base-deferred.ts +++ b/packages/mask/src/plugins/Trader/base-deferred.ts @@ -1,12 +1,12 @@ import type { Plugin } from '@masknet/plugin-infra' -import type { TypedMessage, TypedMessageTuple } from '@masknet/shared-base' +import { visitEachTypedMessageChild } from '@masknet/typed-message/base' import { isCashTagMessage, makeTypedMessageCashTrending } from './messages/TypedMessageCashTrending' export const baseDeferred: Plugin.Shared.Utilities = { - typedMessageTransformer(message) { - return { - ...message, - items: message.items.map((m: TypedMessage) => (isCashTagMessage(m) ? makeTypedMessageCashTrending(m) : m)), - } as TypedMessageTuple + typedMessageTransformer: function visitor(message, context) { + if (isCashTagMessage(message)) { + return makeTypedMessageCashTrending(message) + } + return visitEachTypedMessageChild(message, visitor, context) }, } diff --git a/packages/mask/src/plugins/Trader/messages/TypedMessageCashTrending.tsx b/packages/mask/src/plugins/Trader/messages/TypedMessageCashTrending.tsx index f3fdff25fda2..6137bca8b59d 100644 --- a/packages/mask/src/plugins/Trader/messages/TypedMessageCashTrending.tsx +++ b/packages/mask/src/plugins/Trader/messages/TypedMessageCashTrending.tsx @@ -1,11 +1,11 @@ import { useState } from 'react' import { useChainId } from '@masknet/web3-shared-evm' import { Link, Typography } from '@mui/material' -import { TypedMessageAnchor, TypedMessage, isTypedMessageAnchor } from '@masknet/shared-base' -import type { TypedMessageRendererProps } from '../../../components/InjectedComponents/TypedMessageRenderer' +import { TypedMessageAnchor, TypedMessage, isTypedMessageAnchor } from '@masknet/typed-message/base' import { PluginTraderMessages, PluginTraderRPC } from '../messages' import { TagType } from '../types' -import { registerTypedMessageRenderer } from '../../../protocols/typed-message' +// TODO: when migrate, should have an API in the plugin infra for plugin to define render +import { TypedMessageRenderRegistry } from '../../../../shared-ui/TypedMessageRender/registry' export interface TypedMessageCashTrending extends Omit { readonly type: 'x-cash-trending' @@ -22,13 +22,13 @@ export function makeTypedMessageCashTrending(message: TypedMessageAnchor) { } as TypedMessageCashTrending } -registerTypedMessageRenderer('x-cash-trending', { - component: DefaultTypedMessageCashTrendingRenderer, - id: 'com.maskbook.trader.x-cash-trending', +TypedMessageRenderRegistry.registerTypedMessageRender('x-cash-trending', { + component: CashTrendingRenderer, + id: Symbol('com.maskbook.trader.x-cash-trending'), priority: 0, }) -function DefaultTypedMessageCashTrendingRenderer(props: TypedMessageRendererProps) { +function CashTrendingRenderer(props: TypedMessageCashTrending) { const chainId = useChainId() const [openTimer, setOpenTimer] = useState | null>(null) const onMouseOver = (ev: React.MouseEvent) => { @@ -37,11 +37,10 @@ function DefaultTypedMessageCashTrendingRenderer(props: TypedMessageRendererProp if (openTimer !== null) clearTimeout(openTimer) setOpenTimer( setTimeout(async () => { - if (props.message.category !== 'cash' && props.message.category !== 'hash') return - const { name, category } = props.message + if (props.category !== 'cash' && props.category !== 'hash') return + const { name, category } = props const type = category === 'cash' ? TagType.CASH : TagType.HASH const dataProviders = await PluginTraderRPC.getAvailableDataProviders(type, name) - const tradeProviders = await PluginTraderRPC.getAvailableTraderProviders(chainId) if (!dataProviders.length) return PluginTraderMessages.cashTagObserved.sendToLocal({ name, @@ -60,8 +59,8 @@ function DefaultTypedMessageCashTrendingRenderer(props: TypedMessageRendererProp } return ( - - {props.message.content} + + {props.content} ) diff --git a/packages/mask/src/plugins/UnlockProtocol/SNSAdaptor/UnlockProtocolInPost.tsx b/packages/mask/src/plugins/UnlockProtocol/SNSAdaptor/UnlockProtocolInPost.tsx index 38062c903aa6..274231be68e3 100644 --- a/packages/mask/src/plugins/UnlockProtocol/SNSAdaptor/UnlockProtocolInPost.tsx +++ b/packages/mask/src/plugins/UnlockProtocol/SNSAdaptor/UnlockProtocolInPost.tsx @@ -1,4 +1,4 @@ -import type { TypedMessage } from '@masknet/shared-base' +import type { TypedMessage } from '@masknet/typed-message/base' import { Button, Typography } from '@mui/material' import { useEffect, useState } from 'react' import { useI18N } from '../../../utils' diff --git a/packages/mask/src/plugins/UnlockProtocol/helpers.ts b/packages/mask/src/plugins/UnlockProtocol/helpers.ts index 3cf88ca1d894..dba1333ccd46 100644 --- a/packages/mask/src/plugins/UnlockProtocol/helpers.ts +++ b/packages/mask/src/plugins/UnlockProtocol/helpers.ts @@ -1,4 +1,4 @@ -import { createRenderWithMetadata, createTypedMessageMetadataReader } from '@masknet/shared-base' +import { createRenderWithMetadata, createTypedMessageMetadataReader } from '@masknet/typed-message/base' import { pluginMetaKey } from './constants' import type { UnlockProtocolMetadata } from './types' import schema from './schema.json' diff --git a/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx b/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx index 017740a03739..91b7f345a278 100644 --- a/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx @@ -1,6 +1,7 @@ import { Suspense, useMemo } from 'react' import { Plugin, usePostInfoDetails } from '@masknet/plugin-infra' -import { extractTextFromTypedMessage, parseURL } from '@masknet/shared-base' +import { extractTextFromTypedMessage } from '@masknet/typed-message/base' +import { parseURL } from '@masknet/shared-base' import { SnackbarContent } from '@mui/material' import { base } from '../base' import MaskPluginWrapper from '../../MaskPluginWrapper' diff --git a/packages/mask/src/protocols/typed-message/debugger.tsx b/packages/mask/src/protocols/typed-message/debugger.tsx deleted file mode 100644 index 1c637d225506..000000000000 --- a/packages/mask/src/protocols/typed-message/debugger.tsx +++ /dev/null @@ -1,89 +0,0 @@ -// @ts-ignore -const React = require('jsx-jsonml-devtools-renderer') as any -import { - TypedMessage, - TypedMessageTuple, - TypedMessageImage, - TypedMessageText, - isTypedMessageTuple, - isTypedMessageText, - isTypedMessageImage, -} from '@masknet/shared-base' - -class TypedMessageFormatter { - isTypedMessage(obj: unknown): obj is TypedMessage { - if (typeof obj !== 'object' || obj === null) return false - if (!('version' in obj)) return false - if (!('meta' in obj)) return false - if (!('type' in obj)) return false - return true - } - hasBody(obj: unknown) { - if (!this.isTypedMessage(obj)) return false - if (obj.type === 'empty') return false - return true - } - compound(obj: TypedMessageTuple) { - return ( -
    -
      - {obj.items.map((x, i) => ( -
    1. {display(x)}
    2. - ))} -
    -
    - ) - } - fields(obj: TypedMessage) { - return ( - - - - - - {Object.keys(obj) - .filter((x) => x !== 'type' && x !== 'meta' && x !== 'version') - .map((x, i) => ( - - - {display((obj as any)[x])} - - ))} -
    FieldValue
    {x}
    - ) - } - text(obj: TypedMessageText) { - return {obj.content} - } - image(obj: TypedMessageImage) { - if (typeof obj.image === 'string') - return - return this.fields(obj) - } - body(obj: TypedMessage) { - if (isTypedMessageTuple(obj)) return this.compound(obj) - if (isTypedMessageText(obj)) return this.text(obj) - if (isTypedMessageImage(obj)) return this.image(obj) - return this.fields(obj) - } - header(obj: unknown) { - if (!this.isTypedMessage(obj)) return null - return ( -
    - TypedMessage({obj.type}) {(obj.meta?.size || 0) > 0 ? <>(with meta {display(obj.meta)}) : ''} -
    - ) - } -} -export function enhanceTypedMessageDebugger() { - React.installCustomObjectFormatter(new TypedMessageFormatter()) -} -function display(obj: unknown) { - switch (typeof obj) { - case 'string': - return obj - default: - // @ts-ignore - return - } -} diff --git a/packages/mask/src/protocols/typed-message/index.ts b/packages/mask/src/protocols/typed-message/index.ts deleted file mode 100644 index dcf8cbd66ff4..000000000000 --- a/packages/mask/src/protocols/typed-message/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './types' -export * from './render-registry' diff --git a/packages/mask/src/protocols/typed-message/render-registry.tsx b/packages/mask/src/protocols/typed-message/render-registry.tsx deleted file mode 100644 index 277296a4f171..000000000000 --- a/packages/mask/src/protocols/typed-message/render-registry.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import type { TypedMessage } from '@masknet/shared-base' -import type { TypedMessageRendererProps } from '../../components/InjectedComponents/TypedMessageRenderer' -type Renderer = React.ComponentType> - -interface RendererConfig { - component: Renderer - priority: number - id: string -} -const registry = new Map>>() -// TODO: before metadata, after metadata, ... -export function registerTypedMessageRenderer(matching: T['type'], config: RendererConfig) { - const set = registry.get(matching) || new Set() - // No overwrite in production - if (process.env.NODE_ENV === 'development') { - for (const item of set) - if (item.id === config.id) { - set.delete(item) - break - } - } - set.add(config) - registry.set(matching, set) -} -// TODO: add settings for "selected" renderer -export function getRendererOfTypedMessage(message: T): RendererConfig[] { - const list = [...(registry.get(message.type) || []), ...(registry.get('*') || [])].sort( - (x, y) => x.priority - y.priority, - ) - return list as any -} diff --git a/packages/mask/src/protocols/typed-message/types.ts b/packages/mask/src/protocols/typed-message/types.ts deleted file mode 100644 index b1a618abc607..000000000000 --- a/packages/mask/src/protocols/typed-message/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { isTypedMessageAnchor, isTypedMessageText, TypedMessage } from '@masknet/shared-base' - -export function getTypedMessageContent(message: TypedMessage): string { - if (isTypedMessageText(message)) return message.content - if (isTypedMessageAnchor(message)) return message.href - return '' -} diff --git a/packages/mask/src/settings/settings.ts b/packages/mask/src/settings/settings.ts index 7f62d51f97b8..ae35a9857532 100644 --- a/packages/mask/src/settings/settings.ts +++ b/packages/mask/src/settings/settings.ts @@ -14,14 +14,6 @@ export const debugModeSetting = createGlobalSettings('debugMode', false secondary: () => i18n.t('settings_enable_debug_desc'), }) -/** - * Whether if create substitute post for all posts - */ -export const allPostReplacementSettings = createGlobalSettings('post replacement all', false, { - primary: () => i18n.t('settings_post_replacement'), - secondary: () => i18n.t('settings_post_replacement_desc'), -}) - // #region appearance export const appearanceSettings = createGlobalSettings('appearance', Appearance.default, { primary: () => i18n.t('settings_appearance'), diff --git a/packages/mask/src/social-network-adaptor/browser-action/index.ts b/packages/mask/src/social-network-adaptor/browser-action/index.ts index 8245c74a4e6d..b19802a92f13 100644 --- a/packages/mask/src/social-network-adaptor/browser-action/index.ts +++ b/packages/mask/src/social-network-adaptor/browser-action/index.ts @@ -1,14 +1,15 @@ import { defineSocialNetworkUI, definedSocialNetworkUIs, SocialNetworkUI, SocialNetwork } from '../../social-network' import { isEnvironment, Environment, ValueRef } from '@dimensiondev/holoflows-kit' import { IdentifierMap } from '@masknet/shared-base' +import { SocialNetworkEnum } from '@masknet/encryption' const base: SocialNetwork.Base = { networkIdentifier: 'localhost', - name: '', declarativePermissions: { origins: [] }, shouldActivate(location) { return isEnvironment(Environment.ManifestAction) }, + network: SocialNetworkEnum.Unknown, } const define: SocialNetworkUI.Definition = { ...base, diff --git a/packages/mask/src/social-network-adaptor/facebook.com/automation/openComposeBox.ts b/packages/mask/src/social-network-adaptor/facebook.com/automation/openComposeBox.ts index 4783c9b38c0a..0d4f50e5ed01 100644 --- a/packages/mask/src/social-network-adaptor/facebook.com/automation/openComposeBox.ts +++ b/packages/mask/src/social-network-adaptor/facebook.com/automation/openComposeBox.ts @@ -2,7 +2,8 @@ import { LiveSelector } from '@dimensiondev/holoflows-kit' import { MaskMessages, CompositionRequest } from '../../../utils/messages' import { i18n } from '../../../../shared-ui/locales_legacy' import { untilDocumentReady } from '../../../utils/dom' -import { makeTypedMessageText, TypedMessage, delay } from '@masknet/shared-base' +import { makeTypedMessageText, TypedMessage } from '@masknet/typed-message/base' +import { delay } from '@masknet/shared-base' const nativeComposeButtonSelector = () => new LiveSelector() diff --git a/packages/mask/src/social-network-adaptor/facebook.com/base.ts b/packages/mask/src/social-network-adaptor/facebook.com/base.ts index 6335b60223a9..1b86e66b1bf0 100644 --- a/packages/mask/src/social-network-adaptor/facebook.com/base.ts +++ b/packages/mask/src/social-network-adaptor/facebook.com/base.ts @@ -1,3 +1,4 @@ +import { SocialNetworkEnum } from '@masknet/encryption' import type { SocialNetwork, SocialNetworkWorker } from '../../social-network/types' const origins = ['https://www.facebook.com/*', 'https://m.facebook.com/*', 'https://facebook.com/*'] @@ -5,7 +6,7 @@ const origins = ['https://www.facebook.com/*', 'https://m.facebook.com/*', 'http export const FACEBOOK_ID = 'facebook.com' export const facebookBase: SocialNetwork.Base = { networkIdentifier: FACEBOOK_ID, - name: 'facebook', + network: SocialNetworkEnum.Facebook, declarativePermissions: { origins }, shouldActivate(location) { return location.hostname.endsWith(FACEBOOK_ID) diff --git a/packages/mask/src/social-network-adaptor/facebook.com/collecting/posts.tsx b/packages/mask/src/social-network-adaptor/facebook.com/collecting/posts.tsx index 98f7d681ad29..3a41f47ef981 100644 --- a/packages/mask/src/social-network-adaptor/facebook.com/collecting/posts.tsx +++ b/packages/mask/src/social-network-adaptor/facebook.com/collecting/posts.tsx @@ -3,7 +3,12 @@ import type { SocialNetworkUI as Next } from '../../../social-network/types' import { creator } from '../../../social-network/utils' import { isMobileFacebook } from '../utils/isMobile' import { getProfileIdentifierAtFacebook } from '../utils/getProfileIdentifier' -import { TypedMessage, makeTypedMessageText, makeTypedMessageImage, makeTypedMessageTuple } from '@masknet/shared-base' +import { + TypedMessage, + makeTypedMessageText, + makeTypedMessageImage, + makeTypedMessageTuple, +} from '@masknet/typed-message/base' import { clickSeeMore } from '../injection/PostInspector' import { startWatch } from '../../../utils/watcher' import { facebookShared } from '../shared' @@ -82,10 +87,8 @@ function collectPostsFacebookInner(store: Next.CollectingCapabilities.PostsProvi function collectPostInfo() { rootProxy.realCurrent = root.evaluate()[0] const nextTypedMessage: TypedMessage[] = [] - info.postBy.value = getPostBy( - metadata, - postInfo.containingMaskPayload.getCurrentValue() !== null, - ).identifier + // TODO: + // info.postBy.value = getPostBy(metadata, postInfo.containsMaskPayload.getCurrentValue()).identifier info.postID.value = getPostID(metadata, rootProxy.realCurrent) // parse text const text = collectNodeText(node, { diff --git a/packages/mask/src/social-network-adaptor/facebook.com/injection/PostInspector.tsx b/packages/mask/src/social-network-adaptor/facebook.com/injection/PostInspector.tsx index 0ea99a16375c..4722609c5a02 100644 --- a/packages/mask/src/social-network-adaptor/facebook.com/injection/PostInspector.tsx +++ b/packages/mask/src/social-network-adaptor/facebook.com/injection/PostInspector.tsx @@ -1,4 +1,3 @@ -import type { DOMProxy } from '@dimensiondev/holoflows-kit' import { isMobileFacebook } from '../utils/isMobile' import type { PostInfo } from '../../../social-network/PostInfo' import { injectPostInspectorDefault } from '../../../social-network/defaults/inject/PostInspector' @@ -14,63 +13,9 @@ function getShadowRoot(node: HTMLElement) { export function injectPostInspectorFacebook(signal: AbortSignal, current: PostInfo) { clickSeeMore(current.rootElement.current?.parentElement) return injectPostInspectorDefault({ - zipPost(node) { - zipEncryptedPostContent(node) - zipPostLinkPreview(node) - }, injectionPoint: (post) => getShadowRoot(post.suggestedInjectionPoint), })(current, signal) } -function zipPostLinkPreview(node: DOMProxy) { - const parentEle = node.current.parentElement - if (!parentEle) return - if (isMobileFacebook) { - const img = - parentEle.querySelector('a[href*="maskbook.io"]') ?? - parentEle.querySelector('a[href*="mask.io"]') ?? - parentEle.querySelector('a[href*="maskbook.com"]') - const parent = img?.closest('section') - if (img && parent) { - parent.style.display = 'none' - } - } else { - const img = - parentEle.querySelector('a[href*="maskbook.io"] img') ?? - parentEle.querySelector('a[href*="mask.io"] img') ?? - parentEle.querySelector('a[href*="maskbook.com"] img') - const parent = img?.closest('span') - if (img && parent) { - parent.style.display = 'none' - } - } -} -function zipEncryptedPostContent(node: DOMProxy) { - const parent = node.current.parentElement - // It's image based encryption, skip zip post. - if (!node.current.innerText.includes('\u{1F3BC}')) return - // Style modification for repost - if (!node.current.className.includes('userContent') && node.current.innerText.length > 0) { - node.after.setAttribute( - 'style', - `border: 1px solid #ebedf0; -display: block; -border-top: none; -border-bottom: none; -margin-bottom: 0px; -padding: 0px 10px;`, - ) - } - if (parent) { - // post content - const p = parent.querySelector('p') - if (p) { - p.style.display = 'block' - p.style.maxHeight = '20px' - p.style.overflow = 'hidden' - p.style.marginBottom = '0' - } - } -} export function clickSeeMore(node: HTMLElement | undefined | null) { if (!node) return const more = node.querySelector( diff --git a/packages/mask/src/social-network-adaptor/facebook.com/shared.ts b/packages/mask/src/social-network-adaptor/facebook.com/shared.ts index f181f19d02b4..e0c646923384 100644 --- a/packages/mask/src/social-network-adaptor/facebook.com/shared.ts +++ b/packages/mask/src/social-network-adaptor/facebook.com/shared.ts @@ -2,8 +2,8 @@ import type { SocialNetwork } from '../../social-network/types' import { facebookBase } from './base' import { getPostUrlAtFacebook, isValidFacebookUsername } from './utils/parse-username' import { PostIdentifier, ProfileIdentifier } from '@masknet/shared-base' -import { deconstructPayload } from '../../utils' import { createSNSAdaptorSpecializedPostContext } from '../../social-network/utils/create-post-context' +import { SocialNetworkEnum } from '@masknet/encryption' const getPostURL = (post: PostIdentifier): URL | null => { if (post.identifier instanceof ProfileIdentifier) @@ -16,8 +16,6 @@ export const facebookShared: SocialNetwork.Shared & SocialNetwork.Base = { getHomePage: () => 'https://www.facebook.com', getProfilePage: (userId: string) => 'https://www.facebook.com', isValidUsername: (v) => !!isValidFacebookUsername(v), - publicKeyEncoding: undefined, - textPayloadPostProcessor: undefined, getPostURL, getShareLinkURL(message) { const url = new URL('https://www.facebook.com/sharer/sharer.php') @@ -26,8 +24,8 @@ export const facebookShared: SocialNetwork.Shared & SocialNetwork.Base = { return url }, createPostContext: createSNSAdaptorSpecializedPostContext({ - payloadParser: deconstructPayload, getURLFromPostIdentifier: getPostURL, + socialNetwork: SocialNetworkEnum.Facebook, }), }, } diff --git a/packages/mask/src/social-network-adaptor/facebook.com/ui-provider.ts b/packages/mask/src/social-network-adaptor/facebook.com/ui-provider.ts index 8d81c39aab86..9e321c52ed64 100644 --- a/packages/mask/src/social-network-adaptor/facebook.com/ui-provider.ts +++ b/packages/mask/src/social-network-adaptor/facebook.com/ui-provider.ts @@ -159,8 +159,6 @@ const facebookUI: SocialNetworkUI.Definition = { image: true, }, }, - // Not supported yet - enhancedPostRenderer: undefined, userBadge: undefined, searchResult: undefined, setupPrompt: injectSetupPromptFacebook, diff --git a/packages/mask/src/social-network-adaptor/facebook.com/utils/resolveFacebookLink.ts b/packages/mask/src/social-network-adaptor/facebook.com/utils/resolveFacebookLink.ts index 3acccb7bccd6..abc662cd7634 100644 --- a/packages/mask/src/social-network-adaptor/facebook.com/utils/resolveFacebookLink.ts +++ b/packages/mask/src/social-network-adaptor/facebook.com/utils/resolveFacebookLink.ts @@ -1,5 +1,3 @@ -import { FACEBOOK_ID } from '../base' - -export function resolveFacebookLink(link: string, id: string) { - return id === FACEBOOK_ID ? link.replace(/\?fbclid=[\S\s]*#/, '#') : link +export function resolveFacebookLink(link: string) { + return link.replace(/\?fbclid=[\S\s]*#/, '#') } diff --git a/packages/mask/src/social-network-adaptor/instagram.com/base.ts b/packages/mask/src/social-network-adaptor/instagram.com/base.ts index 4ed98e9b94a3..68db17f1b6e6 100644 --- a/packages/mask/src/social-network-adaptor/instagram.com/base.ts +++ b/packages/mask/src/social-network-adaptor/instagram.com/base.ts @@ -1,10 +1,11 @@ +import { SocialNetworkEnum } from '@masknet/encryption' import type { SocialNetwork, SocialNetworkWorker } from '../../social-network/types' const id = 'instagram.com' const origins = ['https://www.instagram.com/*', 'https://m.instagram.com/*', 'https://instagram.com/*'] export const instagramBase: SocialNetwork.Base = { networkIdentifier: id, - name: 'instagram', + network: SocialNetworkEnum.Instagram, declarativePermissions: { origins }, shouldActivate(location) { return location.host.endsWith(id) diff --git a/packages/mask/src/social-network-adaptor/instagram.com/collecting/posts.ts b/packages/mask/src/social-network-adaptor/instagram.com/collecting/posts.ts index adbe00ad9db8..13fc26b093a4 100644 --- a/packages/mask/src/social-network-adaptor/instagram.com/collecting/posts.ts +++ b/packages/mask/src/social-network-adaptor/instagram.com/collecting/posts.ts @@ -1,7 +1,8 @@ import { DOMProxy, LiveSelector, MutationObserverWatcher } from '@dimensiondev/holoflows-kit' import type { SocialNetworkUI } from '../../../social-network/types' import { creator } from '../../../social-network/utils' -import { TypedMessage, makeTypedMessageImage, makeTypedMessageTuple, ProfileIdentifier } from '@masknet/shared-base' +import { TypedMessage, makeTypedMessageImage, makeTypedMessageTuple } from '@masknet/typed-message/base' +import { ProfileIdentifier } from '@masknet/shared-base' import { startWatch } from '../../../utils/watcher' import { instagramBase } from '../base' import { createRefsForCreatePostContext } from '../../../social-network/utils/create-post-context' diff --git a/packages/mask/src/social-network-adaptor/instagram.com/injection/post-inspector.ts b/packages/mask/src/social-network-adaptor/instagram.com/injection/post-inspector.ts index a44cf7af726c..60aa536db143 100644 --- a/packages/mask/src/social-network-adaptor/instagram.com/injection/post-inspector.ts +++ b/packages/mask/src/social-network-adaptor/instagram.com/injection/post-inspector.ts @@ -10,10 +10,7 @@ function getShadowRoot(node: HTMLElement) { return dom } export function injectPostInspectorInstagram(signal: AbortSignal, current: PostInfo) { - return injectPostInspectorDefault( - { - injectionPoint: (post) => getShadowRoot(post.suggestedInjectionPoint), - }, - () => ({ slotPosition: 'after' }), - )(current, signal) + return injectPostInspectorDefault({ + injectionPoint: (post) => getShadowRoot(post.suggestedInjectionPoint), + })(current, signal) } diff --git a/packages/mask/src/social-network-adaptor/instagram.com/shared.ts b/packages/mask/src/social-network-adaptor/instagram.com/shared.ts index 4a415b1018c7..73c0a1c46aa2 100644 --- a/packages/mask/src/social-network-adaptor/instagram.com/shared.ts +++ b/packages/mask/src/social-network-adaptor/instagram.com/shared.ts @@ -1,6 +1,6 @@ +import { SocialNetworkEnum } from '@masknet/encryption' import type { SocialNetwork } from '../../social-network/types' import { createSNSAdaptorSpecializedPostContext } from '../../social-network/utils/create-post-context' -import { deconstructPayload } from '../../utils' import { instagramBase } from './base' export const instagramShared: SocialNetwork.Shared & SocialNetwork.Base = { @@ -9,7 +9,7 @@ export const instagramShared: SocialNetwork.Shared & SocialNetwork.Base = { getHomePage: () => 'https://www.instagram.com/', getProfilePage: () => 'https://www.instagram.com/', createPostContext: createSNSAdaptorSpecializedPostContext({ - payloadParser: deconstructPayload, + socialNetwork: SocialNetworkEnum.Instagram, }), }, } diff --git a/packages/mask/src/social-network-adaptor/instagram.com/ui-provider.ts b/packages/mask/src/social-network-adaptor/instagram.com/ui-provider.ts index 74a97c9c04e0..592e2b973c44 100644 --- a/packages/mask/src/social-network-adaptor/instagram.com/ui-provider.ts +++ b/packages/mask/src/social-network-adaptor/instagram.com/ui-provider.ts @@ -24,11 +24,7 @@ const define: SocialNetworkUI.Definition = { identityProvider: IdentityProviderInstagram, postsProvider: PostProviderInstagram, }, - configuration: { - setupWizard: { - disableSayHello: true, - }, - }, + configuration: {}, customization: {}, init(signal) { const friends = stateCreator.friends() diff --git a/packages/mask/src/social-network-adaptor/minds.com/automation/openComposeBox.ts b/packages/mask/src/social-network-adaptor/minds.com/automation/openComposeBox.ts index 5529f09ad44b..6a8727e0ab12 100644 --- a/packages/mask/src/social-network-adaptor/minds.com/automation/openComposeBox.ts +++ b/packages/mask/src/social-network-adaptor/minds.com/automation/openComposeBox.ts @@ -1,4 +1,5 @@ -import { makeTypedMessageText, TypedMessage, delay } from '@masknet/shared-base' +import { makeTypedMessageText, TypedMessage } from '@masknet/typed-message/base' +import { delay } from '@masknet/shared-base' import { untilDocumentReady } from '../../../utils/dom' import { i18n } from '../../../../shared-ui/locales_legacy' import { MaskMessages, CompositionRequest } from '../../../utils/messages' diff --git a/packages/mask/src/social-network-adaptor/minds.com/base.ts b/packages/mask/src/social-network-adaptor/minds.com/base.ts index d68eef969776..09b6e490811e 100644 --- a/packages/mask/src/social-network-adaptor/minds.com/base.ts +++ b/packages/mask/src/social-network-adaptor/minds.com/base.ts @@ -1,10 +1,11 @@ +import { SocialNetworkEnum } from '@masknet/encryption' import type { SocialNetwork, SocialNetworkWorker } from '../../social-network/types' export const MINDS_ID = 'minds.com' const origins = ['https://www.minds.com/*', 'https://minds.com/*', 'https://cdn.minds.com/*'] export const mindsBase: SocialNetwork.Base = { networkIdentifier: MINDS_ID, - name: 'minds', + network: SocialNetworkEnum.Minds, declarativePermissions: { origins }, shouldActivate(location) { return location.hostname.endsWith('minds.com') diff --git a/packages/mask/src/social-network-adaptor/minds.com/collecting/post.ts b/packages/mask/src/social-network-adaptor/minds.com/collecting/post.ts index f21b4f9b2253..ae5f11c4571f 100644 --- a/packages/mask/src/social-network-adaptor/minds.com/collecting/post.ts +++ b/packages/mask/src/social-network-adaptor/minds.com/collecting/post.ts @@ -4,9 +4,9 @@ import { makeTypedMessagePromise, makeTypedMessageTuple, makeTypedMessageTupleFromList, - ProfileIdentifier, makeTypedMessageImage, -} from '@masknet/shared-base' +} from '@masknet/typed-message/base' +import { ProfileIdentifier } from '@masknet/shared-base' import type { SocialNetworkUI as Next } from '../../../social-network/types' import { creator } from '../../../social-network/utils' import { createRefsForCreatePostContext } from '../../../social-network/utils/create-post-context' diff --git a/packages/mask/src/social-network-adaptor/minds.com/injection/PostInspector.tsx b/packages/mask/src/social-network-adaptor/minds.com/injection/PostInspector.tsx index 7d6ad19cddad..1d0e9005f213 100644 --- a/packages/mask/src/social-network-adaptor/minds.com/injection/PostInspector.tsx +++ b/packages/mask/src/social-network-adaptor/minds.com/injection/PostInspector.tsx @@ -1,6 +1,25 @@ import { injectPostInspectorDefault } from '../../../social-network/defaults/inject/PostInspector' import type { PostInfo } from '../../../social-network/PostInfo' +function resolveContentNode(node: HTMLElement) { + return node.closest( + [ + 'm-activity__content .m-activityContent__messageWrapper > span:first-child', + 'm-activity__content .m-activityContent__mediaDescriptionText', + ].join() as any, + ) +} + export function injectPostInspectorAtMinds(signal: AbortSignal, current: PostInfo) { - return injectPostInspectorDefault()(current, signal) + return injectPostInspectorDefault({ + zip(node) { + const langNode = resolveContentNode(node.current) + if (langNode) langNode.style.display = 'none' + }, + unzip(node) { + if (!node.current) return + const langNode = resolveContentNode(node.current) + if (langNode) langNode.style.display = 'unset' + }, + })(current, signal) } diff --git a/packages/mask/src/social-network-adaptor/minds.com/injection/PostReplacer.tsx b/packages/mask/src/social-network-adaptor/minds.com/injection/PostReplacer.tsx deleted file mode 100644 index 777f99bedd69..000000000000 --- a/packages/mask/src/social-network-adaptor/minds.com/injection/PostReplacer.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { injectPostReplacer } from '../../../social-network/defaults/inject/PostReplacer' -import type { PostInfo } from '../../../social-network/PostInfo' - -function resolveContentNode(node: HTMLElement) { - return node.closest( - [ - 'm-activity__content .m-activityContent__messageWrapper > span:first-child', - 'm-activity__content .m-activityContent__mediaDescriptionText', - ].join() as any, - ) -} - -export function injectPostReplacerAtMinds(signal: AbortSignal, current: PostInfo) { - return injectPostReplacer({ - zipPost(node) { - const langNode = resolveContentNode(node.current) - if (langNode) langNode.style.display = 'none' - }, - unzipPost(node) { - if (!node.current) return - const langNode = resolveContentNode(node.current) - if (langNode) langNode.style.display = 'unset' - }, - })(current, signal) -} diff --git a/packages/mask/src/social-network-adaptor/minds.com/shared.ts b/packages/mask/src/social-network-adaptor/minds.com/shared.ts index 7272a9f5fc1a..3fc586488165 100644 --- a/packages/mask/src/social-network-adaptor/minds.com/shared.ts +++ b/packages/mask/src/social-network-adaptor/minds.com/shared.ts @@ -1,7 +1,7 @@ +import { SocialNetworkEnum } from '@masknet/encryption' import type { PostIdentifier } from '@masknet/shared-base' import type { SocialNetwork } from '../../social-network/types' import { createSNSAdaptorSpecializedPostContext } from '../../social-network/utils/create-post-context' -import { deconstructPayload } from '../../utils' import { mindsBase } from './base' import { usernameValidator } from './utils/user' @@ -14,15 +14,13 @@ export const mindsShared: SocialNetwork.Shared & SocialNetwork.Base = { getHomePage: () => 'https://www.minds.com', getProfilePage: () => 'https://www.minds.com', isValidUsername: usernameValidator, - publicKeyEncoding: undefined, - textPayloadPostProcessor: undefined, getPostURL, getShareLinkURL(message) { return new URL(`https://www.minds.com/newsfeed/subscriptions?intentUrl=${encodeURIComponent(message)}`) }, createPostContext: createSNSAdaptorSpecializedPostContext({ - payloadParser: deconstructPayload, getURLFromPostIdentifier: getPostURL, + socialNetwork: SocialNetworkEnum.Minds, }), }, } diff --git a/packages/mask/src/social-network-adaptor/minds.com/ui-provider.ts b/packages/mask/src/social-network-adaptor/minds.com/ui-provider.ts index 2c6a547c4e62..a448976c4761 100644 --- a/packages/mask/src/social-network-adaptor/minds.com/ui-provider.ts +++ b/packages/mask/src/social-network-adaptor/minds.com/ui-provider.ts @@ -19,7 +19,6 @@ import { PaletteModeProviderMinds, useThemeMindsVariant } from './customization/ import injectCommentBoxAtMinds from './injection/CommentBox' import { injectPostBoxComposed } from './injection/inject' import { injectPostInspectorAtMinds } from './injection/PostInspector' -import { injectPostReplacerAtMinds } from './injection/PostReplacer' import { injectSearchResultBoxAtMinds } from './injection/SearchResultBox' import { injectSetupPromptAtMinds } from './injection/SetupPrompt' import { injectToolboxHintAtMinds } from './injection/ToolboxHint' @@ -141,7 +140,6 @@ const mindsUI: SocialNetworkUI.Definition = { toolbox: injectToolboxHintAtMinds, pageInspector: injectPageInspectorDefault(), postInspector: injectPostInspectorAtMinds, - enhancedPostRenderer: injectPostReplacerAtMinds, setupPrompt: injectSetupPromptAtMinds, searchResult: injectSearchResultBoxAtMinds, newPostComposition: { diff --git a/packages/mask/src/social-network-adaptor/minds.com/utils/fetch.ts b/packages/mask/src/social-network-adaptor/minds.com/utils/fetch.ts index 15a55a574202..80872f290141 100644 --- a/packages/mask/src/social-network-adaptor/minds.com/utils/fetch.ts +++ b/packages/mask/src/social-network-adaptor/minds.com/utils/fetch.ts @@ -7,7 +7,7 @@ import { makeTypedMessageText, TypedMessage, TypedMessageText, -} from '@masknet/shared-base' +} from '@masknet/typed-message/base' import { assertNonNull } from '../../../../utils-pure' const parseNameArea = (nameArea: HTMLAnchorElement) => { diff --git a/packages/mask/src/social-network-adaptor/twitter.com/automation/openComposeBox.ts b/packages/mask/src/social-network-adaptor/twitter.com/automation/openComposeBox.ts index c95866501c7a..5d863279707d 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/automation/openComposeBox.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/automation/openComposeBox.ts @@ -1,5 +1,5 @@ import { MaskMessages, CompositionRequest } from '../../../utils/messages' -import { makeTypedMessageText, TypedMessage } from '@masknet/shared-base' +import { makeTypedMessageText, TypedMessage } from '@masknet/typed-message/base' export function openComposeBoxTwitter(content: string | TypedMessage, options?: CompositionRequest['options']) { MaskMessages.events.requestComposition.sendToLocal({ diff --git a/packages/mask/src/social-network-adaptor/twitter.com/base.ts b/packages/mask/src/social-network-adaptor/twitter.com/base.ts index a85a61db85cd..61ad6bb4314c 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/base.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/base.ts @@ -1,10 +1,11 @@ +import { SocialNetworkEnum } from '@masknet/encryption' import type { SocialNetwork, SocialNetworkWorker } from '../../social-network/types' const id = 'twitter.com' const origins = ['https://mobile.twitter.com/*', 'https://twitter.com/*'] export const twitterBase: SocialNetwork.Base = { networkIdentifier: id, - name: 'twitter', + network: SocialNetworkEnum.Twitter, declarativePermissions: { origins }, shouldActivate(location) { return location.hostname.endsWith('twitter.com') diff --git a/packages/mask/src/social-network-adaptor/twitter.com/collecting/post.ts b/packages/mask/src/social-network-adaptor/twitter.com/collecting/post.ts index bd4ff7fa6266..63d7ca925157 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/collecting/post.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/collecting/post.ts @@ -6,14 +6,14 @@ import { postIdParser, postParser, postImagesParser } from '../utils/fetch' import { memoize } from 'lodash-unified' import Services from '../../../extension/service' import { injectMaskIconToPostTwitter } from '../injection/MaskIcon' +import { ProfileIdentifier } from '@masknet/shared-base' import { - ProfileIdentifier, makeTypedMessageImage, makeTypedMessageTupleFromList, makeTypedMessageEmpty, makeTypedMessagePromise, makeTypedMessageTuple, -} from '@masknet/shared-base' +} from '@masknet/typed-message/base' import { untilElementAvailable } from '../../../utils/dom' import { twitterBase } from '../base' import { twitterShared } from '../shared' @@ -81,14 +81,15 @@ function registerPostCollectorInner( collectLinks(tweetNode, refs, cancel) } run() - cancel.addEventListener( - 'abort', - info.containingMaskPayload.subscribe(() => { - const payload = info.containingMaskPayload.getCurrentValue() - if (payload.err && refs.postMetadataImages.size === 0) return - updateProfileInfo(info) - }), - ) + // TODO: + // cancel.addEventListener( + // 'abort', + // info.containsMaskPayload.subscribe(() => { + // const noMaskPayload = !info.containsMaskPayload.getCurrentValue() + // if (noMaskPayload && refs.postMetadataImages.size === 0) return + // updateProfileInfo(info) + // }), + // ) injectMaskIconToPostTwitter(info, cancel) postStore.set(proxy, info) return { diff --git a/packages/mask/src/social-network-adaptor/twitter.com/encoding.ts b/packages/mask/src/social-network-adaptor/twitter.com/encoding.ts deleted file mode 100644 index 4eb9420355b2..000000000000 --- a/packages/mask/src/social-network-adaptor/twitter.com/encoding.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { TwitterDecoder, __TwitterEncoder } from '@masknet/encryption' -import { isNull } from 'lodash-unified' -const ICAO9303Checksum = { - encode: (input: string) => { - return `${input}${( - input - .toUpperCase() - .replace(/[+/=]/g, '0') - .split('') - .map((d, i) => Number.parseInt(d, 36) * [7, 3, 1][i % 3]) - .reduce((l, r) => l + r, 0) % 19 - ) - .toString(19) - .toUpperCase()}` - }, - decode: (input: string) => { - const content = input.slice(0, input.length - 1) - const checksum = input.slice(input.length - 1) - const r = ICAO9303Checksum.encode(content) - if (checksum === r.slice(r.length - 1)) { - return content - } else { - return null - } - }, -} - -export const twitterEncoding = { - /** - * @link https://github.com/DimensionDev/Maskbook/issues/191 - */ - publicKeyEncoder: (text: string) => `\u{1F3AD}${ICAO9303Checksum.encode(text)}\u{1F3AD}`, - publicKeyDecoder: (text: string): string[] => { - const r = regexMatchAll(text, /([\d+/=A-Za-z]{20,60})/) - if (isNull(r)) { - return [] - } - for (const v of r) { - const retV = ICAO9303Checksum.decode(v) - if (isNull(retV)) { - continue - } - return [retV] - } - return [] - }, - payloadEncoder: __TwitterEncoder, - payloadDecoder: (text: string): string[] => { - return TwitterDecoder(text) - .map((x) => [x]) - .unwrapOr([]) - }, -} - -function regexMatchAll(str: string, regexp: RegExp, index = 1) { - const gPos = regexp.flags.indexOf('g') - const withoutG = gPos >= 0 ? `${regexp.flags.slice(0, gPos)}${regexp.flags.slice(gPos + 1)}` : regexp.flags - const o = new RegExp(regexp.source, withoutG) - const g = new RegExp(regexp.source, `${withoutG}g`) - const r = str.match(g) - if (isNull(r)) { - return null - } - const sto = [] - for (const v of r) { - const retV = v.match(o) - if (isNull(retV)) { - continue - } - sto.push(retV[index]) - } - if (sto.length === 0) { - return null - } - return sto -} diff --git a/packages/mask/src/social-network-adaptor/twitter.com/injection/PostDialogHint.tsx b/packages/mask/src/social-network-adaptor/twitter.com/injection/PostDialogHint.tsx index 532be145b54c..7a7ce4485eda 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/injection/PostDialogHint.tsx +++ b/packages/mask/src/social-network-adaptor/twitter.com/injection/PostDialogHint.tsx @@ -10,7 +10,7 @@ import { makeStyles, MaskColorVar } from '@masknet/theme' import { alpha } from '@mui/material' import { twitterBase } from '../base' import { sayHelloShowed } from '../../../settings/settings' -import { makeTypedMessageText } from '@masknet/shared-base' +import { makeTypedMessageText } from '@masknet/typed-message/base' import { useI18N } from '../../../utils' const useStyles = makeStyles()((theme) => ({ diff --git a/packages/mask/src/social-network-adaptor/twitter.com/injection/PostInspector.tsx b/packages/mask/src/social-network-adaptor/twitter.com/injection/PostInspector.tsx index ec793e6d3ae9..74e0b9767476 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/injection/PostInspector.tsx +++ b/packages/mask/src/social-network-adaptor/twitter.com/injection/PostInspector.tsx @@ -1,54 +1,22 @@ -/* eslint @dimensiondev/unicode-specific-set: ["error", { "only": "code" }] */ import type { PostInfo } from '../../../social-network/PostInfo' import { injectPostInspectorDefault } from '../../../social-network/defaults/inject/PostInspector' -import { twitterEncoding } from '../encoding' + +function resolveLangNode(node: HTMLElement) { + return node.hasAttribute('lang') + ? node + : node.querySelector('[lang]') ?? node.parentElement?.querySelector('[lang]') +} export function injectPostInspectorAtTwitter(signal: AbortSignal, current: PostInfo) { return injectPostInspectorDefault({ - zipPost(node) { - const contentContainer = node.current.parentElement - if (!contentContainer) return - - const content = contentContainer.querySelector('[lang]') - if (!content) return - - for (const a of content.querySelectorAll('a')) { - if (twitterEncoding.payloadDecoder(a.title).length) hideDOM(a) - - if (/^https?:\/\/mask(\.io|book\.com)$/i.test(a.title)) hideDOM(a) - } - for (const span of content.querySelectorAll('span')) { - // match (.) (\n) (—§—) (any space) (/*) - // Note: In Chinese we can't hide dom because "解密这条推文。\n—§—" is in the same DOM - // hide it will break the sentence. - if (span.innerText.match(/^\.\n\u2014\u00A7\u2014 +\/\* $/)) hideDOM(span) - // match (any space) (*/) (any space) - if (span.innerText.match(/^ +\*\/ ?$/)) hideDOM(span) - } - - const parent = content.parentElement?.nextElementSibling as HTMLElement - if (parent && matches(parent.innerText)) { - parent.style.height = '0' - parent.style.overflow = 'hidden' - } - - const cardWrapper = - contentContainer.parentElement?.querySelector('[data-testid="card.wrapper"]') - if (cardWrapper) { - cardWrapper.style.display = 'none' - cardWrapper.setAttribute('aria-hidden', 'true') - } + zip(node) { + const langNode = resolveLangNode(node.current) + if (langNode) langNode.style.display = 'none' + }, + unzip(node) { + if (!node.current) return + const langNode = resolveLangNode(node.current) + if (langNode) langNode.style.display = 'unset' }, })(current, signal) } -function matches(input: string) { - input = input.toLowerCase() - return input.includes('maskbook.com') && input.includes('make privacy protected again') -} - -function hideDOM(a: HTMLElement) { - a.style.width = '0' - a.style.height = '0' - a.style.overflow = 'hidden' - a.style.display = 'inline-block' -} diff --git a/packages/mask/src/social-network-adaptor/twitter.com/injection/PostReplacer.tsx b/packages/mask/src/social-network-adaptor/twitter.com/injection/PostReplacer.tsx deleted file mode 100644 index 540cfb34f540..000000000000 --- a/packages/mask/src/social-network-adaptor/twitter.com/injection/PostReplacer.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { PostInfo } from '../../../social-network/PostInfo' -import { injectPostReplacer } from '../../../social-network/defaults/inject/PostReplacer' - -function resolveLangNode(node: HTMLElement) { - return node.hasAttribute('lang') - ? node - : node.querySelector('[lang]') ?? node.parentElement?.querySelector('[lang]') -} - -export function injectPostReplacerAtTwitter(signal: AbortSignal, current: PostInfo) { - return injectPostReplacer({ - zipPost(node) { - const langNode = resolveLangNode(node.current) - if (langNode) langNode.style.display = 'none' - }, - unzipPost(node) { - if (!node.current) return - const langNode = resolveLangNode(node.current) - if (langNode) langNode.style.display = 'unset' - }, - })(current, signal) -} diff --git a/packages/mask/src/social-network-adaptor/twitter.com/shared.ts b/packages/mask/src/social-network-adaptor/twitter.com/shared.ts index 015ae96e54a3..d70a23087f8f 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/shared.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/shared.ts @@ -1,9 +1,8 @@ +import { SocialNetworkEnum } from '@masknet/encryption' import { PostIdentifier, ProfileIdentifier } from '@masknet/shared-base' import type { SocialNetwork } from '../../social-network/types' import { createSNSAdaptorSpecializedPostContext } from '../../social-network/utils/create-post-context' -import { deconstructPayload } from '../../utils' import { twitterBase } from './base' -import { twitterEncoding } from './encoding' import { usernameValidator } from './utils/user' const getPostURL = (post: PostIdentifier): URL | null => { @@ -16,30 +15,13 @@ export const twitterShared: SocialNetwork.Shared & SocialNetwork.Base = { getHomePage: () => 'https://twitter.com', getProfilePage: (userId) => `https://twitter.com/${userId}`, isValidUsername: usernameValidator, - publicKeyEncoding: { - encoder(text) { - return twitterEncoding.publicKeyEncoder(text) - }, - decoder(text) { - return twitterEncoding.publicKeyDecoder(text) - }, - }, - textPayloadPostProcessor: { - encoder(text) { - return twitterEncoding.payloadEncoder(text) - }, - decoder(text) { - return twitterEncoding.payloadDecoder(text) - }, - }, getPostURL, getShareLinkURL(message) { return new URL(`https://twitter.com/intent/tweet?text=${encodeURIComponent(message)}`) }, createPostContext: createSNSAdaptorSpecializedPostContext({ - payloadParser: deconstructPayload, - payloadDecoder: twitterEncoding.payloadDecoder, getURLFromPostIdentifier: getPostURL, + socialNetwork: SocialNetworkEnum.Twitter, }), }, } diff --git a/packages/mask/src/social-network-adaptor/twitter.com/ui-provider.ts b/packages/mask/src/social-network-adaptor/twitter.com/ui-provider.ts index 4adcbc16fbcd..3e9497fc9ce7 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/ui-provider.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/ui-provider.ts @@ -17,7 +17,6 @@ import { injectSearchResultBoxAtTwitter } from './injection/SearchResultBox' import { injectProfileSliderAtTwitter } from './injection/ProfileSlider' import { injectProfileTabAtTwitter } from './injection/ProfileTab' import { injectProfileTabContentAtTwitter } from './injection/ProfileTabContent' -import { injectPostReplacerAtTwitter } from './injection/PostReplacer' import { injectPageInspectorDefault } from '../../social-network/defaults/inject/PageInspector' import { injectSetupPromptAtTwitter } from './injection/SetupPrompt' import { injectPostBoxComposed } from './injection/inject' @@ -152,7 +151,6 @@ const twitterUI: SocialNetworkUI.Definition = { profileTab: injectProfileTabAtTwitter, profileTabContent: injectProfileTabContentAtTwitter, profileSlider: injectProfileSliderAtTwitter, - enhancedPostRenderer: injectPostReplacerAtTwitter, pageInspector: injectPageInspectorDefault(), postInspector: injectPostInspectorAtTwitter, setupPrompt: injectSetupPromptAtTwitter, diff --git a/packages/mask/src/social-network-adaptor/twitter.com/utils/fetch.ts b/packages/mask/src/social-network-adaptor/twitter.com/utils/fetch.ts index ce6fcc543261..683903f04773 100644 --- a/packages/mask/src/social-network-adaptor/twitter.com/utils/fetch.ts +++ b/packages/mask/src/social-network-adaptor/twitter.com/utils/fetch.ts @@ -10,7 +10,7 @@ import { isTypedMessageEmpty, isTypedMessageText, TypedMessageText, -} from '@masknet/shared-base' +} from '@masknet/typed-message/base' import { collectNodeText, collectTwitterEmoji } from '../../../utils' /** diff --git a/packages/mask/src/social-network/defaults/index.ts b/packages/mask/src/social-network/defaults/index.ts index 2ef55454dbdb..78df3ed3ee6a 100644 --- a/packages/mask/src/social-network/defaults/index.ts +++ b/packages/mask/src/social-network/defaults/index.ts @@ -5,5 +5,4 @@ export * from './inject/PostInspector' export * from './state/InitFriends' export * from './state/InitProfiles' export * from './inject/PageInspector' -export * from './inject/PostReplacer' export * from './inject/StartSetupGuide' diff --git a/packages/mask/src/social-network/defaults/inject/CommentBox.tsx b/packages/mask/src/social-network/defaults/inject/CommentBox.tsx index 4a8f9893f5d8..00a4da9ec9ae 100644 --- a/packages/mask/src/social-network/defaults/inject/CommentBox.tsx +++ b/packages/mask/src/social-network/defaults/inject/CommentBox.tsx @@ -2,18 +2,17 @@ import { memo, useCallback } from 'react' import type { PostInfo } from '../../PostInfo' import { DOMProxy, MutationObserverWatcher } from '@dimensiondev/holoflows-kit' import { CommentBox, CommentBoxProps } from '../../../components/InjectedComponents/CommentBox' -import Services from '../../../extension/service' import { createReactRootShadowed } from '../../../utils/shadow-root/renderInShadowRoot' import { makeStyles } from '@masknet/theme' -import { usePostInfoDetails, usePostInfo, PostInfoProvider } from '../../../components/DataSource/usePostInfo' +import { usePostInfo, PostInfoProvider } from '../../../components/DataSource/usePostInfo' import { noop } from 'lodash-unified' import { MaskMessages } from '../../../utils/messages' import { startWatch } from '../../../utils/watcher' -import { extractTextFromTypedMessage } from '@masknet/shared-base' +import type { PostContext } from '@masknet/plugin-infra/src' const defaultOnPasteToCommentBox = async ( encryptedComment: string, - _current: PostInfo, + _postContext: PostContext, _realCurrent: HTMLElement | null, ) => { MaskMessages.events.autoPasteFailed.sendToLocal({ text: encryptedComment }) @@ -28,23 +27,20 @@ export const injectCommentBoxDefaultFactory = function ( mountPointCallback?: (node: DOMProxy) => void, ) { const CommentBoxUI = memo(function CommentBoxUI({ dom }: { dom: HTMLElement | null }) { - const info = usePostInfo() - const payload = usePostInfoDetails.containingMaskPayload() - const postContent = usePostInfoDetails.rawMessagePiped() + const info = usePostInfo()! + // TODO: + const hasMask = true // usePostInfoDetails.containsMaskPayload() + const { encryptPostComment } = info const { classes } = useCustomStyles() - const iv = usePostInfoDetails.iv() const props = additionPropsToCommentBox(classes) const onCallback = useCallback( async (content) => { - const postIV = iv || payload.unwrap().iv - const decryptedText = extractTextFromTypedMessage(postContent).unwrap() - const encryptedComment = await Services.Crypto.encryptComment(postIV, decryptedText, content) - onPasteToCommentBox(encryptedComment, info!, dom).catch(console.error) + const encryptedComment = await encryptPostComment(content) + onPasteToCommentBox(encryptedComment, info, dom).catch(console.error) }, - [payload, postContent, info, dom, iv], + [encryptPostComment, info, dom], ) - - if (!postContent.items.length) return null + if (!hasMask) return null return }) return (signal: AbortSignal, current: PostInfo) => { diff --git a/packages/mask/src/social-network/defaults/inject/PostInspector.tsx b/packages/mask/src/social-network/defaults/inject/PostInspector.tsx index 4688fa46a6fc..f8fb1ef23802 100644 --- a/packages/mask/src/social-network/defaults/inject/PostInspector.tsx +++ b/packages/mask/src/social-network/defaults/inject/PostInspector.tsx @@ -1,39 +1,21 @@ -import { memo } from 'react' -import type { DOMProxy } from '@dimensiondev/holoflows-kit' import type { PostInfo } from '../../PostInfo' import { createReactRootShadowed } from '../../../utils/shadow-root/renderInShadowRoot' -import { PostInspector, PostInspectorProps } from '../../../components/InjectedComponents/PostInspector' -import { makeStyles } from '@masknet/theme' +import { PostInspector } from '../../../components/InjectedComponents/PostInspector' import { PostInfoProvider } from '../../../components/DataSource/usePostInfo' -import { noop } from 'lodash-unified' - -export function injectPostInspectorDefault( - config: InjectPostInspectorDefaultConfig = {}, - additionalPropsToPostInspector: (classes: Record) => Partial = () => ({}), - useCustomStyles: (props?: any) => { classes: Record } = makeStyles()({}) as any, -) { - const PostInspectorDefault = memo(function PostInspectorDefault(props: { - onDecrypted: PostInspectorProps['onDecrypted'] - zipPost: PostInspectorProps['needZip'] - }) { - const { onDecrypted, zipPost } = props - const { classes } = useCustomStyles() - const additionalProps = additionalPropsToPostInspector(classes) - return - }) +import type { DOMProxy } from '@dimensiondev/holoflows-kit' +import { PostReplacer } from '../../../components/InjectedComponents/PostReplacer' - const { zipPost, injectionPoint } = config - const zipPostF = zipPost || noop +export function injectPostInspectorDefault(config: InjectPostInspectorDefaultConfig = {}) { + const { injectionPoint } = config return function injectPostInspector(current: PostInfo, signal: AbortSignal) { const jsx = ( - { - current.rawMessagePiped.value = typed - }} - zipPost={() => zipPostF(current.rootElement)} + config.zip?.(current.rootElement)} + unzip={() => config.unzip?.(current.rootElement)} {...current} /> + ) const root = createReactRootShadowed(injectionPoint?.(current) ?? current.rootElement.afterShadow, { @@ -46,6 +28,7 @@ export function injectPostInspectorDefault( } interface InjectPostInspectorDefaultConfig { - zipPost?(node: DOMProxy): void injectionPoint?: (postInfo: PostInfo) => ShadowRoot + zip?(node: DOMProxy): void + unzip?(node: DOMProxy): void } diff --git a/packages/mask/src/social-network/defaults/inject/PostReplacer.tsx b/packages/mask/src/social-network/defaults/inject/PostReplacer.tsx deleted file mode 100644 index e8473bf07057..000000000000 --- a/packages/mask/src/social-network/defaults/inject/PostReplacer.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { memo } from 'react' -import { createReactRootShadowed } from '../../../utils/shadow-root/renderInShadowRoot' -import { PostInfoProvider } from '../../../components/DataSource/usePostInfo' -import { PostReplacer, PostReplacerProps } from '../../../components/InjectedComponents/PostReplacer' -import type { PostInfo } from '../../PostInfo' -import { makeStyles } from '@masknet/theme' -import type { DOMProxy } from '@dimensiondev/holoflows-kit' -import { noop } from 'lodash-unified' - -export function injectPostReplacer( - config: injectPostReplacerConfig = {}, - additionalPropsToPostReplacer: (classes: Record) => Partial = () => ({}), - useCustomStyles: (props?: any) => { classes: Record } = makeStyles()({}) as any, -) { - const PostReplacerDefault = memo(function PostReplacerDefault(props: { - zipPost: PostReplacerProps['zip'] - unZipPost: PostReplacerProps['unzip'] - }) { - const { classes } = useCustomStyles() - const additionalProps = additionalPropsToPostReplacer(classes) - return - }) - - const { zipPost, unzipPost } = config - const zipPostF = zipPost || noop - const unzipPostF = unzipPost || noop - return function injectPostReplacer(current: PostInfo, signal: AbortSignal) { - signal.addEventListener('abort', unzipPostF) - createReactRootShadowed(current.rootElement.afterShadow, { - key: 'post-replacer', - signal, - }).render( - - zipPostF(current.rootElement)} - unZipPost={() => unzipPostF(current.rootElement)} - {...current} - /> - , - ) - } -} - -interface injectPostReplacerConfig { - zipPost?(node: DOMProxy): void - unzipPost?(node: DOMProxy): void -} diff --git a/packages/mask/src/social-network/defaults/maskPayload.ts b/packages/mask/src/social-network/defaults/maskPayload.ts new file mode 100644 index 000000000000..1a75410a617d --- /dev/null +++ b/packages/mask/src/social-network/defaults/maskPayload.ts @@ -0,0 +1,83 @@ +import { + createMaskPayloadTransform, + makeTypedMessageEmpty, + makeTypedMessageMaskPayload, + makeTypedMessagePromise, + makeTypedMessageText, + TransformationContext, + TypedMessage, +} from '@masknet/typed-message/base' +import { TypedMessageTransformers, Order } from '../../../shared-ui/TypedMessageRender/transformer' +import { DecryptProgress, DecryptProgressKind, SocialNetworkEnum } from '@masknet/encryption' +import { ServicesWithProgress } from '../../extension/service' +import { ProfileIdentifier } from '@masknet/shared-base' +import type { DecryptionInfo } from '../../../background/services/crypto' + +export function registerMaskPayloadTransformer(network: SocialNetworkEnum) { + return TypedMessageTransformers.addTransformer( + createMaskPayloadTransform({ + removePrefixText: [], + removePostfixText: [], + transformText(text, context) { + const { authorHint, currentProfile, postURL } = context + const generator = ServicesWithProgress.decryptionWithSocialNetworkDecoding( + { type: 'text', text }, + { + currentSocialNetwork: network, + authorHint: authorHint ? new ProfileIdentifier(authorHint.network, authorHint.userId) : null, + currentProfile: currentProfile + ? new ProfileIdentifier(currentProfile.network, currentProfile.userId) + : null, + postURL, + }, + ) + const f = iter(generator, context) + return makeTypedMessagePromise(generator.next().then(f)) + }, + transformImage(image, context) { + // We return Empty for early returns because we don't hide replace images on SNS and we don't want duplicated images. + if (typeof image.image !== 'string') return makeTypedMessageEmpty() + if (!context.authorHint) return makeTypedMessageEmpty() + + const { authorHint, currentProfile, postURL } = context + // Note: image decryption requires authorHint. If this field is missing, we shall early return. + const generator = ServicesWithProgress.decryptionWithSocialNetworkDecoding( + { type: 'image-url', image: image.image }, + { + currentSocialNetwork: network, + authorHint: new ProfileIdentifier(authorHint.network, authorHint.userId), + currentProfile: currentProfile + ? new ProfileIdentifier(currentProfile.network, currentProfile.userId) + : null, + postURL, + }, + ) + const f = iter(generator, context) + return makeTypedMessagePromise(generator.next().then(f)) + }, + }), + Order.MaskPayload, + ) +} + +function iter(gen: AsyncGenerator, context: TransformationContext) { + return function iter_inner(result: IteratorResult): TypedMessage { + // should not happen. + if (result.done) { + console.warn('Unreachable case') + return makeTypedMessageEmpty() + } + + const progress = result.value + if (progress.type === DecryptProgressKind.Info) { + context.reportDecryptedInfo?.(progress.iv, progress.claimedAuthor, progress.publicShared) + return makeTypedMessagePromise(gen.next().then(iter_inner), makeTypedMessageText('[Mask]')) + } else if (progress.type === DecryptProgressKind.Success) { + return makeTypedMessageMaskPayload(progress.content) + } else if (progress.type === DecryptProgressKind.Error) { + return makeTypedMessageText(String(progress.message)) + } + + return makeTypedMessagePromise(gen.next().then(iter_inner)) + } +} diff --git a/packages/mask/src/social-network/types.ts b/packages/mask/src/social-network/types.ts index 8fa395669d45..865f037b3ada 100644 --- a/packages/mask/src/social-network/types.ts +++ b/packages/mask/src/social-network/types.ts @@ -6,27 +6,19 @@ import type { ProfileIdentifier, ReadonlyIdentifierMap, ObservableWeakMap, - TypedMessage, } from '@masknet/shared-base' +import type { TypedMessage } from '@masknet/typed-message/base' import type { PaletteMode, Theme } from '@mui/material' import type { InjectedDialogClassKey, InjectedDialogProps } from '../components/shared/InjectedDialog' import type { Profile } from '../database' import type { PostInfo } from './PostInfo' -import type { GrayscaleAlgorithm } from '@masknet/encryption' +import type { GrayscaleAlgorithm, SocialNetworkEnum } from '@masknet/encryption' import type { createSNSAdaptorSpecializedPostContext } from './utils/create-post-context' import type { Subscription } from 'use-subscription' type ClassNameMap = { [P in ClassKey]: string } // Don't define values in namespaces export namespace SocialNetwork { - export interface PayloadEncoding { - encoder(text: string): string - /** - * the result is candidates - */ - decoder(text: string): string[] - } - export interface Utils { /** @returns the homepage url. e.g.: https://twitter.com/ */ getHomePage?(): string @@ -36,10 +28,6 @@ export namespace SocialNetwork { getPostURL?(post: PostIdentifier): URL | null /** Is this username valid in this network */ isValidUsername?(username: string): boolean - /** How to encode/decode public keys when it is put in the bio. */ - publicKeyEncoding?: PayloadEncoding - /** How to encode/decode text payload (e.g. make it into a link so it will be shortened by SNS). */ - textPayloadPostProcessor?: PayloadEncoding /** Given a text, return a URL that will allow user to share this text */ getShareLinkURL?(text: string): URL createPostContext: ReturnType @@ -54,7 +42,6 @@ export namespace SocialNetwork { * !!! THIS SHOULD NOT BE USED TO CONSTRUCT A NEW ProfileIdentifier !!! */ networkIdentifier: string - name: string /** * This field _will_ be overwritten by SocialNetworkUI.permissions */ @@ -63,6 +50,7 @@ export namespace SocialNetwork { shouldActivate(location: Location | URL): boolean /** This provider is not ready for production, Mask will not use it in production */ notReadyForProduction?: boolean + network: SocialNetworkEnum } } export namespace SocialNetworkUI { @@ -111,7 +99,6 @@ export namespace SocialNetworkUI { /** Inject the UI that used to open the composition UI */ newPostComposition?: NewPostComposition commentComposition?: CommentComposition - enhancedPostRenderer?(signal: AbortSignal, current: PostInfo): void /** Display the additional content (decrypted, plugin, ...) below the post */ postInspector?(signal: AbortSignal, current: PostInfo): void /** Inject a tool box that displayed in the navigation bar of the SNS */ @@ -287,7 +274,6 @@ export namespace SocialNetworkUI { export namespace Configuration { export interface Define { steganography?: SteganographyConfig - setupWizard?: SetupWizardConfig } export interface SteganographyConfig { grayscaleAlgorithm?: GrayscaleAlgorithm @@ -297,9 +283,6 @@ export namespace SocialNetworkUI { */ password?(): string } - export interface SetupWizardConfig { - disableSayHello?: boolean - } } } diff --git a/packages/mask/src/social-network/ui.ts b/packages/mask/src/social-network/ui.ts index 6b8ced86016c..08c916772f30 100644 --- a/packages/mask/src/social-network/ui.ts +++ b/packages/mask/src/social-network/ui.ts @@ -21,6 +21,8 @@ import { getCurrentSNSNetwork } from '../social-network-adaptor/utils' import { createPluginHost } from '../plugin-infra/host' import { definedSocialNetworkUIs } from './define' import { setupShadowRootPortal, MaskMessages } from '../utils' +import { registerMaskPayloadTransformer } from './defaults/maskPayload' +import { SocialNetworkEnum } from '@masknet/encryption' const definedSocialNetworkUIsResolved = new Map() export let activatedSocialNetworkUI: SocialNetworkUI.Definition = { @@ -37,11 +39,11 @@ export let activatedSocialNetworkUI: SocialNetworkUI.Definition = { }, injection: {}, networkIdentifier: 'localhost', - name: '', shouldActivate: () => false, utils: { createPostContext: null! }, notReadyForProduction: true, declarativePermissions: { origins: [] }, + network: SocialNetworkEnum.Unknown, } export let globalUIState: Readonly = {} as any @@ -69,6 +71,16 @@ export async function activateSocialNetworkUIInner(ui_deferred: SocialNetworkUI. i18nOverwrite() const state = await ui.init(signal) + + { + let f = registerMaskPayloadTransformer(ui.network) + import.meta.webpackHot && + import.meta.webpackHot.accept('./defaults/maskPayload.ts', () => { + f() + f = registerMaskPayloadTransformer(ui.network) + }) + signal.addEventListener('abort', () => f()) + } globalUIState = { ...state, ...managedStateCreator() } ui.customization.paletteMode?.start(signal) @@ -154,7 +166,6 @@ export async function activateSocialNetworkUIInner(ui_deferred: SocialNetworkUI. signal.addEventListener('abort', () => abort.abort()) abortSignals.set(key, abort) const { signal: postSignal } = abort - ui.injection.enhancedPostRenderer?.(postSignal, value) ui.injection.postInspector?.(postSignal, value) ui.injection.commentComposition?.compositionBox(postSignal, value) ui.injection.commentComposition?.commentInspector(postSignal, value) diff --git a/packages/mask/src/social-network/utils/create-post-context.ts b/packages/mask/src/social-network/utils/create-post-context.ts index 989b4f1da134..6fffe2f1b8ca 100644 --- a/packages/mask/src/social-network/utils/create-post-context.ts +++ b/packages/mask/src/social-network/utils/create-post-context.ts @@ -2,24 +2,26 @@ import { ValueRef } from '@dimensiondev/holoflows-kit' import type { PostContext, PostContextAuthor, PostContextCreation, PostContextSNSActions } from '@masknet/plugin-infra' import { ALL_EVENTS, - extractTextFromTypedMessage, - isTypedMessageEqual, - makeTypedMessageTupleFromList, ObservableMap, ObservableSet, parseURL, - Payload, PostIdentifier, ProfileIdentifier, - TypedMessage, - TypedMessageTuple, SubscriptionFromValueRef, SubscriptionDebug as debug, mapSubscription, } from '@masknet/shared-base' -import { Err, Result } from 'ts-results' +import { + FlattenTypedMessage, + extractTextFromTypedMessage, + collectTypedMessagePromise, + type TypedMessageTuple, + type TypedMessage, + makeTypedMessageTupleFromList, +} from '@masknet/typed-message/base' import type { Subscription } from 'use-subscription' import { activatedSocialNetworkUI } from '../' +import { FACEBOOK_ID } from '../../social-network-adaptor/facebook.com/base' import { resolveFacebookLink } from '../../social-network-adaptor/facebook.com/utils/resolveFacebookLink' export function createSNSAdaptorSpecializedPostContext(create: PostContextSNSActions) { @@ -27,60 +29,44 @@ export function createSNSAdaptorSpecializedPostContext(create: PostContextSNSAct const cancel: (Function | undefined)[] = [] opt.signal?.addEventListener('abort', () => cancel.forEach((fn) => fn?.())) - // #region Post text content - const postContent = new ValueRef(extractText()) - cancel.push(opt.rawMessage.subscribe(() => (postContent.value = extractText()))) - function extractText() { - return extractTextFromTypedMessage(opt.rawMessage.getCurrentValue()).unwrapOr('') - } - // #endregion - // #region Mentioned links const links = new ObservableSet() - cancel.push( - postContent.addListener((post) => { - links.clear() - parseURL(post).forEach((link) => - links.add(resolveFacebookLink(link, activatedSocialNetworkUI.networkIdentifier)), - ) - opt.postMentionedLinksProvider - ?.getCurrentValue() - .forEach((link) => links.add(resolveFacebookLink(link, activatedSocialNetworkUI.networkIdentifier))) - }), - ) - cancel.push( - opt.postMentionedLinksProvider?.subscribe(() => { - // Not clean old links cause post content not changed - opt.postMentionedLinksProvider - ?.getCurrentValue() - .forEach((link) => links.add(resolveFacebookLink(link, activatedSocialNetworkUI.networkIdentifier))) - }), - ) - const linksSubscribe: Subscription = debug({ - getCurrentValue: () => [...links], - subscribe: (sub) => links.event.on(ALL_EVENTS, sub), - }) - // #endregion + { + const isFB = activatedSocialNetworkUI.networkIdentifier === FACEBOOK_ID - // #region Parse payload - const postPayload = new ValueRef>(Err(new Error('Empty'))) - parsePayload() - cancel.push(postContent.addListener(parsePayload)) - cancel.push(linksSubscribe.subscribe(parsePayload)) - function parsePayload() { - // TODO: Also parse for payload in the image. - let lastResult: Result = Err(new Error('No candidate')) - for (const each of (create.payloadDecoder || ((x) => [x]))( - postContent.value + linksSubscribe.getCurrentValue().join('\n'), - )) { - lastResult = create.payloadParser(each) - if (lastResult.ok) { - postPayload.value = lastResult - return + let controller = new AbortController() + function fillLinks() { + const signal = controller.signal + function addLink(x: string) { + if (signal.aborted) return + if (isFB) links.add(resolveFacebookLink(x)) + else links.add(x) } + // Instant values + const message = FlattenTypedMessage(opt.rawMessage.getCurrentValue(), {}) + const text = extractTextFromTypedMessage(message).unwrapOr('') + const link = parseURL(text).concat(opt.postMentionedLinksProvider?.getCurrentValue() || []) + link.forEach(addLink) + + // Deferred values + collectTypedMessagePromise(message).forEach((x) => + x.then(extractTextFromTypedMessage).then((x) => x.map(parseURL).map((val) => val.forEach(addLink))), + ) + } + const retry = () => { + controller.abort() + controller = new AbortController() + links.clear() + fillLinks() } - if (postPayload.value.err) postPayload.value = lastResult + fillLinks() + cancel.push(opt.rawMessage.subscribe(retry)) + cancel.push(opt.postMentionedLinksProvider?.subscribe(retry)) } + const mentionedLinks: Subscription = debug({ + getCurrentValue: () => [...links], + subscribe: (sub) => links.event.on(ALL_EVENTS, sub), + }) // #endregion const author: PostContextAuthor = { avatarURL: opt.avatarURL, @@ -88,7 +74,6 @@ export function createSNSAdaptorSpecializedPostContext(create: PostContextSNSAct author: opt.author, snsID: opt.snsID, } - const transformedPostContent = new ValueRef(makeTypedMessageTupleFromList(), isTypedMessageEqual) const postIdentifier = debug({ getCurrentValue: () => { const by = opt.author.getCurrentValue() @@ -102,8 +87,19 @@ export function createSNSAdaptorSpecializedPostContext(create: PostContextSNSAct return () => void [a(), b()] }, }) + const url = debug({ + getCurrentValue: () => { + const id = postIdentifier.getCurrentValue() + if (id) return create.getURLFromPostIdentifier?.(id) || null + return null + }, + subscribe: (sub) => postIdentifier.subscribe(sub), + }) return { - ...author, + author: author.author, + avatarURL: author.avatarURL, + nickname: author.nickname, + snsID: author.snsID, get rootNode() { return opt.rootElement.realCurrent @@ -114,37 +110,18 @@ export function createSNSAdaptorSpecializedPostContext(create: PostContextSNSAct comment: opt.comments, identifier: postIdentifier, - url: debug({ - getCurrentValue: () => { - const id = postIdentifier.getCurrentValue() - if (id) return create.getURLFromPostIdentifier?.(id) || null - return null - }, - subscribe: (sub) => postIdentifier.subscribe(sub), - }), + url, - mentionedLinks: linksSubscribe, - postMetadataImages: - opt.postImagesProvider || - debug({ - getCurrentValue: () => [], - subscribe: () => () => {}, - }), + mentionedLinks: mentionedLinks, rawMessage: opt.rawMessage, - rawMessagePiped: transformedPostContent, - postContent: SubscriptionFromValueRef(postContent), - containingMaskPayload: SubscriptionFromValueRef(postPayload), - decryptedPayloadForImage: new ValueRef(null), - iv: new ValueRef(null), - publicShared: debug({ - getCurrentValue: () => - postPayload.value - .map((val) => val.version === -38 && val.sharedPublic) - .unwrapOr(undefined), - subscribe: (sub) => postPayload.addListener(sub), - }), + async decryptPostComment() { + throw new Error('TODO') + }, + async encryptPostComment() { + throw new Error('TODO') + }, } } } @@ -168,10 +145,6 @@ export function createRefsForCreatePostContext() { author: SubscriptionFromValueRef(postBy), snsID: SubscriptionFromValueRef(postID), rawMessage: SubscriptionFromValueRef(postMessage), - postImagesProvider: debug({ - getCurrentValue: () => [...postMetadataImages], - subscribe: (sub) => postMetadataImages.event.on(ALL_EVENTS, sub), - }), postMentionedLinksProvider: debug({ getCurrentValue: () => [...postMetadataMentionedLinks.values()], subscribe: (sub) => postMetadataMentionedLinks.event.on(ALL_EVENTS, sub), diff --git a/packages/mask/src/social-network/utils/text-payload-ui.ts b/packages/mask/src/social-network/utils/text-payload-ui.ts deleted file mode 100644 index bcfc6cb4e605..000000000000 --- a/packages/mask/src/social-network/utils/text-payload-ui.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { activatedSocialNetworkUI } from '../ui' -export function encodePublicKeyUI(x: string): string { - const f = activatedSocialNetworkUI.utils.publicKeyEncoding?.encoder - if (f) return f(x) || x - return x -} -export function decodePublicKeyUI(x: string): string[] { - const f = activatedSocialNetworkUI.utils.publicKeyEncoding?.decoder - if (f) return f(x).concat(x) - return [x] -} -export function encodeTextPayloadUI(x: string): string { - const f = activatedSocialNetworkUI.utils.textPayloadPostProcessor?.encoder - if (f) return f(x) || x - return x -} -export function decodeTextPayloadUI(x: string): string[] { - const f = activatedSocialNetworkUI.utils.textPayloadPostProcessor?.decoder - if (f) return f(x).concat(x) - return [x] -} diff --git a/packages/mask/src/social-network/utils/text-payload-worker.ts b/packages/mask/src/social-network/utils/text-payload-worker.ts deleted file mode 100644 index c7f1c0ac3209..000000000000 --- a/packages/mask/src/social-network/utils/text-payload-worker.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { getNetworkWorker, NetworkWorkerQuery } from '../worker' -export async function encodePublicKeyWorker(query: NetworkWorkerQuery): Promise<(text: string) => string> { - const f = (await getNetworkWorker(query)).utils.publicKeyEncoding?.encoder - return (x) => f?.(x) || x -} -export async function decodePublicKeyWorker(query: NetworkWorkerQuery): Promise<(text: string) => string[]> { - const f = (await getNetworkWorker(query)).utils.publicKeyEncoding?.decoder - if (f) return (x) => f(x).concat(x) - return (x) => [x] -} -export async function encodeTextPayloadWorker(query: NetworkWorkerQuery): Promise<(text: string) => string> { - const f = (await getNetworkWorker(query)).utils.textPayloadPostProcessor?.encoder - return (x) => f?.(x) || x -} -export async function decodeTextPayloadWorker(query: NetworkWorkerQuery): Promise<(text: string) => string[]> { - const f = (await getNetworkWorker(query)).utils.textPayloadPostProcessor?.decoder - if (f) return (x) => f(x).concat(x) - return (x) => [x] -} diff --git a/packages/mask/src/tsconfig.json b/packages/mask/src/tsconfig.json index 7bdabfffe9d5..05903f5c1369 100644 --- a/packages/mask/src/tsconfig.json +++ b/packages/mask/src/tsconfig.json @@ -21,6 +21,8 @@ { "path": "../../web3-shared/flow" }, { "path": "../../web3-providers" }, { "path": "../../theme" }, + { "path": "../../typed-message/base" }, + { "path": "../../typed-message/dom" }, { "path": "../../icons" }, { "path": "../../plugin-infra" }, { "path": "../../plugins/Wallet" }, diff --git a/packages/mask/src/utils/constants.ts b/packages/mask/src/utils/constants.ts deleted file mode 100644 index 090383f89115..000000000000 --- a/packages/mask/src/utils/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export enum DecryptFailedReason { - MyCryptoKeyNotFound = 'MyCryptoKeyNotFound', -} diff --git a/packages/mask/src/utils/debug/ui.ts b/packages/mask/src/utils/debug/ui.ts index e3b33c58b8ab..3514073ada6e 100644 --- a/packages/mask/src/utils/debug/ui.ts +++ b/packages/mask/src/utils/debug/ui.ts @@ -1,9 +1,7 @@ import { LiveSelector, Watcher, DOMProxy } from '@dimensiondev/holoflows-kit' -import { enhanceTypedMessageDebugger } from '../../protocols/typed-message/debugger' if (typeof window === 'object') { LiveSelector.enhanceDebugger() Watcher.enhanceDebugger() DOMProxy.enhanceDebugger() - enhanceTypedMessageDebugger() } diff --git a/packages/mask/src/utils/hooks/useMenu.tsx b/packages/mask/src/utils/hooks/useMenu.tsx index be8311fb72c1..a6ac08f1acf8 100644 --- a/packages/mask/src/utils/hooks/useMenu.tsx +++ b/packages/mask/src/utils/hooks/useMenu.tsx @@ -1,7 +1,7 @@ import { SyntheticEvent, cloneElement, isValidElement, useCallback, useState, createElement } from 'react' import { Menu, PopoverOrigin } from '@mui/material' import type { MenuListProps, PaperProps } from '@mui/material' -import { ShadowRootMenu } from '../shadow-root/ShadowRootComponents' +import { ShadowRootMenu } from '../../../shared-ui/shadow-root/ShadowRootComponents' import { useUpdate } from 'react-use' interface MenuProps { diff --git a/packages/mask/src/utils/index.ts b/packages/mask/src/utils/index.ts index 8336323e4d8a..f208007c1320 100644 --- a/packages/mask/src/utils/index.ts +++ b/packages/mask/src/utils/index.ts @@ -5,7 +5,6 @@ export * from './shadow-root' export * from './suspends' export * from './type-transform' export * from './comparer' -export * from './constants' export * from './dom' export * from './getTextUILength' export * from './i18n-next-ui' @@ -17,3 +16,8 @@ export * from './theme' export * from './utils' export * from './watcher' export * from './collectNodeText' +export async function asyncIteratorToArray(iter: AsyncIterable): Promise { + const x: T[] = [] + for await (const y of x) x.push(y) + return x +} diff --git a/packages/mask/src/utils/shadow-root/index.ts b/packages/mask/src/utils/shadow-root/index.ts index bfe12b0094c0..f481b15148df 100644 --- a/packages/mask/src/utils/shadow-root/index.ts +++ b/packages/mask/src/utils/shadow-root/index.ts @@ -1,5 +1,5 @@ export * from './renderInShadowRoot' -export * from './ShadowRootComponents' +export * from '../../../shared-ui/shadow-root/ShadowRootComponents' export { usePortalShadowRoot, createShadowRootForwardedComponent, diff --git a/packages/mask/src/utils/type-transform/BackupFormat/JSON/DBRecord-JSON/PostRecord.ts b/packages/mask/src/utils/type-transform/BackupFormat/JSON/DBRecord-JSON/PostRecord.ts index 73d5bc29ba73..9c6a307b65ce 100644 --- a/packages/mask/src/utils/type-transform/BackupFormat/JSON/DBRecord-JSON/PostRecord.ts +++ b/packages/mask/src/utils/type-transform/BackupFormat/JSON/DBRecord-JSON/PostRecord.ts @@ -3,8 +3,8 @@ import type { BackupJSONFileLatest } from '../latest' import type { RecipientReasonJSON } from '../version-2' import { encodeArrayBuffer, decodeArrayBuffer, unreachable } from '@dimensiondev/kit' import { encode, decode } from '@msgpack/msgpack' +import type { TypedMessage } from '@masknet/typed-message/base' import { - type TypedMessage, IdentifierMap, ECKeyIdentifier, GroupIdentifier, diff --git a/packages/mask/src/utils/type-transform/Payload.ts b/packages/mask/src/utils/type-transform/Payload.ts deleted file mode 100644 index 1042756774e7..000000000000 --- a/packages/mask/src/utils/type-transform/Payload.ts +++ /dev/null @@ -1,111 +0,0 @@ -/* eslint @dimensiondev/unicode-specific-set: ["error", { "only": "code" }] */ -import type { SocialNetwork } from '../../social-network' -import { isEnvironment, Environment } from '@dimensiondev/holoflows-kit' -import { i18n } from '../../../shared-ui/locales_legacy' -import { Result, Ok, Err } from 'ts-results' -import { decodeTextPayloadUI, encodeTextPayloadUI } from '../../social-network/utils/text-payload-ui' - -import { Identifier, Payload, PayloadAlpha38, ProfileIdentifier } from '@masknet/shared-base' - -/** - * Detect if there is version -40, -39 or -38 payload - */ -function deconstructAlpha40_Or_Alpha39_Or_Alpha38(str: string, throws = false): Payload | null { - // ? payload is 🎼2/4|ownersAESKeyEncrypted|iv|encryptedText|signature:|| - // ? payload is 🎼3/4|ownersAESKeyEncrypted|iv|encryptedText|signature:|| - // ? payload is 🎼4/4|AESKeyEncrypted|iv|encryptedText|signature|authorPublicKey?|publicShared?|authorIdentifier:|| - // ? if publicShared is true, that means AESKeyEncrypted is shared with public - // ? "1" treated as true, "0" or not defined treated as false - // ? authorIdentifier is encoded as `${network}/${id}` - const isVersion40 = str.includes('\u{1F3BC}2/4') - const isVersion39 = str.includes('\u{1F3BC}3/4') - const isVersion38 = str.includes('\u{1F3BC}4/4') - str = str.replace('\u{1F3BC}2/4', '\u{1F3BC}3/4') - str = str.replace('\u{1F3BC}3/4', '\u{1F3BC}4/4') - const [_, payloadStart] = str.split('\u{1F3BC}4/4|') - if (!payloadStart) - if (throws) throw new Error(i18n.t('payload_not_found')) - else return null - const [payload, rest] = payloadStart.split(':||') - if (rest === undefined) - if (throws) throw new Error(i18n.t('payload_incomplete')) - else return null - const [AESKeyEncrypted, iv, encryptedText, signature, ...optional] = payload.split('|') - const [authorPublicKey, publicShared, authorID, ...extra] = optional - if (!(AESKeyEncrypted && iv && encryptedText)) - if (throws) throw new Error(i18n.t('payload_bad')) - else return null - if (extra.length) console.warn('Found extra payload', extra) - if (isVersion38) { - if (!signature) throw new Error(i18n.t('payload_bad')) - return { - version: -38, - AESKeyEncrypted, - iv, - encryptedText, - signature, - authorPublicKey, - sharedPublic: publicShared === '1', - authorUserID: Result.wrap(() => - Identifier.fromString('person:' + atob(authorID), ProfileIdentifier).unwrap(), - ).unwrapOr(undefined), - } - } - return { - ownersAESKeyEncrypted: AESKeyEncrypted, - iv, - encryptedText, - signature, - version: isVersion39 ? -39 : -40, - } -} - -function deconstructAlpha41(str: string, throws = false): null | never { - // 🎼1/4|ownersAESKeyEncrypted|iv|encryptedText|signature:|| - if (str.includes('\u{1F3BC}1/4') && str.includes(':||')) - if (throws) throw new Error(i18n.t('payload_throw_in_alpha41')) - else return null - return null -} - -const versions = new Set([deconstructAlpha40_Or_Alpha39_Or_Alpha38, deconstructAlpha41]) - -/** - * @type Decoder - defines decoder. if null, auto select decoder. - */ -type Decoder = SocialNetwork.PayloadEncoding['decoder'] | null -type Encoder = SocialNetwork.PayloadEncoding['encoder'] - -export function deconstructPayload(str: string, networkDecoder?: Decoder): Result { - if (!networkDecoder) { - networkDecoder = isEnvironment(Environment.ContentScript) ? decodeTextPayloadUI : (x) => [x] - } - - for (const versionDecoder of versions) { - const results = networkDecoder(str) - for (const result of results) { - if (!result) continue - const payload = versionDecoder(result, false) - if (payload) return Ok(payload) - } - } - if (str.includes('\u{1F3BC}') && str.includes(':||')) return Err(new TypeError(i18n.t('service_unknown_payload'))) - return Err(new TypeError(i18n.t('payload_not_found'))) -} - -export function constructAlpha38(data: PayloadAlpha38, encoder?: Encoder) { - if (!encoder) { - encoder = isEnvironment(Environment.ContentScript) ? encodeTextPayloadUI : (x) => x - } - const userID = data.authorUserID?.toText().replace('person:', '') || '' - const fields = [ - data.AESKeyEncrypted, - data.iv, - data.encryptedText, - data.signature, - data.authorPublicKey, - data.sharedPublic ? '1' : '0', - userID.includes('|') ? undefined : btoa(userID), - ] - return encoder(`\u{1F3BC}4/4|${fields.join('|')}:||`) -} diff --git a/packages/mask/src/utils/type-transform/asyncIteratorHelpers.ts b/packages/mask/src/utils/type-transform/asyncIteratorHelpers.ts deleted file mode 100644 index 86b302c742f3..000000000000 --- a/packages/mask/src/utils/type-transform/asyncIteratorHelpers.ts +++ /dev/null @@ -1,63 +0,0 @@ -export async function* asyncIteratorWithResult( - iter: AsyncIterator, - callback?: (promise: Promise>) => void, -) { - let yielded: IteratorResult - do { - const p = iter.next() - callback?.(p) - yielded = await p - yield yielded - } while (yielded.done === false) - return -} - -export function memorizeAsyncGenerator( - f: (...args: Args) => AsyncGenerator, - getKey: (...args: Args) => string, - expireAfter: number, -): typeof f { - type Iter = AsyncGenerator - type IterResult = Promise> - const iterCache = new Map() - const progressCache = new WeakMap() - return async function* memorizedAsyncGenerator(...args: Args) { - const key = getKey(...args) - const iter = iterCache.get(key) ?? f(...args) - iterCache.set(key, iter) - const process = progressCache.get(iter) - if (!process) { - setTimeout(() => iterCache.delete(key), expireAfter) - const arr: IterResult[] = [] - progressCache.set(iter, arr) - try { - for await (const _ of asyncIteratorWithResult(iter, (x) => arr.push(x))) { - if (_.done) return _.value - yield _.value - } - } catch { - iterCache.delete(key) - } - } else { - let index = 0 - while (index < process.length) { - const p = await process[index] - if (p.done) return p.value - yield p.value - index += 1 - } - } - // cache not working - for await (const _ of asyncIteratorWithResult(f(...args))) { - if (_.done) return _.value - yield _.value - } - throw new Error('Unreachable') - } -} - -export async function asyncIteratorToArray(it: AsyncIterable) { - const arr: T[] = [] - for await (const x of it) arr.push(x) - return arr -} diff --git a/packages/mask/src/utils/type-transform/index.ts b/packages/mask/src/utils/type-transform/index.ts index f19d98fa2759..8a50dc9c7bdc 100644 --- a/packages/mask/src/utils/type-transform/index.ts +++ b/packages/mask/src/utils/type-transform/index.ts @@ -1,6 +1,4 @@ -export * from './asyncIteratorHelpers' export * from './BackupFile' export * from './BackupFormat' export * from './CryptoKey-JsonWebKey' -export * from './Payload' export * from './SECP256k1-ETH' diff --git a/packages/plugin-infra/package.json b/packages/plugin-infra/package.json index 3489a4fb2d3c..680708cc6de7 100644 --- a/packages/plugin-infra/package.json +++ b/packages/plugin-infra/package.json @@ -7,9 +7,11 @@ "scripts": {}, "dependencies": { "@dimensiondev/holoflows-kit": "^0.9.0-20210902104757-7c3d0d0", + "@masknet/encryption": "workspace:^*", "@masknet/shared": "workspace:*", "@masknet/shared-base": "workspace:*", "@masknet/theme": "workspace:*", + "@masknet/typed-message": "workspace:*", "@masknet/web3-shared-base": "workspace:*", "@servie/events": "^3.0.0", "@types/use-subscription": "^1.0.0", diff --git a/packages/plugin-infra/src/PostContext.ts b/packages/plugin-infra/src/PostContext.ts index 2ddf141cb8d2..a6e5a8ddea5b 100644 --- a/packages/plugin-infra/src/PostContext.ts +++ b/packages/plugin-infra/src/PostContext.ts @@ -1,25 +1,14 @@ import { useObservableValues, useValueRef } from '@masknet/shared' -import { - ObservableMap, - ObservableSet, - type Payload, - type PostIdentifier, - type ProfileIdentifier, - type TypedMessageTuple, -} from '@masknet/shared-base' +import { ObservableMap, ObservableSet, type PostIdentifier, type ProfileIdentifier } from '@masknet/shared-base' +import type { TypedMessage } from '@masknet/typed-message/base' import { ValueRef, LiveSelector, DOMProxy } from '@dimensiondev/holoflows-kit' -import type { Result } from 'ts-results' import { Context, createContext, createElement, memo, useContext } from 'react' import { Subscription, useSubscription } from 'use-subscription' +import type { SocialNetworkEnum } from '@masknet/encryption' export interface PostContextSNSActions { - /** Parse payload into Payload */ - payloadParser(raw: string): Result - /** - * It will run before parser. - * @returns a list of candidates of payload string. - */ - payloadDecoder?(postContent: string): string[] getURLFromPostIdentifier?(post: PostIdentifier): URL | null + /** This used for encode/decode */ + socialNetwork: SocialNetworkEnum } export interface PostContextAuthor { readonly nickname: Subscription @@ -42,12 +31,10 @@ export interface PostContextCreation extends PostContextAuthor { * You don't need to provide this to resolve links in `PostContext.postContent`. */ readonly postMentionedLinksProvider?: Subscription - /** @deprecated It should parse image into rawMessage */ - readonly postImagesProvider?: Subscription /** * The raw TypedMessage that the SNS gives. */ - readonly rawMessage: Subscription + readonly rawMessage: Subscription readonly signal?: AbortSignal } export interface PostContext extends PostContextAuthor { @@ -63,26 +50,15 @@ export interface PostContext extends PostContextAuthor { readonly url: Subscription // Meta readonly mentionedLinks: Subscription - /** @deprecated It should appears in rawMessage */ - readonly postMetadataImages: Subscription // #endregion // #region Raw post content (not decrypted) - readonly rawMessage: Subscription - // TODO: should be a Subscription - readonly rawMessagePiped: ValueRef - /** @deprecated Use postMessage or transformedPostContent (depends on your usage) instead */ - readonly postContent: Subscription + readonly rawMessage: Subscription // #endregion - // #region Post payload discovered in the rawMessage - readonly containingMaskPayload: Subscription> - /** @deprecated Use postPayload instead */ - readonly decryptedPayloadForImage: ValueRef - // TODO: should be a Subscription - readonly iv: ValueRef - /** - * undefined => payload not found - */ - readonly publicShared: Subscription + // #region Information revealed in the Mask Payload + // TODO: + // readonly containsMaskPayload: Subscription + encryptPostComment(comment: string): Promise + decryptPostComment(comment: string): Promise // #endregion } export type PostInfo = PostContext @@ -134,11 +110,3 @@ function isSubscription(x: any): x is Subscription { Boolean((x as Subscription).getCurrentValue && (x as Subscription).subscribe) ) } - -export function usePostInfoSharedPublic(): boolean { - const info = usePostInfoDetails.containingMaskPayload() - if (info.err) return false - const payload = info.val - if (payload.version !== -38) return false - return !!payload.sharedPublic -} diff --git a/packages/plugin-infra/src/types.ts b/packages/plugin-infra/src/types.ts index 949c384e29b6..591dbbe2cb03 100644 --- a/packages/plugin-infra/src/types.ts +++ b/packages/plugin-infra/src/types.ts @@ -1,13 +1,8 @@ /* eslint @dimensiondev/unicode-specific-set: ["error", { "only": "code" }] */ import type React from 'react' import type { Option, Result } from 'ts-results' -import type { - TypedMessage, - TypedMessageTuple, - ScopedStorage, - ProfileIdentifier, - PersonaIdentifier, -} from '@masknet/shared-base' +import type { ScopedStorage, ProfileIdentifier, PersonaIdentifier } from '@masknet/shared-base' +import type { TypedMessage, Transformer } from '@masknet/typed-message/base' import type { Emitter } from '@servie/events' import type { Web3Plugin } from './web3-types' import type { Subscription } from 'use-subscription' @@ -149,9 +144,8 @@ export namespace Plugin.Shared { /** * A pure function that convert a TypedMessage into another one */ - typedMessageTransformer?: TypedMessageTransformer + typedMessageTransformer?: Transformer } - export type TypedMessageTransformer = (message: TypedMessageTuple) => TypedMessageTuple /** The publisher of the plugin */ export interface Publisher { /** The name of the publisher */ diff --git a/packages/plugin-infra/tsconfig.json b/packages/plugin-infra/tsconfig.json index e7f2792a782a..159a47d8c079 100644 --- a/packages/plugin-infra/tsconfig.json +++ b/packages/plugin-infra/tsconfig.json @@ -10,6 +10,7 @@ { "path": "../shared/" }, { "path": "../shared-base" }, { "path": "../theme" }, + { "path": "../encryption" }, { "path": "../web3-shared/base" } ], "ts-node": { diff --git a/packages/plugins/FileService/package.json b/packages/plugins/FileService/package.json index ca963e59fb3e..eb8933b1ab05 100644 --- a/packages/plugins/FileService/package.json +++ b/packages/plugins/FileService/package.json @@ -11,6 +11,7 @@ "@masknet/shared": "workspace:*", "@masknet/shared-base": "workspace:*", "@masknet/theme": "workspace:*", + "@masknet/typed-message": "workspace:*", "@msgpack/msgpack": "^2.7.1", "arweave": "^1.10.3", "date-fns": "^2.28.0", diff --git a/packages/plugins/FileService/src/helpers.ts b/packages/plugins/FileService/src/helpers.ts index c64f928179cc..99dcb0294ac1 100644 --- a/packages/plugins/FileService/src/helpers.ts +++ b/packages/plugins/FileService/src/helpers.ts @@ -1,4 +1,4 @@ -import { type TypedMessage, createTypedMessageMetadataReader } from '@masknet/shared-base' +import { type TypedMessage, createTypedMessageMetadataReader } from '@masknet/typed-message/base' import { META_KEY_1, META_KEY_2 } from './constants' import type { FileInfo, FileInfoV1 } from './types' import schemaV1 from './schema-v1.json' diff --git a/packages/plugins/FileService/tsconfig.json b/packages/plugins/FileService/tsconfig.json index a7a6e510a964..0ed7a58a1f0f 100644 --- a/packages/plugins/FileService/tsconfig.json +++ b/packages/plugins/FileService/tsconfig.json @@ -11,6 +11,7 @@ { "path": "../../theme" }, { "path": "../../plugin-infra" }, { "path": "../../shared-base" }, + { "path": "../../typed-message/base" }, { "path": "../../shared" }, { "path": "../../icons" }, { "path": "../Wallet" } diff --git a/packages/shared-base/package.json b/packages/shared-base/package.json index d1c2ce045963..c55642eaa98d 100644 --- a/packages/shared-base/package.json +++ b/packages/shared-base/package.json @@ -6,6 +6,7 @@ "sideEffect": false, "dependencies": { "@dimensiondev/holoflows-kit": "^0.9.0-20210902104757-7c3d0d0", + "@masknet/typed-message": "workspace:*", "@msgpack/msgpack": "^2.7.1", "@mui/icons-material": "link:..\\empty", "@mui/lab": "link:..\\empty", diff --git a/packages/shared-base/src/MaskPayload/index.ts b/packages/shared-base/src/MaskPayload/index.ts deleted file mode 100644 index 9fc78a56cb13..000000000000 --- a/packages/shared-base/src/MaskPayload/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { ProfileIdentifier } from '../Identifier/type' - -export type Payload = PayloadAlpha40_Or_Alpha39 | PayloadAlpha38 -export type PayloadLatest = PayloadAlpha38 - -export interface PayloadAlpha40_Or_Alpha39 { - version: -40 | -39 - ownersAESKeyEncrypted: string - iv: string - encryptedText: string - signature?: string -} -export interface PayloadAlpha38 { - version: -38 - AESKeyEncrypted: string - iv: string - encryptedText: string - /** @deprecated but don't remove it cause it will break */ - signature: string - authorPublicKey?: string - authorUserID?: ProfileIdentifier - sharedPublic?: boolean -} - -/** - * The string part is in the front of the payload. - * The number part is used in the database. - */ -export enum PayloadVersions { - '2/4' = -40, - '3/4' = -39, - '4/4' = -38, -} diff --git a/packages/shared-base/src/Messages/Mask.ts b/packages/shared-base/src/Messages/Mask.ts index a3a96e21a0ad..2c55162b55d5 100644 --- a/packages/shared-base/src/Messages/Mask.ts +++ b/packages/shared-base/src/Messages/Mask.ts @@ -1,4 +1,4 @@ -import type { TypedMessage } from '../TypedMessage' +import type { TypedMessage } from '@masknet/typed-message/base' import type { ProfileIdentifier, PersonaIdentifier } from '../Identifier/type' import type { RelationFavor } from '../Persona/type' import type { Appearance, LanguageOptions, DataProvider } from '../../../public-api/src/web' diff --git a/packages/shared-base/src/TypedMessage/README.md b/packages/shared-base/src/TypedMessage/README.md deleted file mode 100644 index a3810ee59959..000000000000 --- a/packages/shared-base/src/TypedMessage/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# TypedMessage - -TypedMessage represents a structured message. diff --git a/packages/shared-base/src/TypedMessage/binary-encode/type.ts b/packages/shared-base/src/TypedMessage/binary-encode/type.ts deleted file mode 100644 index b50b2666bbfb..000000000000 --- a/packages/shared-base/src/TypedMessage/binary-encode/type.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum TypedMessageTypeEnum { - Tuple = 0, - Text = 1, -} diff --git a/packages/shared-base/src/TypedMessage/core.ts b/packages/shared-base/src/TypedMessage/core.ts deleted file mode 100644 index 5a576289d799..000000000000 --- a/packages/shared-base/src/TypedMessage/core.ts +++ /dev/null @@ -1,135 +0,0 @@ -import type { - SerializableTypedMessage, - SerializableTypedMessages, - NonSerializableTypedMessage, - TypedMessage, -} from './base' -import { isSerializableTypedMessage } from './utils' -import { composeEvery, composeSome, createIsType } from './utils/internal' -// Don't forget to add to isWellKnownCoreTypedMessages also -type Meta = TypedMessage['meta'] -export type WellKnownCoreTypedMessages = - | TypedMessageText - | TypedMessageImage - | TypedMessageTuple - | TypedMessageTupleSerializable - | TypedMessageUnknown - | TypedMessageEmpty - | TypedMessagePromise -// #region Text -export type TypedMessageText = TypedMessageTextV1 -/** A text message */ -export interface TypedMessageTextV1 extends SerializableTypedMessage<1> { - readonly type: 'text' - readonly content: string -} -export const isTypedMessageTextV1 = createIsType('text', 1) -export const isTypedMessageText = composeSome(isTypedMessageTextV1) as (x: TypedMessage) => x is TypedMessageText -export function makeTypedMessageText(text: string, meta?: Meta): TypedMessageTextV1 { - return { type: 'text', version: 1, serializable: true, content: text, meta } -} -// #endregion -// #region Image -export type TypedMessageImage = TypedMessageImageV1 -/** - * A single image - * TODO: it should be serializable but still not decided how to do that yet. - */ -export interface TypedMessageImageV1 extends NonSerializableTypedMessage { - readonly type: 'image' - readonly image: string | Blob - readonly width?: number - readonly height?: number -} -export const isTypedMessageImageV1 = createIsType('image') -export const isTypedMessageImage = composeSome(isTypedMessageImageV1) as (x: TypedMessage) => x is TypedMessageImage -export function makeTypedMessageImage( - image: TypedMessageImageV1['image'], - size?: { width: number; height: number }, - meta?: Meta, -): TypedMessageImageV1 { - return { type: 'image', serializable: false, image, width: size?.width, height: size?.height, meta } -} -// #endregion -// #region Tuple - -/** Multiple TypedMessages (ordered) */ -export interface TypedMessageTuple extends TypedMessage { - readonly type: 'tuple' - readonly items: T -} -export interface TypedMessageTupleSerializable< - T extends readonly SerializableTypedMessages[] = readonly SerializableTypedMessages[], -> extends SerializableTypedMessage<1>, - TypedMessageTuple { - readonly type: 'tuple' -} -export const isTypedMessageTuple = (x: TypedMessage): x is TypedMessageTuple | TypedMessageTupleSerializable => - x.type === 'tuple' -export const isTypedMessageTupleSerializable: (x: TypedMessage) => x is TypedMessageTupleSerializable = composeEvery( - isTypedMessageTuple, - isSerializableTypedMessage, -) as any -export function makeTypedMessageTuple( - items: T, - meta?: Meta, -): TypedMessageTuple { - return { type: 'tuple', items, meta } -} -export function makeTypedMessageTupleFromList( - ...args: T -): TypedMessageTuple { - return { type: 'tuple', items: args } -} -export function makeTypedMessageTupleSerializable< - T extends readonly SerializableTypedMessages[] = readonly SerializableTypedMessages[], ->(items: T, meta?: Meta): TypedMessageTupleSerializable { - return { type: 'tuple', version: 1, serializable: true, items, meta } -} -export function makeTypedMessageSerializableTupleFromList< - T extends readonly SerializableTypedMessages[] = readonly SerializableTypedMessages[], ->(...args: T): TypedMessageTupleSerializable { - return { type: 'tuple', version: 1, items: args, serializable: true } -} -// #endregion -// #region unknown and empty -export interface TypedMessageUnknown extends NonSerializableTypedMessage { - readonly type: 'unknown' - /** The unrecognized data */ - readonly raw?: unknown -} -export const isTypedMessageUnknown = createIsType('unknown') -export function makeTypedMessageUnknown(raw?: unknown, meta?: Meta): TypedMessageUnknown { - return { type: 'unknown', serializable: false, meta, raw } -} - -export interface TypedMessageEmpty extends SerializableTypedMessage<1> { - readonly type: 'empty' -} -export const isTypedMessageEmpty = createIsType('empty') -export function makeTypedMessageEmpty(meta?: Meta): TypedMessageEmpty { - return { type: 'empty', serializable: true, version: 1, meta } -} -// #endregion -// #region Promise -export interface TypedMessagePromise extends NonSerializableTypedMessage { - readonly type: 'promise' - readonly promise: Promise - readonly value?: T -} -export const isTypedMessagePromise = createIsType('promise') -export function makeTypedMessagePromise( - promise: Promise, -): TypedMessagePromise { - const x: TypedMessagePromise = { type: 'promise', serializable: false, promise } - promise.then((y) => ((x as any).value = y)) - return x -} -// #endregion -export const isWellKnownCoreTypedMessages = composeSome( - isTypedMessageText, - isTypedMessageImage, - isTypedMessageTuple, - isTypedMessageUnknown, - isTypedMessagePromise, -) as (x: TypedMessage) => x is WellKnownCoreTypedMessages diff --git a/packages/shared-base/src/TypedMessage/index.ts b/packages/shared-base/src/TypedMessage/index.ts deleted file mode 100644 index b6e7ef53fea2..000000000000 --- a/packages/shared-base/src/TypedMessage/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export * from './base' -export * from './extension' -export * from './utils' -export * from './core' -export * from './metadata' -import { isWellKnownExtensionTypedMessages, WellKnownExtensionTypedMessages } from './extension' -import { composeSome } from './utils/internal' -import { isWellKnownCoreTypedMessages, WellKnownCoreTypedMessages } from './core' -export type WellKnownTypedMessages = WellKnownCoreTypedMessages | WellKnownExtensionTypedMessages -export const isWellKnownTypedMessages = composeSome(isWellKnownCoreTypedMessages, isWellKnownExtensionTypedMessages) -export { encodeTypedMessageToDocument } from './binary-encode/encode' -export { decodeTypedMessageFromDocument } from './binary-encode/decode' -export * from './deprecated-encode' diff --git a/packages/shared-base/src/TypedMessage/transforms/flatten.ts b/packages/shared-base/src/TypedMessage/transforms/flatten.ts deleted file mode 100644 index 678a5d658790..000000000000 --- a/packages/shared-base/src/TypedMessage/transforms/flatten.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { - isTypedMessagePromise, - isTypedMessageText, - isTypedMessageTuple, - makeTypedMessageEmpty, - makeTypedMessageText, - makeTypedMessageTuple, - TypedMessage, -} from '..' -export function flattenTypedMessage(x: TypedMessage): TypedMessage { - // Promise are always dropped after resolve even it has meta. - if (isTypedMessagePromise(x) && x.value) return flattenTypedMessage(x.value) - if (isTypedMessageTuple(x)) { - if (x.meta) return x - if (x.items.length === 0) return makeTypedMessageEmpty() - if (x.items.length === 1) return flattenTypedMessage(x.items[0]) - const nextItem = x.items - .map(flattenTypedMessage) - .flatMap((x) => (isTypedMessageTuple(x) && !x.meta ? x.items : x)) - .reduce((prev, current) => { - const lastItem = prev.at(-1) - if (!lastItem || lastItem.meta || current.meta) return prev.concat(current) - if (!isTypedMessageText(current) || !isTypedMessageText(lastItem)) return prev.concat(current) - // Only concat when last one and current one are both text and have no meta. - prev.pop() - prev.push(makeTypedMessageText(`${lastItem.content} ${current.content}`)) - return prev - }, []) - if (nextItem.length === 1) return nextItem[0] - return makeTypedMessageTuple(nextItem) - } - return x -} diff --git a/packages/shared-base/src/TypedMessage/transforms/promise.ts b/packages/shared-base/src/TypedMessage/transforms/promise.ts deleted file mode 100644 index 26a225d06f4a..000000000000 --- a/packages/shared-base/src/TypedMessage/transforms/promise.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { flattenTypedMessage, isTypedMessagePromise, isTypedMessageTuple, TypedMessage } from '..' - -export function hasPromise(x: TypedMessage) { - if (isTypedMessagePromise(x)) return true - if (isTypedMessageTuple(x)) return x.items.some(hasPromise) - return false -} - -export function collectTypedMessagePromise( - x: TypedMessage, - result: Promise[] = [], -): Promise[] { - if (isTypedMessagePromise(x)) return result.concat(x.promise.then(flattenTypedMessage)) - if (isTypedMessageTuple(x)) { - return result.concat(x.items.flatMap((x) => collectTypedMessagePromise(x))) - } - return result -} diff --git a/packages/shared-base/src/TypedMessage/utils/index.ts b/packages/shared-base/src/TypedMessage/utils/index.ts deleted file mode 100644 index 7719a1ff5d21..000000000000 --- a/packages/shared-base/src/TypedMessage/utils/index.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { isTypedMessageAnchor } from '../extension' -import { isTypedMessageText, isTypedMessageTuple, TypedMessageTuple } from '../core' -import type { - NonSerializableWithAltTypedMessage, - SerializableTypedMessage, - SerializableTypedMessages, - TypedMessage, -} from '../base' -import { eq } from 'lodash-unified' -import { Option, Some, None } from 'ts-results' -import { isTypedMessageImage } from '..' - -export function isSerializableTypedMessage(x: TypedMessage): x is SerializableTypedMessages { - if ((x as SerializableTypedMessage).serializable) return true - const y = x as NonSerializableWithAltTypedMessage - if (y.serializable === false && y.alt) return true - return false -} - -/** - * This is a tree compare algorithm, may need to find a more efficient one from NPM - */ -export function isTypedMessageEqual(message1: TypedMessage, message2: TypedMessage): boolean { - if (message1.type !== message2.type) return false - if (message1.meta !== message2.meta) return false - if (isTypedMessageTuple(message1)) { - const msg1 = message1 as TypedMessageTuple - const msg2 = message2 as TypedMessageTuple - if (msg1.items.length !== msg2.items.length) return false - return msg1.items.every((item, index) => isTypedMessageEqual(item, msg2.items[index])) - } - return eq(message1, message2) -} - -/** - * Get inner text from a TypedMessage - * @param message message - */ -export function extractTextFromTypedMessage(message: TypedMessage | null): Option { - if (!message) return None - if (isTypedMessageText(message)) return Some(message.content) - if (isTypedMessageAnchor(message)) return Some(message.content) - if (isTypedMessageTuple(message)) { - const str: string[] = [] - for (const item of message.items) { - const text = extractTextFromTypedMessage(item) - if (text.some) str.push(text.val) - } - if (str.length) return Some(str.join(' ')) - return None - } - return None -} -export function extractImageFromTypedMessage( - message: TypedMessage | null, - result: (string | Blob)[] = [], -): (string | Blob)[] { - if (!message) return result - if (isTypedMessageImage(message)) return result.concat(message.image) - if (isTypedMessageTuple(message)) - return result.concat(message.items.flatMap((x) => extractImageFromTypedMessage(x))) - return result -} -export * from '../transforms/flatten' -export * from '../transforms/promise' diff --git a/packages/shared-base/src/index.ts b/packages/shared-base/src/index.ts index 347dfe9de26b..ed4ca8bdde69 100644 --- a/packages/shared-base/src/index.ts +++ b/packages/shared-base/src/index.ts @@ -1,10 +1,8 @@ -export { serializer } from './serializer' +export { serializer, registerSerializableClass } from './serializer' export { IdentifierMap, ReadonlyIdentifierMap } from './Identifier/IdentifierMap' export * from './collections' -export * from './MaskPayload' export * from './Identifier/type' export * from './i18n' -export * from './TypedMessage' export * from './utils' export * from './kv-storage' export * from './crypto' diff --git a/packages/shared-base/src/serializer/index.ts b/packages/shared-base/src/serializer/index.ts index 577aa9a14663..528901b58af3 100644 --- a/packages/shared-base/src/serializer/index.ts +++ b/packages/shared-base/src/serializer/index.ts @@ -21,14 +21,9 @@ import { } from '../Identifier/type' let typeson: Typeson | undefined +const pendingRegister = new Set<() => void>() function setup() { const { default: BigNumber } = BN - type f = (...args: any[]) => any - type T = [name: string, ser: f | undefined, de_ser: f | undefined, ctor: f] - const all: T[] = [] - function addClass(name: string, constructor: any) { - all.push([name, undefined, undefined, constructor]) - } typeson = new Typeson({}) typeson.register(builtins) typeson.register(num) @@ -48,34 +43,7 @@ function setup() { addClass('PostIVIdentifier', PostIVIdentifier) addClass('IdentifierMap', IdentifierMap) - for (const [name, ser, des, constructor] of all) { - Object.defineProperty(constructor, 'name', { - configurable: true, - enumerable: false, - writable: false, - value: name, - }) - typeson.register({ - [name]: - ser && des - ? [(x) => x instanceof constructor, ser, des] - : [ - (x) => x instanceof constructor, - // eslint-disable-next-line @typescript-eslint/no-loop-func - (x: unknown) => { - const y = Object.assign({}, x) - Object.getOwnPropertySymbols(y).forEach((x) => Reflect.deleteProperty(y, x)) - return typeson!.encapsulate(y) - }, - // eslint-disable-next-line @typescript-eslint/no-loop-func - (x: unknown) => { - const y = typeson!.revive(x) - Object.setPrototypeOf(y, constructor.prototype) - return y - }, - ], - }) - } + for (const a of pendingRegister) a() } export const serializer: Serialization = { serialization(from: unknown) { @@ -92,3 +60,45 @@ export const serializer: Serialization = { return {} }, } +export function registerSerializableClass(name: string, constructor: NewableFunction): void +export function registerSerializableClass( + name: string, + isT: (x: unknown) => boolean, + ser: (x: T) => Q, + de_ser: (x: Q) => T, +): void +export function registerSerializableClass(name: string, a: any, b?: any, c?: any): void { + if (typeson) { + if (b) typeson.register({ [name]: [a, b, c] }) + else addClass(name, a) + } else { + if (b) pendingRegister.add(() => typeson!.register({ [name]: [a, b, c] })) + else pendingRegister.add(() => addClass(name, a)) + } +} + +function addClass(name: string, constructor: any) { + Object.defineProperty(constructor, 'name', { + configurable: true, + enumerable: false, + writable: false, + value: name, + }) + typeson!.register({ + [name]: [ + (x) => x instanceof constructor, + // eslint-disable-next-line @typescript-eslint/no-loop-func + (x: unknown) => { + const y = Object.assign({}, x) + Object.getOwnPropertySymbols(y).forEach((x) => Reflect.deleteProperty(y, x)) + return typeson!.encapsulate(y) + }, + // eslint-disable-next-line @typescript-eslint/no-loop-func + (x: unknown) => { + const y = typeson!.revive(x) + Object.setPrototypeOf(y, constructor.prototype) + return y + }, + ], + }) +} diff --git a/packages/shared-base/tests/typed-message.ts b/packages/shared-base/tests/typed-message.ts index b20ff5a796b3..3fbcf0abe5c2 100644 --- a/packages/shared-base/tests/typed-message.ts +++ b/packages/shared-base/tests/typed-message.ts @@ -4,7 +4,7 @@ import { encodeTypedMessageToDocument, makeTypedMessageSerializableTupleFromList, decodeTypedMessageFromDocument, -} from '../src/TypedMessage' +} from '@masknet/typed-message/base' const meta = new Map([ ['com.example.test', 'hi'], diff --git a/packages/shared-base/tsconfig.json b/packages/shared-base/tsconfig.json index 799a575812fd..398b55ddd11e 100644 --- a/packages/shared-base/tsconfig.json +++ b/packages/shared-base/tsconfig.json @@ -7,5 +7,5 @@ }, "include": ["./src", "./src/**/*.json"], // Only type-level dependency. - "references": [{ "path": "../public-api" }, { "path": "../web3-shared/evm" }] + "references": [{ "path": "../public-api" }, { "path": "../web3-shared/evm" }, { "path": "../typed-message/base" }] } diff --git a/packages/shared-base/src/TypedMessage/base.ts b/packages/typed-message/base/base.ts similarity index 96% rename from packages/shared-base/src/TypedMessage/base.ts rename to packages/typed-message/base/base.ts index 34adb8995404..5167aba19870 100644 --- a/packages/shared-base/src/TypedMessage/base.ts +++ b/packages/typed-message/base/base.ts @@ -1,3 +1,4 @@ +export type Meta = ReadonlyMap /** * The basic structure that contains */ diff --git a/packages/shared-base/src/TypedMessage/binary-encode/decode.ts b/packages/typed-message/base/binary-encode/decode.ts similarity index 85% rename from packages/shared-base/src/TypedMessage/binary-encode/decode.ts rename to packages/typed-message/base/binary-encode/decode.ts index 73bbd829abdb..45fbac7f78a5 100644 --- a/packages/shared-base/src/TypedMessage/binary-encode/decode.ts +++ b/packages/typed-message/base/binary-encode/decode.ts @@ -1,9 +1,10 @@ import { decode } from '@msgpack/msgpack' import { Result } from 'ts-results' -import { makeTypedMessageText, makeTypedMessageTuple, makeTypedMessageUnknown, TypedMessage } from '..' -import { TypedMessageTypeEnum } from './type' +import type { TypedMessage } from '../base' +import { makeTypedMessageText, makeTypedMessageTuple, makeTypedMessageUnknown } from '../core' +import { TypedMessageBinaryEncodingTypeEnum } from './type' -const HEAD = '[@masknet/shared-base] TypedMessage: ' +const HEAD = '[@masknet/typed-message] ' export function decodeTypedMessageFromDocument(bin: Uint8Array) { return Result.wrap(() => { const doc = decode(bin) @@ -19,9 +20,9 @@ export function decodeTypedMessageFromDocument(bin: Uint8Array) { function decodeTypedMessage(tm: readonly unknown[]): TypedMessage { const [type] = tm if (typeof type !== 'string' && typeof type !== 'number') throw new TypeError(`${HEAD}Invalid TypedMessage`) - if (type === TypedMessageTypeEnum.Text) return decodeTypedMessageText(tm) - if (type === TypedMessageTypeEnum.Tuple) return decodeTypedMessageTuple(tm) - return makeTypedMessageUnknown(tm, decodeMetadata(tm[1])) + if (type === TypedMessageBinaryEncodingTypeEnum.Text) return decodeTypedMessageText(tm) + if (type === TypedMessageBinaryEncodingTypeEnum.Tuple) return decodeTypedMessageTuple(tm) + return makeTypedMessageUnknown(tm) } function decodeTypedMessageText([, version, meta, text, format]: readonly unknown[]) { assertNumber(version) diff --git a/packages/shared-base/src/TypedMessage/binary-encode/encode.ts b/packages/typed-message/base/binary-encode/encode.ts similarity index 84% rename from packages/shared-base/src/TypedMessage/binary-encode/encode.ts rename to packages/typed-message/base/binary-encode/encode.ts index 401e5dff5758..81d4d65c5671 100644 --- a/packages/shared-base/src/TypedMessage/binary-encode/encode.ts +++ b/packages/typed-message/base/binary-encode/encode.ts @@ -1,15 +1,14 @@ import { isTypedMessageText, isTypedMessageTupleSerializable, - SerializableTypedMessages, - TypedMessage, TypedMessageText, TypedMessageTupleSerializable, -} from '..' +} from '../core' +import type { SerializableTypedMessages, TypedMessage } from '../base' import { encode } from '@msgpack/msgpack' -import { TypedMessageTypeEnum } from './type' +import { TypedMessageBinaryEncodingTypeEnum } from './type' -const HEAD = '[@masknet/shared-base] TypedMessage: ' +const HEAD = '[@masknet/typed-message] ' export function encodeTypedMessageToDocument(tm: SerializableTypedMessages) { const doc = [0, encodeTypedMessage(tm)] return encode(doc) @@ -25,10 +24,10 @@ function encodeTypedMessage(tm: SerializableTypedMessages): any[] { } function encodeTypedMessageText(tm: TypedMessageText): any[] { // TODO: TextFormat - return [TypedMessageTypeEnum.Text, tm.version, encodeMeta(tm), tm.content] + return [TypedMessageBinaryEncodingTypeEnum.Text, tm.version, encodeMeta(tm), tm.content] } function encodeTypedMessageTuple(tm: TypedMessageTupleSerializable): any[] { - return [TypedMessageTypeEnum.Tuple, tm.version, encodeMeta(tm), tm.items.map(encodeTypedMessage)] + return [TypedMessageBinaryEncodingTypeEnum.Tuple, tm.version, encodeMeta(tm), tm.items.map(encodeTypedMessage)] } function encodeMeta(tm: TypedMessage) { @@ -78,7 +77,7 @@ function collectValue(val: any): any { } return result } catch (err) { - console.warn('[@masknet/shared-base] TypedMessage: When converting value', val, ', an error occurred', err) + console.warn(HEAD, 'When converting value', val, ', an error occurred', err) throw err } } diff --git a/packages/typed-message/base/binary-encode/index.ts b/packages/typed-message/base/binary-encode/index.ts new file mode 100644 index 000000000000..95179f2f0e2d --- /dev/null +++ b/packages/typed-message/base/binary-encode/index.ts @@ -0,0 +1,2 @@ +export { decodeTypedMessageFromDocument } from './decode' +export { encodeTypedMessageToDocument } from './encode' diff --git a/packages/typed-message/base/binary-encode/type.ts b/packages/typed-message/base/binary-encode/type.ts new file mode 100644 index 000000000000..f531a4e0e0ae --- /dev/null +++ b/packages/typed-message/base/binary-encode/type.ts @@ -0,0 +1,5 @@ +/** @internal */ +export enum TypedMessageBinaryEncodingTypeEnum { + Tuple = 0, + Text = 1, +} diff --git a/packages/typed-message/base/core/empty.ts b/packages/typed-message/base/core/empty.ts new file mode 100644 index 000000000000..eaa227eab98e --- /dev/null +++ b/packages/typed-message/base/core/empty.ts @@ -0,0 +1,21 @@ +import type { SerializableTypedMessage } from '../base' +import { createIsType } from '../utils/internal' + +export interface TypedMessageEmpty extends SerializableTypedMessage<1> { + readonly type: 'empty' + readonly meta?: undefined +} + +export const isTypedMessageEmpty = createIsType('empty') + +const empty: TypedMessageEmpty = { + type: 'empty', + serializable: true, + version: 1, + meta: undefined, +} +Object.setPrototypeOf(empty, null) +Object.freeze(empty) +export function makeTypedMessageEmpty(): TypedMessageEmpty { + return empty +} diff --git a/packages/typed-message/base/core/image.ts b/packages/typed-message/base/core/image.ts new file mode 100644 index 000000000000..e3321663eaa7 --- /dev/null +++ b/packages/typed-message/base/core/image.ts @@ -0,0 +1,30 @@ +import type { NonSerializableTypedMessage, Meta } from '../base' +import { createIsType } from '../utils/internal' + +/** + * A single image + * TODO: it should be serializable but still not decided how to do that yet. + */ +export interface TypedMessageImage extends NonSerializableTypedMessage { + readonly type: 'image' + readonly image: string | Blob + readonly width?: number + readonly height?: number +} + +export const isTypedMessageImage = createIsType('image') + +export function makeTypedMessageImage( + image: TypedMessageImage['image'], + size?: { width: number; height: number }, + meta?: Meta, +): TypedMessageImage { + return { + type: 'image', + serializable: false, + image, + width: size?.width, + height: size?.height, + meta, + } +} diff --git a/packages/typed-message/base/core/index.ts b/packages/typed-message/base/core/index.ts new file mode 100644 index 000000000000..015e2047fe1f --- /dev/null +++ b/packages/typed-message/base/core/index.ts @@ -0,0 +1,34 @@ +export * from './empty' +export * from './text' +export * from './image' +export * from './tuple' +export * from './unknown' +export * from './promise' + +import * as empty from './empty' +import * as unknown from './unknown' +import * as tuple from './tuple' +import * as text from './text' +import * as image from './image' +import * as promise from './promise' + +import type { TypedMessage } from '../base' +import { composeSome } from '../utils/internal' + +export type CoreTypedMessages = + | empty.TypedMessageEmpty + | text.TypedMessageText + | image.TypedMessageImage + | tuple.TypedMessageTuple + | tuple.TypedMessageTupleSerializable + | unknown.TypedMessageUnknown + | promise.TypedMessagePromise + +export const isCoreTypedMessages = composeSome( + empty.isTypedMessageEmpty, + text.isTypedMessageText, + image.isTypedMessageImage, + tuple.isTypedMessageTuple, + unknown.isTypedMessageUnknown, + promise.isTypedMessagePromise, +) as (x: TypedMessage) => x is CoreTypedMessages diff --git a/packages/typed-message/base/core/promise.ts b/packages/typed-message/base/core/promise.ts new file mode 100644 index 000000000000..9a2941065525 --- /dev/null +++ b/packages/typed-message/base/core/promise.ts @@ -0,0 +1,26 @@ +import type { TypedMessage, NonSerializableTypedMessage } from '../base' +import { createIsType } from '../utils/internal' + +export interface TypedMessagePromise extends NonSerializableTypedMessage { + readonly type: 'promise' + readonly promise: Promise & { value?: T } + readonly meta?: undefined + /** What to display when the message is not ready. */ + readonly alt?: TypedMessage +} + +export const isTypedMessagePromise = createIsType('promise') + +export function makeTypedMessagePromise( + promise: Promise, + alt?: TypedMessage, +): TypedMessagePromise { + const x: TypedMessagePromise = { + type: 'promise', + serializable: false, + promise: promise.then((y) => (x.promise.value = y)), + alt, + meta: undefined, + } + return x +} diff --git a/packages/typed-message/base/core/text.ts b/packages/typed-message/base/core/text.ts new file mode 100644 index 000000000000..56a5936acd2e --- /dev/null +++ b/packages/typed-message/base/core/text.ts @@ -0,0 +1,24 @@ +import type { SerializableTypedMessage, TypedMessage, Meta } from '../base' +import { createIsType } from '../utils/internal' + +export type TypedMessageText = TypedMessageTextV1 + +/** A text message */ +export interface TypedMessageTextV1 extends SerializableTypedMessage<1> { + readonly type: 'text' + readonly content: string +} + +export const isTypedMessageTextV1 = createIsType('text', 1) + +export const isTypedMessageText: (x: TypedMessage) => x is TypedMessageText = isTypedMessageTextV1 + +export function makeTypedMessageText(text: string, meta?: Meta): TypedMessageTextV1 { + return { + type: 'text', + version: 1, + serializable: true, + content: text, + meta, + } +} diff --git a/packages/typed-message/base/core/tuple.ts b/packages/typed-message/base/core/tuple.ts new file mode 100644 index 000000000000..2b8a1c9f9570 --- /dev/null +++ b/packages/typed-message/base/core/tuple.ts @@ -0,0 +1,47 @@ +import type { SerializableTypedMessage, SerializableTypedMessages, TypedMessage, Meta } from '../base' +import { isSerializableTypedMessage } from '../utils' +import { composeEvery } from '../utils/internal' + +/** Multiple TypedMessages (ordered) */ +export interface TypedMessageTuple extends TypedMessage { + readonly type: 'tuple' + readonly items: T +} +export interface TypedMessageTupleSerializable< + T extends readonly SerializableTypedMessages[] = readonly SerializableTypedMessages[], +> extends SerializableTypedMessage<1>, + TypedMessageTuple { + readonly type: 'tuple' +} + +export const isTypedMessageTuple = (x: TypedMessage): x is TypedMessageTuple | TypedMessageTupleSerializable => + x.type === 'tuple' + +export const isTypedMessageTupleSerializable: (x: TypedMessage) => x is TypedMessageTupleSerializable = composeEvery( + isTypedMessageTuple, + isSerializableTypedMessage, +) as any + +export function makeTypedMessageTuple( + items: T, + meta?: Meta, +): TypedMessageTuple { + return { type: 'tuple', items, meta } +} +export function makeTypedMessageTupleFromList( + ...args: T +): TypedMessageTuple { + return { type: 'tuple', items: args } +} + +export function makeTypedMessageTupleSerializable< + T extends readonly SerializableTypedMessages[] = readonly SerializableTypedMessages[], +>(items: T, meta?: Meta): TypedMessageTupleSerializable { + return { type: 'tuple', version: 1, serializable: true, items, meta } +} + +export function makeTypedMessageSerializableTupleFromList< + T extends readonly SerializableTypedMessages[] = readonly SerializableTypedMessages[], +>(...args: T): TypedMessageTupleSerializable { + return { type: 'tuple', version: 1, items: args, serializable: true } +} diff --git a/packages/typed-message/base/core/unknown.ts b/packages/typed-message/base/core/unknown.ts new file mode 100644 index 000000000000..8bb8cbe49a7f --- /dev/null +++ b/packages/typed-message/base/core/unknown.ts @@ -0,0 +1,14 @@ +import type { NonSerializableTypedMessage } from '../base' +import { createIsType } from '../utils/internal' + +export interface TypedMessageUnknown extends NonSerializableTypedMessage { + readonly type: 'unknown' + /** The unrecognized data */ + readonly raw?: unknown + readonly meta?: undefined +} +export const isTypedMessageUnknown = createIsType('unknown') + +export function makeTypedMessageUnknown(raw?: unknown): TypedMessageUnknown { + return { type: 'unknown', serializable: false, meta: undefined, raw } +} diff --git a/packages/shared-base/src/TypedMessage/deprecated-encode/index.ts b/packages/typed-message/base/deprecated-encode/index.ts similarity index 93% rename from packages/shared-base/src/TypedMessage/deprecated-encode/index.ts rename to packages/typed-message/base/deprecated-encode/index.ts index ff73a4da28f1..76a7e1ecb195 100644 --- a/packages/shared-base/src/TypedMessage/deprecated-encode/index.ts +++ b/packages/typed-message/base/deprecated-encode/index.ts @@ -1,6 +1,5 @@ import { None, Ok, Result } from 'ts-results' -import type { TypedMessageText } from '..' -import { makeTypedMessageText } from '../core' +import { makeTypedMessageText, TypedMessageText } from '../core' export function encodeTypedMessageV38Format(message: TypedMessageText) { const encoder = new TextEncoder() diff --git a/packages/typed-message/base/extension/MaskPayload.ts b/packages/typed-message/base/extension/MaskPayload.ts new file mode 100644 index 000000000000..4643f37b2feb --- /dev/null +++ b/packages/typed-message/base/extension/MaskPayload.ts @@ -0,0 +1,22 @@ +import type { Meta, TypedMessage } from '../base' +import { createIsType } from '../utils/internal' + +/** + * This TypedMessage represents an encrypted TypedMessage. + */ +export interface TypedMessageMaskPayload extends TypedMessage { + readonly type: 'x-mask-payload' + readonly message: TypedMessage +} +export const isTypedMessageMaskPayload = createIsType('x-mask-payload') + +export function makeTypedMessageMaskPayload( + message: TypedMessageMaskPayload['message'], + meta?: Meta, +): TypedMessageMaskPayload { + return { + type: 'x-mask-payload', + message, + meta, + } +} diff --git a/packages/shared-base/src/TypedMessage/extension.ts b/packages/typed-message/base/extension/anchor.ts similarity index 64% rename from packages/shared-base/src/TypedMessage/extension.ts rename to packages/typed-message/base/extension/anchor.ts index 1936116847c7..73fb986d5c27 100644 --- a/packages/shared-base/src/TypedMessage/extension.ts +++ b/packages/typed-message/base/extension/anchor.ts @@ -1,7 +1,7 @@ -import type { NonSerializableWithAltTypedMessage, TypedMessage } from './base' -import { composeSome, createIsType } from './utils/internal' -import { makeTypedMessageText, TypedMessageText } from './core' -export type WellKnownExtensionTypedMessages = TypedMessageAnchor +import type { NonSerializableWithAltTypedMessage } from '../base' +import { createIsType } from '../utils/internal' +import { makeTypedMessageText, TypedMessageText } from '../core' + /** It represents a single link */ export interface TypedMessageAnchor extends NonSerializableWithAltTypedMessage { readonly type: 'x-anchor' @@ -10,7 +10,9 @@ export interface TypedMessageAnchor extends NonSerializableWithAltTypedMessage { readonly content: string readonly alt: TypedMessageText } + export const isTypedMessageAnchor = createIsType('x-anchor') + export function makeTypedMessageAnchor( category: TypedMessageAnchor['category'], href: TypedMessageAnchor['href'], @@ -25,7 +27,3 @@ export function makeTypedMessageAnchor( alt: makeTypedMessageText(`[${content}](${href})`), } } -// -export const isWellKnownExtensionTypedMessages = composeSome(isTypedMessageAnchor) as ( - x: TypedMessage, -) => x is WellKnownExtensionTypedMessages diff --git a/packages/typed-message/base/extension/index.ts b/packages/typed-message/base/extension/index.ts new file mode 100644 index 000000000000..2ed1e097eaf2 --- /dev/null +++ b/packages/typed-message/base/extension/index.ts @@ -0,0 +1,12 @@ +export * from './anchor' +export * from './MaskPayload' + +import { composeSome } from '../utils/internal' +import * as anchor from './anchor' +import * as MaskPayload from './MaskPayload' +export type WellKnownExtensionTypedMessages = anchor.TypedMessageAnchor | MaskPayload.TypedMessageMaskPayload + +export const isWellKnownExtensionTypedMessages = composeSome( + anchor.isTypedMessageAnchor, + MaskPayload.isTypedMessageMaskPayload, +) diff --git a/packages/typed-message/base/index.ts b/packages/typed-message/base/index.ts new file mode 100644 index 000000000000..2a7b522050ea --- /dev/null +++ b/packages/typed-message/base/index.ts @@ -0,0 +1,15 @@ +export * from './base' +export * from './core' +export * from './extension' +export * from './binary-encode' +export * from './deprecated-encode' +export * from './utils' +export * from './visitor' +export * from './transformer' + +import { isCoreTypedMessages, CoreTypedMessages } from './core' +import { isWellKnownExtensionTypedMessages, WellKnownExtensionTypedMessages } from './extension' +import { composeSome } from './utils/internal' + +export type WellKnownTypedMessages = WellKnownExtensionTypedMessages | CoreTypedMessages +export const isWellKnownTypedMessages = composeSome(isCoreTypedMessages, isWellKnownExtensionTypedMessages) diff --git a/packages/typed-message/base/transformer/Flatten.ts b/packages/typed-message/base/transformer/Flatten.ts new file mode 100644 index 000000000000..ba5f8f40f2aa --- /dev/null +++ b/packages/typed-message/base/transformer/Flatten.ts @@ -0,0 +1,42 @@ +import { + isTypedMessageEmpty, + isTypedMessagePromise, + isTypedMessageText, + isTypedMessageTuple, + makeTypedMessageEmpty, + makeTypedMessageText, + makeTypedMessageTuple, + makeTypedMessageTupleSerializable, +} from '../core' +import type { TypedMessage } from '../base' +import { visitEachTypedMessageChild } from '../visitor' +import { isSerializableTypedMessage } from '../utils' +import { emptyTransformationContext, TransformationContext } from './context' + +export function FlattenTypedMessage(message: TypedMessage, context: TransformationContext): TypedMessage { + if (isTypedMessagePromise(message) && message.promise.value) return message.promise.value + if (isTypedMessageTuple(message)) { + const next = message.items + .map((x) => FlattenTypedMessage(x, context)) + .flatMap((x) => (isTypedMessageTuple(x) ? (x.meta ? x : x.items) : x)) + .filter((x) => !isTypedMessageEmpty(x)) + .reduce((result, current) => { + const lastItem = result.at(-1) + if (!lastItem || lastItem.meta || current.meta) return result.concat(current) + if (!isTypedMessageText(current) || !isTypedMessageText(lastItem)) return result.concat(current) + // Only concat when last one and current one are both text and have no meta. + result.pop() + result.push(makeTypedMessageText(`${lastItem.content} ${current.content}`)) + return result + }, []) + + if (!message.meta) { + if (next.length === 0) return makeTypedMessageEmpty() + if (next.length === 1) return next[0] + } + if (next.every(isSerializableTypedMessage)) return makeTypedMessageTupleSerializable(next, message.meta) + return makeTypedMessageTuple(next, message.meta) + } + return visitEachTypedMessageChild(message, FlattenTypedMessage, context) +} +FlattenTypedMessage.NoContext = (message: TypedMessage) => FlattenTypedMessage(message, emptyTransformationContext) diff --git a/packages/typed-message/base/transformer/MaskPayload/index.ts b/packages/typed-message/base/transformer/MaskPayload/index.ts new file mode 100644 index 000000000000..a6debceabfff --- /dev/null +++ b/packages/typed-message/base/transformer/MaskPayload/index.ts @@ -0,0 +1,90 @@ +import { FlattenTypedMessage } from '..' +import type { TypedMessage } from '../../base' +import { isTypedMessageImage, isTypedMessageText, isTypedMessageTuple, TypedMessageImage } from '../../core' +import { isTypedMessageAnchor, isTypedMessageMaskPayload } from '../../extension' +import { visitEachTypedMessageChild } from '../../visitor' +import type { TransformationContext } from '../context' + +export interface MaskPayloadTransformOptions { + /** + * Text that always before the Mask Payload. This transform will remove them. + * + * ``` + * This message is encrypted by @Mask. _link here_ + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * ``` + * + * This part can be removed by providing the strings into this option. + */ + removePrefixText: string[] + /** + * Text that always after the Mask Payload. This transform will remove them. + * + * ``` + * _link here_ Install to decrypt! + * ~~~~~~~~~~~~~~~~~~~~ + * ``` + * + * This part can be removed by providing the strings into this option. + */ + removePostfixText: string[] + /** + * An example: + * + * TypedMessagePromise (alt = TypedMessageText("decrypting...")) resolves to + * TypedMessagePromise (alt = TypedMessageText("waiting key on gun")) resolves to + * TypedMessageMaskPayload (message = TypedMessageText("hey this is an encrypted message!")) + */ + transformText(payloadLike: string, context: TransformationContext): TypedMessage + transformImage(image: TypedMessageImage, context: TransformationContext): TypedMessage +} +export function createMaskPayloadTransform(options: MaskPayloadTransformOptions) { + return function MaskPayloadTransform(message: TypedMessage, context: TransformationContext) { + message = FlattenTypedMessage(message, context) + // We don't transform nested message + + // When a false positive payload detected, + // if we return the result in TypedMessageText (or if we also transform TypedMessageMaskPayload) + // we will detect the payload again and cause an infinite retry. + if (isTypedMessageMaskPayload(message)) return message + + // Note: there maybe more than 1 payload in the message. Make sure both of them are handled. + if (isTypedMessageAnchor(message)) { + if (message.content.match(linkPayload)) return options.transformText(message.content, context) + if (message.href.match(linkPayload)) return options.transformText(message.href, context) + } else if (isTypedMessageImage(message)) { + return options.transformImage(message, context) + } else if (isTypedMessageText(message)) { + // TODO: there maybe more than 1 payload to parse. + // Not detect link form here. Only detect raw form (used on FB) in this branch. + if (message.content.match(textPayload)) { + return options.transformText(message.content, context) + } + } else if (isTypedMessageTuple(message)) { + // TODO: there maybe more than 1 payload to parse. + // Visit each child here, when a raw form or link form is detected, + // we should check if the before/after is the text need to be removed. + // For example: + // Tuple( + // Text("Keep this text! This post is encrypted by") + // Anchor("@mask.io"), + // Text(" . Install to decrypt!"), + // Anchor(payload here), + // Text(" more text to be removed! But keep this one!") + // ) + // it should be transformed into + // Tuple( + // Text("Keep this text! "), + // MaskPayload(pending...), + // Text(" But keep this one!"), + // ) + } + return visitEachTypedMessageChild(message, MaskPayloadTransform, context) + } +} +// match the link version payload + +/* cspell:disable-next-line */ +const linkPayload = /^https?:\/\/mask(\.io|book\.com)\/\?postdata_v/i +// match the text version payload +const textPayload = /(\u{1F3BC}[\w+/=|]+:\|\|)/giu diff --git a/packages/typed-message/base/transformer/ParseLink.ts b/packages/typed-message/base/transformer/ParseLink.ts new file mode 100644 index 000000000000..79550fc17009 --- /dev/null +++ b/packages/typed-message/base/transformer/ParseLink.ts @@ -0,0 +1,21 @@ +import type { TypedMessage } from '../base' +import { isTypedMessageText, makeTypedMessageTupleSerializable, makeTypedMessageText } from '../core' +import { makeTypedMessageAnchor } from '../extension' +import { parseLink } from '../utils/parseLink' +import { visitEachTypedMessageChild } from '../visitor' +import type { TransformationContext } from './context' + +export function ParseLinkTransformer(message: TypedMessage, context: TransformationContext): TypedMessage { + if (isTypedMessageText(message)) { + const parsed = parseLink(message.content) + if (parsed.length === 1 && parsed[0].type === 'text') return message + return makeTypedMessageTupleSerializable( + parsed.map((i) => { + if (i.type === 'text') return makeTypedMessageText(i.content) + return makeTypedMessageAnchor(i.category, i.content, i.content) + }), + message.meta, + ) + } + return visitEachTypedMessageChild(message, ParseLinkTransformer, context) +} diff --git a/packages/typed-message/base/transformer/composed.ts b/packages/typed-message/base/transformer/composed.ts new file mode 100644 index 000000000000..e0ef953527e2 --- /dev/null +++ b/packages/typed-message/base/transformer/composed.ts @@ -0,0 +1,57 @@ +import type { TypedMessage } from '../base' +import type { TransformationContext } from './context' +import type { Transformer } from './index' +export interface ComposedTransformers { + subscription: { + getCurrentValue: () => Transformer + subscribe(f: () => void): () => void + } + addTransformer( + transformer: Transformer | ComposedTransformers['subscription'], + priority: number, + signal?: AbortSignal, + ): () => void +} +export function composeTransformers(): ComposedTransformers { + const event = new EventTarget() + const onUpdate = () => event.dispatchEvent(new Event('update')) + const transformers = new Set() + + function composed(message: TypedMessage, context: TransformationContext) { + return [...transformers].sort((a, b) => a[1] - b[1]).reduce((p, [c]) => c(p, context), message) + } + + const subscription = { + getCurrentValue: (): Transformer => (message, context) => composed(message, context), + subscribe(f: () => void) { + event.addEventListener('update', f) + return () => { + event.removeEventListener('update', f) + } + }, + } + return { + subscription, + addTransformer(t, priority, signal) { + const f_priority = [ + typeof t === 'function' + ? t + : (message: TypedMessage, context: TransformationContext) => t.getCurrentValue()(message, context), + priority, + ] as const + transformers.add(f_priority) + onUpdate() + + const cancelSubscription = typeof t === 'function' ? () => {} : t.subscribe(onUpdate) + + const remove = () => { + transformers.delete(f_priority) + cancelSubscription() + onUpdate() + } + + signal?.addEventListener('abort', remove) + return remove + }, + } +} diff --git a/packages/typed-message/base/transformer/context.ts b/packages/typed-message/base/transformer/context.ts new file mode 100644 index 000000000000..c81767f6bd25 --- /dev/null +++ b/packages/typed-message/base/transformer/context.ts @@ -0,0 +1,14 @@ +export interface TransformationContext { + authorHint?: { network: string; userId: string } + currentProfile?: { network: string; userId: string } + postURL?: string + reportDecryptedInfo?( + iv?: Uint8Array, + claimedAuthor?: { network: string; userId: string }, + publicShared?: boolean, + ): void +} +export function createTransformationContext(): TransformationContext { + return Object.freeze({}) +} +export const emptyTransformationContext = createTransformationContext() diff --git a/packages/typed-message/base/transformer/index.ts b/packages/typed-message/base/transformer/index.ts new file mode 100644 index 000000000000..4c9128e560bc --- /dev/null +++ b/packages/typed-message/base/transformer/index.ts @@ -0,0 +1,8 @@ +import type { TypedMessage } from '../base' +import type { TransformationContext } from './context' +export type Transformer = (message: TypedMessage, context: TransformationContext) => TypedMessage +export * from './composed' +export * from './context' +export { FlattenTypedMessage } from './Flatten' +export { ParseLinkTransformer } from './ParseLink' +export { createMaskPayloadTransform } from './MaskPayload' diff --git a/packages/typed-message/base/tsconfig.json b/packages/typed-message/base/tsconfig.json new file mode 100644 index 000000000000..c2405a737449 --- /dev/null +++ b/packages/typed-message/base/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "rootDir": "../base/", + "outDir": "../dist/base", + "tsBuildInfoFile": "../dist/base.tsbuildinfo" + }, + "include": ["./"], + "references": [] +} diff --git a/packages/typed-message/base/utils/extract.ts b/packages/typed-message/base/utils/extract.ts new file mode 100644 index 000000000000..d3ef1fd2d3c5 --- /dev/null +++ b/packages/typed-message/base/utils/extract.ts @@ -0,0 +1,30 @@ +import type { TypedMessage } from '../base' +import { isTypedMessageText, isTypedMessageImage } from '../core' +import { isTypedMessageAnchor } from '../extension' +import { Option, Some, None } from 'ts-results' +import { forEachTypedMessageChild } from '../visitor/forEachChild' + +/** + * Get inner text from a TypedMessage + * @param message message + */ +export function extractTextFromTypedMessage(message: TypedMessage | null): Option { + if (!message) return None + const text: string[] = [] + forEachTypedMessageChild(message, function visitor() { + if (isTypedMessageText(message)) text.push(message.content) + else if (isTypedMessageAnchor(message)) text.push(message.content) + else forEachTypedMessageChild(message, visitor) + }) + if (text.length) return Some(text.join(' ')) + return None +} +export function extractImageFromTypedMessage(message: TypedMessage | null): (string | Blob)[] { + if (!message) return [] + const image: (string | Blob)[] = [] + forEachTypedMessageChild(message, function visitor(message) { + if (isTypedMessageImage(message)) return image.push(message.image) + return forEachTypedMessageChild(message, visitor) + }) + return image +} diff --git a/packages/typed-message/base/utils/index.ts b/packages/typed-message/base/utils/index.ts new file mode 100644 index 000000000000..1a691e5b978e --- /dev/null +++ b/packages/typed-message/base/utils/index.ts @@ -0,0 +1,37 @@ +export * from './metadata' +export * from './extract' +export * from './promise' + +import type { + TypedMessage, + SerializableTypedMessages, + SerializableTypedMessage, + NonSerializableWithAltTypedMessage, +} from '../base' +import { isTypedMessageTuple, TypedMessageTuple } from '../core' +import { eq } from 'lodash-unified' + +export function isNonSerializableTypedMessageWithAlt(x: TypedMessage): x is NonSerializableWithAltTypedMessage { + const y = x as NonSerializableWithAltTypedMessage + if (y.serializable !== false) return false + return isSerializableTypedMessage(y.alt) +} +export function isSerializableTypedMessage(x: TypedMessage): x is SerializableTypedMessages { + if ((x as SerializableTypedMessage).serializable) return true + return isNonSerializableTypedMessageWithAlt(x) +} + +/** + * This is a tree compare algorithm, may need to find a more efficient one from NPM + */ +export function isTypedMessageEqual(message1: TypedMessage, message2: TypedMessage): boolean { + if (message1.type !== message2.type) return false + if (message1.meta !== message2.meta) return false + if (isTypedMessageTuple(message1)) { + const msg1 = message1 as TypedMessageTuple + const msg2 = message2 as TypedMessageTuple + if (msg1.items.length !== msg2.items.length) return false + return msg1.items.every((item, index) => isTypedMessageEqual(item, msg2.items[index])) + } + return eq(message1, message2) +} diff --git a/packages/shared-base/src/TypedMessage/utils/internal.ts b/packages/typed-message/base/utils/internal.ts similarity index 85% rename from packages/shared-base/src/TypedMessage/utils/internal.ts rename to packages/typed-message/base/utils/internal.ts index 69f16b807b3e..00513963ae3d 100644 --- a/packages/shared-base/src/TypedMessage/utils/internal.ts +++ b/packages/typed-message/base/utils/internal.ts @@ -1,7 +1,7 @@ import type { SerializableTypedMessage, TypedMessage } from '../base' /** @internal */ -export function createIsType(x: string, version?: number) { +export function createIsType(x: T['type'], version?: number) { return (y: TypedMessage): y is T => { if (version !== undefined && (y as SerializableTypedMessage).version !== version) return false return y.type === x @@ -12,6 +12,7 @@ export function composeSome(...fns: ((...args: Args) => bool return (...args: Args) => fns.some((f) => f(...args)) } +/** @internal */ export function composeEvery(...fns: ((...args: Args) => boolean)[]) { return (...args: Args) => fns.every((f) => f(...args)) } diff --git a/packages/shared-base/src/TypedMessage/metadata.ts b/packages/typed-message/base/utils/metadata.ts similarity index 96% rename from packages/shared-base/src/TypedMessage/metadata.ts rename to packages/typed-message/base/utils/metadata.ts index 731bcc89cd43..e535e680c65c 100644 --- a/packages/shared-base/src/TypedMessage/metadata.ts +++ b/packages/typed-message/base/utils/metadata.ts @@ -1,5 +1,5 @@ import { Result, Ok, Err, Some, Option, None } from 'ts-results' -import type { TypedMessage } from './base' +import type { TypedMessage } from '../base' import z_schema from 'z-schema' import draft, { enableMapSet, Draft } from 'immer' enableMapSet() @@ -8,17 +8,20 @@ const metadataSchemaStore = new Map() export function getKnownMetadataKeys() { return [...metadataSchemaStore.keys()] } + export function getMetadataSchema(key: string): Option { return metadataSchemaStore.has(key) ? Some(metadataSchemaStore.get(key)!) : None } + /** - * Register your metadata with a JSON Schema so Mask can validate the schema for you. + * Register your metadata with a JSON Schema so we can validate the schema for you. * @param key Metadata key * @param jsonSchema JSON Schema to validate the metadata */ export function registerMetadataSchema(key: string, jsonSchema: object) { metadataSchemaStore.set(key, jsonSchema) } + /** * Create a TypedMessage metadata reader for your plugin * @param key Metadata key @@ -31,6 +34,7 @@ export function createTypedMessageMetadataReader(key: string, jsonSchema?: ob if (jsonSchema) registerMetadataSchema(key, jsonSchema) return (meta: TypedMessage['meta']) => readTypedMessageMetadataUntyped(meta, key) } + /** * The raw parser of metadata reader * @param meta Metadata object diff --git a/packages/typed-message/base/utils/parseLink.ts b/packages/typed-message/base/utils/parseLink.ts new file mode 100644 index 000000000000..7316a43bf953 --- /dev/null +++ b/packages/typed-message/base/utils/parseLink.ts @@ -0,0 +1,50 @@ +import _anchorme from 'anchorme' +import type { TypedMessageAnchor } from '..' +// ESM/CJS compat +const anchorme = ((_anchorme as any).default || _anchorme) as typeof _anchorme + +export type ParseLinkResult = + | { + type: 'text' + content: string + } + | { + type: 'link' + content: string + category: TypedMessageAnchor['category'] + } + +export function parseLink(text: string): ParseLinkResult[] { + const parsed = anchorme.list(text) + + const result: ParseLinkResult[] = [] + + let start = 0 + for (const x of parsed) { + if (x.isURL) { + result.push({ type: 'text', content: text.slice(start, x.start) }) + result.push({ type: 'link', content: x.string, category: 'normal' }) + } else { + result.push({ type: 'text', content: text.slice(start, x.end) }) + } + start = x.end + } + result.push({ type: 'text', content: text.slice(start, text.length) }) + return result.filter((x) => x.content).flatMap((x) => (x.type === 'text' ? parseTag(x.content) : x)) +} + +const TagLike = /([#$@][\w\-]+)/g +const map = { + '@': 'user', + '#': 'hash', + $: 'cash', +} as const +function parseTag(x: string): ParseLinkResult[] { + return x + .split(TagLike) + .map((x) => + TagLike.test(x) + ? { type: 'link', content: x, category: map[x[0] as keyof typeof map] || 'normal' } + : { type: 'text', content: x }, + ) +} diff --git a/packages/typed-message/base/utils/promise.ts b/packages/typed-message/base/utils/promise.ts new file mode 100644 index 000000000000..11facaf34e35 --- /dev/null +++ b/packages/typed-message/base/utils/promise.ts @@ -0,0 +1,12 @@ +import { isTypedMessagePromise } from '../core' +import type { TypedMessage } from '../base' +import { forEachTypedMessageChild } from '../visitor/forEachChild' + +export function collectTypedMessagePromise(x: TypedMessage): Promise[] { + const result: Promise[] = [] + forEachTypedMessageChild(x, function visitor(x: TypedMessage) { + if (isTypedMessagePromise(x)) return result.push(x.promise) + return forEachTypedMessageChild(x, visitor) + }) + return result +} diff --git a/packages/typed-message/base/visitor/forEachChild.ts b/packages/typed-message/base/visitor/forEachChild.ts new file mode 100644 index 000000000000..de2d0d7c1145 --- /dev/null +++ b/packages/typed-message/base/visitor/forEachChild.ts @@ -0,0 +1,18 @@ +import { isTypedMessagePromise, isTypedMessageTuple } from '../core' +import { isNonSerializableTypedMessageWithAlt } from '../utils' +import type { TypedMessage } from '../base' +import { isTypedMessageMaskPayload } from '../extension' + +export function forEachTypedMessageChild(node: TypedMessage, visitor: (x: TypedMessage) => void) { + if (isTypedMessageTuple(node)) { + for (const each of node.items) visitor(each) + } else if (isTypedMessagePromise(node)) { + // if Promise has a resolved value, we ignore it's alt. + if (node.promise.value) visitor(node.promise.value) + else if (node.alt) visitor(node.alt) + } else if (isTypedMessageMaskPayload(node)) { + visitor(node.message) + } else if (isNonSerializableTypedMessageWithAlt(node)) { + visitor(node.alt) + } +} diff --git a/packages/typed-message/base/visitor/index.ts b/packages/typed-message/base/visitor/index.ts new file mode 100644 index 000000000000..a677985107d3 --- /dev/null +++ b/packages/typed-message/base/visitor/index.ts @@ -0,0 +1 @@ +export * from './visitEachChild' diff --git a/packages/typed-message/base/visitor/visitEachChild.ts b/packages/typed-message/base/visitor/visitEachChild.ts new file mode 100644 index 000000000000..f077226fe6ee --- /dev/null +++ b/packages/typed-message/base/visitor/visitEachChild.ts @@ -0,0 +1,53 @@ +import { + isTypedMessagePromise, + isTypedMessageTuple, + makeTypedMessagePromise, + makeTypedMessageTuple, + makeTypedMessageTupleSerializable, +} from '../core' +import { isNonSerializableTypedMessageWithAlt, isSerializableTypedMessage } from '../utils' +import type { TypedMessage } from '../base' +import { isTypedMessageMaskPayload, makeTypedMessageMaskPayload } from '../extension' +import type { TransformationContext, Transformer } from '../transformer' + +export function visitEachTypedMessageChild( + node: TypedMessage, + visitor: Transformer, + context: TransformationContext, +): TypedMessage { + if (isTypedMessageTuple(node)) { + const after = node.items.flatMap((x) => { + const next = visitor(x, context) + if (isTypedMessageTuple(next)) return next.items + return next + }) + if (after.every(isSerializableTypedMessage)) { + return makeTypedMessageTupleSerializable(after, node.meta) + } + return makeTypedMessageTuple(after, node.meta) + } else if (isTypedMessagePromise(node)) { + // we ignore alt if promise is resolved. + if (node.promise.value) return visitor(node.promise.value, context) + else if (node.alt) return makeTypedMessagePromise(node.promise, visitor(node.alt, context)) + return node + } else if (isTypedMessageMaskPayload(node)) { + const next = visitor(node.message, context) + return makeTypedMessageMaskPayload(next, node.meta) + } else if (isNonSerializableTypedMessageWithAlt(node)) { + const alt = visitor(node.alt, context) + if (!isSerializableTypedMessage(alt)) { + console.warn( + '[@masknet/typed-message] You must return a serializable message in this position. Original:', + node, + 'Transformed child "alt":', + alt, + ) + // ignore the transform result + return node + } + return { ...node, alt } as TypedMessage + } else { + // return node with no child + return node + } +} diff --git a/packages/typed-message/dom/Renderer/Core/Image.tsx b/packages/typed-message/dom/Renderer/Core/Image.tsx new file mode 100644 index 000000000000..f7e30b2cfdf4 --- /dev/null +++ b/packages/typed-message/dom/Renderer/Core/Image.tsx @@ -0,0 +1,30 @@ +import { memo, useContext, useEffect, useState } from 'react' +import type { TypedMessageImage } from '../../../base' +import { useMetadataRender } from '../MetadataRender' +import { MessageRenderUIComponentsContext, ImageDefault } from '../utils/ComponentsContext' + +export const TypedMessageImageRenderer = memo(function TypedMessageImageRenderer(props: TypedMessageImage) { + const { Image = ImageDefault! } = useContext(MessageRenderUIComponentsContext) + const { image, width, height } = props + const [blobSrc, setBlobSrc] = useState(null) + + useEffect(() => { + if (typeof image === 'string') return + const src = URL.createObjectURL(image) + setBlobSrc(src) + return () => { + setBlobSrc(null) + URL.revokeObjectURL(src) + } + }, [image]) + + const finalSrc = blobSrc || image + if (typeof finalSrc !== 'string') return null + + return ( + <> + + {useMetadataRender(props)} + + ) +}) diff --git a/packages/typed-message/dom/Renderer/Core/Promise.tsx b/packages/typed-message/dom/Renderer/Core/Promise.tsx new file mode 100644 index 000000000000..bacafe8b89c7 --- /dev/null +++ b/packages/typed-message/dom/Renderer/Core/Promise.tsx @@ -0,0 +1,25 @@ +import { memo, Suspense, useEffect, useState } from 'react' +import type { TypedMessagePromise } from '../../../base' +import { TypedMessageRender } from '../Entry' +import { useTransformedValue } from '../utils/TransformContext' +export const TypedMessagePromiseRenderer = memo(function TypedMessagePromiseRenderer(props: TypedMessagePromise) { + const { promise, alt } = props + const _ = useState(0)[1] + const rerender = () => _(Math.random()) + + useEffect(() => { + promise.then(rerender) + }, [promise, _]) + + const transformedValue = useTransformedValue(promise.value) + if (transformedValue) return + return ( + : null}> + + + ) +}) + +function Await(props: { promise: Promise }): JSX.Element { + throw props.promise +} diff --git a/packages/typed-message/dom/Renderer/Core/Text.tsx b/packages/typed-message/dom/Renderer/Core/Text.tsx new file mode 100644 index 000000000000..ad8efc76560e --- /dev/null +++ b/packages/typed-message/dom/Renderer/Core/Text.tsx @@ -0,0 +1,14 @@ +import { memo } from 'react' +import type { TypedMessageText } from '../../../base' +import { RenderText } from '../utils/renderText' +import { useMetadataRender } from '../MetadataRender' + +export const TypedMessageTextRenderer = memo(function TypedMessageTextRenderer(props: TypedMessageText) { + const { content } = props + return ( + <> + + {useMetadataRender(props)} + + ) +}) diff --git a/packages/typed-message/dom/Renderer/Core/Tuple.tsx b/packages/typed-message/dom/Renderer/Core/Tuple.tsx new file mode 100644 index 000000000000..a71a8333c575 --- /dev/null +++ b/packages/typed-message/dom/Renderer/Core/Tuple.tsx @@ -0,0 +1,17 @@ +import { memo, useMemo } from 'react' +import type { TypedMessageTuple } from '../../../base' +import { hasCircular } from '../utils/circularDetect' +import { TypedMessageRender } from '../Entry' +import { useMetadataRender } from '../MetadataRender' + +export const TypedMessageTupleRenderer = memo(function TypedMessageTupleRenderer(props: TypedMessageTuple) { + if (useMemo(() => hasCircular(props.items), [props.items])) return null + return ( + <> + {props.items.map((message, index) => ( + + ))} + {useMetadataRender(props)} + + ) +}) diff --git a/packages/typed-message/dom/Renderer/Core/Unknown.tsx b/packages/typed-message/dom/Renderer/Core/Unknown.tsx new file mode 100644 index 000000000000..a9c49991fea5 --- /dev/null +++ b/packages/typed-message/dom/Renderer/Core/Unknown.tsx @@ -0,0 +1,15 @@ +import { memo, useRef } from 'react' +import type { TypedMessage } from '../../../base' + +/** @internal */ +export const TypedMessageUnknownRenderer = memo(function TypedMessageUnknownRenderer(props: TypedMessage) { + const warned = useRef(false) + if (!warned.current) { + warned.current = true + console.warn( + '[@masknet/typed-message] Trying to render an unknown TypedMessage (or a known TypedMessage with no renderer) with props', + props, + ) + } + return null +}) diff --git a/packages/typed-message/dom/Renderer/Entry.tsx b/packages/typed-message/dom/Renderer/Entry.tsx new file mode 100644 index 000000000000..037d9debfd67 --- /dev/null +++ b/packages/typed-message/dom/Renderer/Entry.tsx @@ -0,0 +1,26 @@ +import { useContext } from 'react' +import type { TypedMessage } from '../../base' +import { TypedMessageUnknownRenderer as TypedMessageUnknownRender } from './Core/Unknown' +import { RegistryContext } from './utils/RegistryContext' +export interface RenderProps { + message: TypedMessage +} +export function TypedMessageRender(props: RenderProps) { + const { message } = props + const Registry = useContext(RegistryContext) + if (message.type === 'empty') return null + + const Render = Registry(message.type)?.component || TypedMessageUnknownRender + if (process.env.NODE_ENV === 'development') { + return ( + { + if (ref) (ref as any).message = message + }}> + + + ) + } + return +} diff --git a/packages/typed-message/dom/Renderer/Extension/Anchor.tsx b/packages/typed-message/dom/Renderer/Extension/Anchor.tsx new file mode 100644 index 000000000000..ada6331e1bb5 --- /dev/null +++ b/packages/typed-message/dom/Renderer/Extension/Anchor.tsx @@ -0,0 +1,14 @@ +import { memo, useContext } from 'react' +import type { TypedMessageAnchor } from '../../../base' +import { LinkDefault, MessageRenderUIComponentsContext } from '../utils/ComponentsContext' + +export const TypedMessageAnchorRenderer = memo(function TypedMessageAnchorRenderer(props: TypedMessageAnchor) { + const { content, href, category } = props + const { Link = LinkDefault! } = useContext(MessageRenderUIComponentsContext) + // Not render meta of inline component. + return ( + + {content} + + ) +}) diff --git a/packages/typed-message/dom/Renderer/MetadataRender.tsx b/packages/typed-message/dom/Renderer/MetadataRender.tsx new file mode 100644 index 000000000000..61e79947349b --- /dev/null +++ b/packages/typed-message/dom/Renderer/MetadataRender.tsx @@ -0,0 +1,13 @@ +import { useContext } from 'react' +import { MessageRenderUIComponentsContext } from './utils/ComponentsContext' +import type { TypedMessage } from '../../base' + +export interface MetadataRenderProps { + metadata: TypedMessage['meta'] + message: TypedMessage +} +export function useMetadataRender(message: TypedMessage) { + const { Metadata } = useContext(MessageRenderUIComponentsContext) + if (!Metadata || !message.meta) return null + return +} diff --git a/packages/typed-message/dom/Renderer/registry.tsx b/packages/typed-message/dom/Renderer/registry.tsx new file mode 100644 index 000000000000..f6d91cde2c59 --- /dev/null +++ b/packages/typed-message/dom/Renderer/registry.tsx @@ -0,0 +1,93 @@ +import type { + TypedMessage, + TypedMessageText, + TypedMessageImage, + TypedMessageUnknown, + TypedMessageAnchor, + TypedMessageTuple, + TypedMessagePromise, +} from '../../base' +import { TypedMessageTextRenderer } from './Core/Text' +import { TypedMessageImageRenderer } from './Core/Image' +import { TypedMessageTupleRenderer } from './Core/Tuple' +import { TypedMessagePromiseRenderer } from './Core/Promise' +import { TypedMessageUnknownRenderer } from './Core/Unknown' +import { TypedMessageAnchorRenderer } from './Extension/Anchor' + +export interface RenderConfig { + component: React.ComponentType + priority: number + id: symbol +} + +export function createTypedMessageRenderRegistry() { + const registry = new Map>>() + const event = new EventTarget() + + function registerTypedMessageRender(type: T['type'], config: RenderConfig) { + if (!registry.has(type)) registry.set(type, new Map()) + const map = registry.get(type)! + + const id = config.id + map.set(id, config) + event.dispatchEvent(new Event('update')) + return () => { + map.delete(id) + event.dispatchEvent(new Event('update')) + } + } + function getTypedMessageRender(type: T['type']): RenderConfig | undefined { + return Array.from(registry.get(type)?.values() || []).sort((a, b) => b.priority - a.priority)[0] + } + const subscription = { + // generate a new function everytime to make sure old !== new + getCurrentValue: (): typeof getTypedMessageRender => (type) => getTypedMessageRender(type), + subscribe: (f: () => void) => { + event.addEventListener('update', f) + return () => event.removeEventListener('update', f) + }, + } + + registerTypedMessageRender('text', { + component: TypedMessageTextRenderer, + id: Symbol('std.text'), + priority: 0, + }) + + registerTypedMessageRender('image', { + component: TypedMessageImageRenderer, + id: Symbol('std.image'), + priority: 0, + }) + + registerTypedMessageRender('unknown', { + component: TypedMessageUnknownRenderer, + id: Symbol('std.unknown'), + priority: 0, + }) + + registerTypedMessageRender('tuple', { + component: TypedMessageTupleRenderer, + id: Symbol('std.tuple'), + priority: 0, + }) + + registerTypedMessageRender('promise', { + component: TypedMessagePromiseRenderer, + id: Symbol('std.promise'), + priority: 0, + }) + + // Extension + registerTypedMessageRender('x-anchor', { + component: TypedMessageAnchorRenderer, + id: Symbol('std.anchor'), + priority: 0, + }) + + return { + registerTypedMessageRender, + getTypedMessageRender, + subscription, + } +} diff --git a/packages/typed-message/dom/Renderer/utils/ComponentsContext.tsx b/packages/typed-message/dom/Renderer/utils/ComponentsContext.tsx new file mode 100644 index 000000000000..a5f931e3c0d9 --- /dev/null +++ b/packages/typed-message/dom/Renderer/utils/ComponentsContext.tsx @@ -0,0 +1,40 @@ +import { createContext } from 'react' +import type { MetadataRenderProps } from '../MetadataRender' + +/** @internal */ +export const TextDefault: MessageRenderUIComponentsContext['Text'] = (props) => {props.children} +/** @internal */ +export const LinkDefault: MessageRenderUIComponentsContext['Link'] = (props) => ( + + {props.children} + +) +/** @internal */ +export const ImageDefault: MessageRenderUIComponentsContext['Image'] = (props) => + props.width === 0 ? null : + +/** @internal */ +export const MetadataDefault = () => null + +export interface MessageRenderUIComponentsContext { + Text?: React.ComponentType<{ children: string; fontSize?: number }> + Link?: React.ComponentType<{ + href?: string + category: 'normal' | 'hash' | 'cash' | 'user' + children: string + fontSize?: number + }> + Image?: React.ComponentType<{ + src: string + width?: number + height?: number + aspectRatio?: number + }> + Metadata?: React.ComponentType +} +export const MessageRenderUIComponentsContext = createContext({ + Text: TextDefault, + Link: LinkDefault, + Image: ImageDefault, + Metadata: MetadataDefault, +}) diff --git a/packages/typed-message/dom/Renderer/utils/RegistryContext.tsx b/packages/typed-message/dom/Renderer/utils/RegistryContext.tsx new file mode 100644 index 000000000000..df5c6e28c092 --- /dev/null +++ b/packages/typed-message/dom/Renderer/utils/RegistryContext.tsx @@ -0,0 +1,9 @@ +import { createContext } from 'react' +import type { RenderConfig } from '../registry' + +export const RegistryContext = createContext<(type: string) => undefined | RenderConfig>(() => { + console.error( + '[@masknet/typed-message] Please create a TypedMessageRenderRegistry and provide it via RegistryContext', + ) + return undefined +}) diff --git a/packages/typed-message/dom/Renderer/utils/TransformContext.ts b/packages/typed-message/dom/Renderer/utils/TransformContext.ts new file mode 100644 index 000000000000..7db7c987a0d9 --- /dev/null +++ b/packages/typed-message/dom/Renderer/utils/TransformContext.ts @@ -0,0 +1,16 @@ +import type { Transformer, TypedMessage } from '../../../base' +import { createContext, useContext, useMemo } from 'react' +import { emptyTransformationContext, TransformationContext } from '../../../base/transformer/context' +export const TransformerContext = createContext([ + (x) => x, + emptyTransformationContext, +]) + +export function useTransformedValue(message: TypedMessage): TypedMessage +export function useTransformedValue(message: undefined | TypedMessage): TypedMessage | undefined +export function useTransformedValue(message: undefined | TypedMessage): TypedMessage | undefined { + const [transform, context] = useContext(TransformerContext) + return useMemo(() => { + return message ? transform(message, context) : undefined + }, [message, transform, context]) +} diff --git a/packages/typed-message/dom/Renderer/utils/circularDetect.ts b/packages/typed-message/dom/Renderer/utils/circularDetect.ts new file mode 100644 index 000000000000..25292ac11d1a --- /dev/null +++ b/packages/typed-message/dom/Renderer/utils/circularDetect.ts @@ -0,0 +1,13 @@ +export function hasCircular(message: object) { + try { + JSON.stringify(message) + return false + } catch (err) { + console.warn( + '[@masknet/typed-message] TypedMessage', + message, + 'may contains circular structure. Skip rendering.', + ) + return true + } +} diff --git a/packages/typed-message/dom/Renderer/utils/renderText.tsx b/packages/typed-message/dom/Renderer/utils/renderText.tsx new file mode 100644 index 000000000000..6829e2ed25ac --- /dev/null +++ b/packages/typed-message/dom/Renderer/utils/renderText.tsx @@ -0,0 +1,39 @@ +import { memo, Fragment, createElement, useContext } from 'react' +import { MessageRenderUIComponentsContext, LinkDefault, TextDefault } from './ComponentsContext' +import { parseLink } from '../../../base/utils/parseLink' + +/** @internal */ +export interface RenderTextProps { + text: string +} + +/** @internal */ +export const RenderText = memo(function RenderText(props: RenderTextProps) { + const { Link = LinkDefault!, Text = TextDefault! } = useContext(MessageRenderUIComponentsContext) + return createElement(Fragment, {}, ...parseText(props.text, false, { Link, Text })) +}) + +function parseText( + string: string, + allowTextEnlarge: boolean, + components: Required>, +) { + const { Link, Text } = components + const fontSize = + 14 * + (allowTextEnlarge && Array.from(string).length < 45 + ? 1.5 + : allowTextEnlarge && Array.from(string).length < 85 + ? 1.2 + : 1) + const links = parseLink(string).flatMap((x) => { + if (x.type === 'text') { + return x.content + .split(/(\n)/g) + .map((x) => (x === '\n' ?
    : )) + } + if (x.category === 'normal' && !x.content.match(/^https?:\/\//gi)) x.content = 'http://' + x.content + return + }) + return links +} diff --git a/packages/typed-message/dom/index.ts b/packages/typed-message/dom/index.ts new file mode 100644 index 000000000000..4d7d34de3ec9 --- /dev/null +++ b/packages/typed-message/dom/index.ts @@ -0,0 +1,11 @@ +// Render +export { TypedMessageRender, type RenderProps } from './Renderer/Entry' +export { useMetadataRender, type MetadataRenderProps } from './Renderer/MetadataRender' + +// Render Registry +export { type RenderConfig, createTypedMessageRenderRegistry } from './Renderer/registry' +export { MessageRenderUIComponentsContext } from './Renderer/utils/ComponentsContext' +export { RegistryContext as RenderRegistryContext } from './Renderer/utils/RegistryContext' + +// Transformation +export { TransformerContext, useTransformedValue } from './Renderer/utils/TransformContext' diff --git a/packages/typed-message/dom/tsconfig.json b/packages/typed-message/dom/tsconfig.json new file mode 100644 index 000000000000..3e753ffac6e6 --- /dev/null +++ b/packages/typed-message/dom/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "rootDir": "../dom/", + "outDir": "../dist/dom", + "tsBuildInfoFile": "../dist/dom.tsbuildinfo" + }, + "include": ["./"], + "references": [{ "path": "../base/" }] +} diff --git a/packages/typed-message/package.json b/packages/typed-message/package.json new file mode 100644 index 000000000000..528eb5fe9257 --- /dev/null +++ b/packages/typed-message/package.json @@ -0,0 +1,18 @@ +{ + "name": "@masknet/typed-message", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": {}, + "dependencies": { + "@msgpack/msgpack": "^2.7.1", + "@mui/material": "link:..\\empty", + "anchorme": "^2.1.2", + "immer": "^9.0.7", + "z-schema": "^5.0.2" + }, + "exports": { + "./base": "./dist/base/index.js", + "./dom": "./dist/dom/index.js" + } +} diff --git a/packages/web3-shared/base/tsconfig.json b/packages/web3-shared/base/tsconfig.json index 07353b9b0ada..0645b741df7c 100644 --- a/packages/web3-shared/base/tsconfig.json +++ b/packages/web3-shared/base/tsconfig.json @@ -5,6 +5,6 @@ "outDir": "./dist", "tsBuildInfoFile": "./dist/src.tsbuildinfo" }, - "include": ["./src", "./src/env.d.ts", "./src/**/*.json"], + "include": ["./src", "./src/**/*.json"], "references": [{ "path": "../../injected-script/sdk" }] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 40bfc15a743a..35900461f4e2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -90,7 +90,7 @@ importers: devDependencies: '@commitlint/cli': 16.1.0 '@commitlint/config-conventional': 16.0.0 - '@dimensiondev/eslint-plugin': 0.0.1-20220117062517-fd3cb01_24acdcee9b05b2b5fa08cf9fa2608e46 + '@dimensiondev/eslint-plugin': 0.0.1-20220117073238-5be2759_24acdcee9b05b2b5fa08cf9fa2608e46 '@dimensiondev/patch-package': 6.5.0 '@jest/globals': 27.4.6 '@magic-works/i18n-codegen': 0.0.6_typescript@4.6.0-dev.20211202 @@ -245,10 +245,12 @@ importers: specifiers: '@dimensiondev/stego-js': 0.11.1-20201027083223-8ab41be '@masknet/shared-base': workspace:* + '@masknet/typed-message': workspace:* '@msgpack/msgpack': ^2.7.0 dependencies: '@dimensiondev/stego-js': 0.11.1-20201027083223-8ab41be '@masknet/shared-base': link:../shared-base + '@masknet/typed-message': link:../typed-message '@msgpack/msgpack': 2.7.1 packages/external-plugin-previewer: @@ -259,6 +261,14 @@ importers: '@masknet/theme': link:../theme ef.js: 0.14.2 + packages/gun-utils: + specifiers: + event-iterator: ^2.0.0 + gun: ^0.2020.1234 + dependencies: + event-iterator: 2.0.0 + gun: 0.2020.1235 + packages/icons: specifiers: '@emotion/server': ^11.4.0 @@ -293,6 +303,7 @@ importers: '@masknet/dashboard': workspace:* '@masknet/encryption': workspace:^0.0.0 '@masknet/external-plugin-previewer': workspace:* + '@masknet/gun-utils': workspace:* '@masknet/icons': workspace:* '@masknet/injected-script': workspace:* '@masknet/plugin-dao': workspace:* @@ -309,6 +320,7 @@ importers: '@masknet/shared': workspace:* '@masknet/shared-base': workspace:* '@masknet/theme': workspace:* + '@masknet/typed-message': workspace:* '@masknet/web3-contracts': workspace:* '@masknet/web3-providers': workspace:* '@masknet/web3-shared-base': workspace:* @@ -362,7 +374,6 @@ importers: fuse.js: ^6.5.3 graphql: ^15.5.1 graphql-request: ^3.4.0 - gun: ^0.2020.1234 history: ^5.2.0 html-webpack-plugin: ^5.5.0 https-browserify: ^1.0.0 @@ -374,7 +385,6 @@ importers: jsbi: 3.1.4 json-stable-stringify: ^1.0.1 json2csv: ^5.0.6 - jsx-jsonml-devtools-renderer: ^1.4.3 millify: ^4.0.0 next-tick: ^1.0.0 opensea-js: ^1.2.7 @@ -430,6 +440,7 @@ importers: '@masknet/dashboard': link:../dashboard '@masknet/encryption': link:../encryption '@masknet/external-plugin-previewer': link:../external-plugin-previewer + '@masknet/gun-utils': link:../gun-utils '@masknet/icons': link:../icons '@masknet/injected-script': link:../injected-script '@masknet/plugin-dao': link:../plugins/DAO @@ -446,6 +457,7 @@ importers: '@masknet/shared': link:../shared '@masknet/shared-base': link:../shared-base '@masknet/theme': link:../theme + '@masknet/typed-message': link:../typed-message '@masknet/web3-contracts': link:../web3-contracts '@masknet/web3-providers': link:../web3-providers '@masknet/web3-shared-base': link:../web3-shared/base @@ -459,7 +471,7 @@ importers: '@types/elliptic': 6.4.14 '@types/json-stable-stringify': 1.0.33 '@types/json2csv': 5.0.3 - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/react-highlight-words': 0.16.4 '@types/react-router-dom': 5.3.3 '@types/react-virtualized-auto-sizer': 1.0.1 @@ -492,7 +504,6 @@ importers: fuse.js: 6.5.3 graphql: 15.5.3 graphql-request: 3.5.0_graphql@15.5.3 - gun: 0.2020.1234 history: 5.2.0 https-browserify: 1.0.0 i18next-browser-languagedetector: 6.1.3 @@ -503,7 +514,6 @@ importers: jsbi: 3.1.4 json-stable-stringify: 1.0.1 json2csv: 5.0.6 - jsx-jsonml-devtools-renderer: 1.4.3 millify: 4.0.0 next-tick: 1.1.0 opensea-js: 1.2.7 @@ -575,9 +585,11 @@ importers: packages/plugin-infra: specifiers: '@dimensiondev/holoflows-kit': ^0.9.0-20210902104757-7c3d0d0 + '@masknet/encryption': workspace:^* '@masknet/shared': workspace:* '@masknet/shared-base': workspace:* '@masknet/theme': workspace:* + '@masknet/typed-message': workspace:* '@masknet/web3-shared-base': workspace:* '@servie/events': ^3.0.0 '@types/use-subscription': ^1.0.0 @@ -588,9 +600,11 @@ importers: use-subscription: ^1.5.1 dependencies: '@dimensiondev/holoflows-kit': 0.9.0-20210902104757-7c3d0d0 + '@masknet/encryption': link:../encryption '@masknet/shared': link:../shared '@masknet/shared-base': link:../shared-base '@masknet/theme': link:../theme + '@masknet/typed-message': link:../typed-message '@masknet/web3-shared-base': link:../web3-shared/base '@servie/events': 3.0.0 '@types/use-subscription': 1.0.0 @@ -659,6 +673,7 @@ importers: '@masknet/shared': workspace:* '@masknet/shared-base': workspace:* '@masknet/theme': workspace:* + '@masknet/typed-message': workspace:* '@msgpack/msgpack': ^2.7.1 arweave: ^1.10.3 date-fns: ^2.28.0 @@ -673,6 +688,7 @@ importers: '@masknet/shared': link:../../shared '@masknet/shared-base': link:../../shared-base '@masknet/theme': link:../../theme + '@masknet/typed-message': link:../../typed-message '@msgpack/msgpack': 2.7.1 arweave: 1.10.13 date-fns: 2.28.0 @@ -768,7 +784,7 @@ importers: '@metaplex-foundation/mpl-token-metadata': 1.1.0 '@metaplex/js': 4.11.7 '@solana/spl-token': 0.1.8 - '@solana/spl-token-registry': 0.2.1301 + '@solana/spl-token-registry': 0.2.1550 '@solana/web3.js': 1.31.0 bignumber.js: 9.0.2 bn.js: 4.12.0 @@ -828,7 +844,7 @@ importers: '@rollup/plugin-json': 4.1.0_rollup@2.66.1 '@rollup/plugin-node-resolve': 13.1.3_rollup@2.66.1 '@rollup/plugin-sucrase': 4.0.2_rollup@2.66.1 - '@types/node': 16.11.21 + '@types/node': 16.11.17 core-js-builder: 3.20.3 rollup: 2.66.1 rollup-plugin-terser: 7.0.2_rollup@2.66.1 @@ -936,6 +952,7 @@ importers: packages/shared-base: specifiers: '@dimensiondev/holoflows-kit': ^0.9.0-20210902104757-7c3d0d0 + '@masknet/typed-message': workspace:* '@msgpack/msgpack': ^2.7.1 '@mui/icons-material': link:..\empty '@mui/lab': link:..\empty @@ -957,6 +974,7 @@ importers: z-schema: ^5.0.2 dependencies: '@dimensiondev/holoflows-kit': 0.9.0-20210902104757-7c3d0d0 + '@masknet/typed-message': link:../typed-message '@msgpack/msgpack': 2.7.1 '@mui/icons-material': link:../empty '@mui/lab': link:../empty @@ -1033,6 +1051,20 @@ importers: '@storybook/react': 6.4.14_7122d2cc33d84542a3dd23dd5171c285 babel-loader: 8.2.3_e748cba1f5e972defd8ae51292b4033f + packages/typed-message: + specifiers: + '@msgpack/msgpack': ^2.7.1 + '@mui/material': link:..\empty + anchorme: ^2.1.2 + immer: ^9.0.7 + z-schema: ^5.0.2 + dependencies: + '@msgpack/msgpack': 2.7.1 + '@mui/material': link:../empty + anchorme: 2.1.2 + immer: 9.0.7 + z-schema: 5.0.2 + packages/web3-constants: specifiers: {} @@ -1239,7 +1271,7 @@ packages: engines: {node: '>=6.12'} dependencies: '@0xproject/typescript-typings': 0.3.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 jsonschema: 1.4.0 lodash.values: 4.3.0 dev: false @@ -1255,7 +1287,7 @@ packages: resolution: {integrity: sha1-+tE5Je6SrU7hmAZopcsr7U3Kq48=} engines: {node: '>=6.12'} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 bignumber.js: 4.1.0 dev: false @@ -1301,6 +1333,13 @@ packages: web3: 0.20.7 dev: false + /@babel/code-frame/7.15.8: + resolution: {integrity: sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.14.5 + dev: true + /@babel/code-frame/7.16.0: resolution: {integrity: sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==} engines: {node: '>=6.9.0'} @@ -1313,9 +1352,15 @@ packages: dependencies: '@babel/highlight': 7.16.10 - /@babel/compat-data/7.16.8: - resolution: {integrity: sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q==} + /@babel/compat-data/7.16.0: + resolution: {integrity: sha512-DGjt2QZse5SGd9nfOSqO4WLJ8NN/oHkijbXbPrxuoJO3oIPJL3TciZs9FX+cOHNiY9E9l0opL8g7BmLe3T+9ew==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/compat-data/7.16.4: + resolution: {integrity: sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==} engines: {node: '>=6.9.0'} + dev: true /@babel/core/7.12.9: resolution: {integrity: sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==} @@ -1334,7 +1379,7 @@ packages: gensync: 1.0.0-beta.2 json5: 2.2.0 lodash: 4.17.21 - resolve: 1.22.0 + resolve: 1.20.0 semver: 5.7.1 source-map: 0.5.7 transitivePeerDependencies: @@ -1364,6 +1409,15 @@ packages: - supports-color dev: true + /@babel/generator/7.16.0: + resolution: {integrity: sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + jsesc: 2.5.2 + source-map: 0.5.7 + dev: false + /@babel/generator/7.16.8: resolution: {integrity: sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==} engines: {node: '>=6.9.0'} @@ -1371,60 +1425,74 @@ packages: '@babel/types': 7.16.8 jsesc: 2.5.2 source-map: 0.5.7 + dev: true - /@babel/helper-annotate-as-pure/7.16.7: - resolution: {integrity: sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==} + /@babel/helper-annotate-as-pure/7.16.0: + resolution: {integrity: sha512-ItmYF9vR4zA8cByDocY05o0LGUkp1zhbTQOH1NFyl5xXEqlTJQCEJjieriw+aFpxo16swMxUnUiKS7a/r4vtHg==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.16.8 dev: true - /@babel/helper-builder-binary-assignment-operator-visitor/7.16.7: - resolution: {integrity: sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==} + /@babel/helper-builder-binary-assignment-operator-visitor/7.16.0: + resolution: {integrity: sha512-9KuleLT0e77wFUku6TUkqZzCEymBdtuQQ27MhEKzf9UOOJu3cYj98kyaDAzxpC7lV6DGiZFuC8XqDsq8/Kl6aQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-explode-assignable-expression': 7.16.7 + '@babel/helper-explode-assignable-expression': 7.16.0 '@babel/types': 7.16.8 dev: true + /@babel/helper-compilation-targets/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-S7iaOT1SYlqK0sQaCi21RX4+13hmdmnxIEAnQUB/eh7GeAnRjOUgTYpLkUOiRXzD+yog1JxP0qyAQZ7ZxVxLVg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.16.0 + '@babel/core': 7.16.12 + '@babel/helper-validator-option': 7.14.5 + browserslist: 4.18.1 + semver: 6.3.0 + dev: false + /@babel/helper-compilation-targets/7.16.7_@babel+core@7.16.12: resolution: {integrity: sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/compat-data': 7.16.8 + '@babel/compat-data': 7.16.4 '@babel/core': 7.16.12 '@babel/helper-validator-option': 7.16.7 browserslist: 4.19.1 semver: 6.3.0 + dev: true - /@babel/helper-create-class-features-plugin/7.16.10_@babel+core@7.16.12: - resolution: {integrity: sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg==} + /@babel/helper-create-class-features-plugin/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-XLwWvqEaq19zFlF5PTgOod4bUA+XbkR4WLQBct1bkzmxJGB0ZEJaoKF4c8cgH9oBtCDuYJ8BP5NB9uFiEgO5QA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-annotate-as-pure': 7.16.7 - '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.0 '@babel/helper-function-name': 7.16.7 - '@babel/helper-member-expression-to-functions': 7.16.7 - '@babel/helper-optimise-call-expression': 7.16.7 - '@babel/helper-replace-supers': 7.16.7 + '@babel/helper-member-expression-to-functions': 7.16.0 + '@babel/helper-optimise-call-expression': 7.16.0 + '@babel/helper-replace-supers': 7.16.0 '@babel/helper-split-export-declaration': 7.16.7 transitivePeerDependencies: - supports-color dev: true - /@babel/helper-create-regexp-features-plugin/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g==} + /@babel/helper-create-regexp-features-plugin/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-3DyG0zAFAZKcOp7aVr33ddwkxJ0Z0Jr5V99y3I690eYLpukJsJvAbzTy1ewoCqsML8SbIrjH14Jc/nSQ4TvNPA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.0 regexpu-core: 4.8.0 dev: true @@ -1436,47 +1504,65 @@ packages: '@babel/core': 7.16.12 '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.12 '@babel/helper-module-imports': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/traverse': 7.16.10 debug: 4.3.3 lodash.debounce: 4.0.8 - resolve: 1.22.0 + resolve: 1.20.0 semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true + /@babel/helper-define-polyfill-provider/0.2.3_@babel+core@7.16.12: + resolution: {integrity: sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==} + peerDependencies: + '@babel/core': ^7.4.0-0 + dependencies: + '@babel/core': 7.16.12 + '@babel/helper-compilation-targets': 7.16.0_@babel+core@7.16.12 + '@babel/helper-module-imports': 7.16.0 + '@babel/helper-plugin-utils': 7.14.5 + '@babel/traverse': 7.16.0 + debug: 4.3.2 + lodash.debounce: 4.0.8 + resolve: 1.20.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: false + /@babel/helper-define-polyfill-provider/0.2.4_@babel+core@7.16.12: resolution: {integrity: sha512-OrpPZ97s+aPi6h2n1OXzdhVis1SGSsMU2aMHgLcOKfsp4/v1NWpx3CWT3lBj5eeBq9cDkPkh+YCfdF7O12uNDQ==} peerDependencies: '@babel/core': ^7.4.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.12 + '@babel/helper-compilation-targets': 7.16.0_@babel+core@7.16.12 '@babel/helper-module-imports': 7.16.0 - '@babel/helper-plugin-utils': 7.16.5 - '@babel/traverse': 7.16.10 - debug: 4.3.3 + '@babel/helper-plugin-utils': 7.14.5 + '@babel/traverse': 7.16.0 + debug: 4.3.2 lodash.debounce: 4.0.8 - resolve: 1.22.0 + resolve: 1.20.0 semver: 6.3.0 transitivePeerDependencies: - supports-color dev: false - /@babel/helper-define-polyfill-provider/0.3.1_@babel+core@7.16.12: - resolution: {integrity: sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==} + /@babel/helper-define-polyfill-provider/0.3.0_@babel+core@7.16.12: + resolution: {integrity: sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==} peerDependencies: '@babel/core': ^7.4.0-0 dependencies: '@babel/core': 7.16.12 '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.12 '@babel/helper-module-imports': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/traverse': 7.16.10 debug: 4.3.3 lodash.debounce: 4.0.8 - resolve: 1.22.0 + resolve: 1.20.0 semver: 6.3.0 transitivePeerDependencies: - supports-color @@ -1487,14 +1573,24 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.16.8 + dev: true - /@babel/helper-explode-assignable-expression/7.16.7: - resolution: {integrity: sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==} + /@babel/helper-explode-assignable-expression/7.16.0: + resolution: {integrity: sha512-Hk2SLxC9ZbcOhLpg/yMznzJ11W++lg5GMbxt1ev6TXUiJB0N42KPC+7w8a+eWGuqDnUYuwStJoZHM7RgmIOaGQ==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.16.8 dev: true + /@babel/helper-function-name/7.16.0: + resolution: {integrity: sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-get-function-arity': 7.16.0 + '@babel/template': 7.16.0 + '@babel/types': 7.16.0 + dev: false + /@babel/helper-function-name/7.16.7: resolution: {integrity: sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==} engines: {node: '>=6.9.0'} @@ -1502,21 +1598,38 @@ packages: '@babel/helper-get-function-arity': 7.16.7 '@babel/template': 7.16.7 '@babel/types': 7.16.8 + dev: true + + /@babel/helper-get-function-arity/7.16.0: + resolution: {integrity: sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + dev: false /@babel/helper-get-function-arity/7.16.7: resolution: {integrity: sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.16.8 + dev: true + + /@babel/helper-hoist-variables/7.16.0: + resolution: {integrity: sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + dev: false /@babel/helper-hoist-variables/7.16.7: resolution: {integrity: sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.16.8 + dev: true - /@babel/helper-member-expression-to-functions/7.16.7: - resolution: {integrity: sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==} + /@babel/helper-member-expression-to-functions/7.16.0: + resolution: {integrity: sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.16.8 @@ -1526,7 +1639,7 @@ packages: resolution: {integrity: sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.16.8 + '@babel/types': 7.16.0 dev: false /@babel/helper-module-imports/7.16.7: @@ -1552,8 +1665,8 @@ packages: - supports-color dev: true - /@babel/helper-optimise-call-expression/7.16.7: - resolution: {integrity: sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==} + /@babel/helper-optimise-call-expression/7.16.0: + resolution: {integrity: sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.16.8 @@ -1566,36 +1679,29 @@ packages: /@babel/helper-plugin-utils/7.14.5: resolution: {integrity: sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==} engines: {node: '>=6.9.0'} - dev: false /@babel/helper-plugin-utils/7.16.5: resolution: {integrity: sha512-59KHWHXxVA9K4HNF4sbHCf+eJeFe0Te/ZFGqBT4OjXhrwvA04sGfaEGsVTdsjoszq0YTP49RC9UKe5g8uN2RwQ==} engines: {node: '>=6.9.0'} - dev: false - - /@babel/helper-plugin-utils/7.16.7: - resolution: {integrity: sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==} - engines: {node: '>=6.9.0'} dev: true - /@babel/helper-remap-async-to-generator/7.16.8: - resolution: {integrity: sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==} + /@babel/helper-remap-async-to-generator/7.16.4: + resolution: {integrity: sha512-vGERmmhR+s7eH5Y/cp8PCVzj4XEjerq8jooMfxFdA5xVtAk9Sh4AQsrWgiErUEBjtGrBtOFKDUcWQFW4/dFwMA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-annotate-as-pure': 7.16.7 - '@babel/helper-wrap-function': 7.16.8 + '@babel/helper-annotate-as-pure': 7.16.0 + '@babel/helper-wrap-function': 7.16.0 '@babel/types': 7.16.8 transitivePeerDependencies: - supports-color dev: true - /@babel/helper-replace-supers/7.16.7: - resolution: {integrity: sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==} + /@babel/helper-replace-supers/7.16.0: + resolution: {integrity: sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-environment-visitor': 7.16.7 - '@babel/helper-member-expression-to-functions': 7.16.7 - '@babel/helper-optimise-call-expression': 7.16.7 + '@babel/helper-member-expression-to-functions': 7.16.0 + '@babel/helper-optimise-call-expression': 7.16.0 '@babel/traverse': 7.16.10 '@babel/types': 7.16.8 transitivePeerDependencies: @@ -1616,11 +1722,19 @@ packages: '@babel/types': 7.16.8 dev: true + /@babel/helper-split-export-declaration/7.16.0: + resolution: {integrity: sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.16.0 + dev: false + /@babel/helper-split-export-declaration/7.16.7: resolution: {integrity: sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.16.8 + dev: true /@babel/helper-validator-identifier/7.15.7: resolution: {integrity: sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==} @@ -1630,12 +1744,18 @@ packages: resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==} engines: {node: '>=6.9.0'} + /@babel/helper-validator-option/7.14.5: + resolution: {integrity: sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==} + engines: {node: '>=6.9.0'} + dev: false + /@babel/helper-validator-option/7.16.7: resolution: {integrity: sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==} engines: {node: '>=6.9.0'} + dev: true - /@babel/helper-wrap-function/7.16.8: - resolution: {integrity: sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==} + /@babel/helper-wrap-function/7.16.0: + resolution: {integrity: sha512-VVMGzYY3vkWgCJML+qVLvGIam902mJW0FvT7Avj1zEe0Gn7D93aWdLblYARTxEw+6DhZmtzhBM2zv0ekE5zg1g==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-function-name': 7.16.7 @@ -1657,6 +1777,15 @@ packages: - supports-color dev: true + /@babel/highlight/7.14.5: + resolution: {integrity: sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.15.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + /@babel/highlight/7.16.0: resolution: {integrity: sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==} engines: {node: '>=6.9.0'} @@ -1677,158 +1806,171 @@ packages: resolution: {integrity: sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==} engines: {node: '>=6.0.0'} hasBin: true + dev: true + + /@babel/parser/7.16.2: + resolution: {integrity: sha512-RUVpT0G2h6rOZwqLDTrKk7ksNv7YpAilTnYe1/Q+eDjxEceRMKVWbCsX7t8h6C1qCFi/1Y8WZjcEPBAFG27GPw==} + engines: {node: '>=6.0.0'} + hasBin: true + dev: false + + /@babel/parser/7.16.6: + resolution: {integrity: sha512-Gr86ujcNuPDnNOY8mi383Hvi8IYrJVJYuf3XcuBM/Dgd+bINn/7tHqsj+tKkoreMbmGsFLsltI/JJd8fOFWGDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dev: false - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==} + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.2_@babel+core@7.16.12: + resolution: {integrity: sha512-h37CvpLSf8gb2lIJ2CgC3t+EjFbi0t8qS7LCS1xcJIlEXE4czlofwaW7W1HA8zpgOCzI9C1nmoqNR1zWkk0pQg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==} + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-4tcFwwicpWTrpl9qjf7UsoosaArgImF85AxqCRZlgc3IQDvkUHjJpruXAL58Wmj+T6fypWTC/BakfEkwIL/pwA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 - '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-proposal-optional-chaining': 7.16.0_@babel+core@7.16.12 dev: true - /@babel/plugin-proposal-async-generator-functions/7.16.8_@babel+core@7.16.12: - resolution: {integrity: sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==} + /@babel/plugin-proposal-async-generator-functions/7.16.4_@babel+core@7.16.12: + resolution: {integrity: sha512-/CUekqaAaZCQHleSK/9HajvcD/zdnJiKRiuUFq8ITE+0HsPzquf53cpFiqAwl/UfmJbR6n5uGPQSPdrmKOvHHg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 - '@babel/helper-remap-async-to-generator': 7.16.8 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/helper-remap-async-to-generator': 7.16.4 '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.16.12 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-properties/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==} + /@babel/plugin-proposal-class-properties/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-mCF3HcuZSY9Fcx56Lbn+CGdT44ioBMMvjNVldpKtj8tpniETdLjnxdHI1+sDWXIM1nNt+EanJOZ3IG9lzVjs7A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-create-class-features-plugin': 7.16.10_@babel+core@7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-create-class-features-plugin': 7.16.0_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-static-block/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==} + /@babel/plugin-proposal-class-static-block/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-mAy3sdcY9sKAkf3lQbDiv3olOfiLqI51c9DR9b19uMoR2Z6r5pmGl7dfNFqEvqOyqbf1ta4lknK4gc5PJn3mfA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-create-class-features-plugin': 7.16.10_@babel+core@7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-create-class-features-plugin': 7.16.0_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.16.12 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-decorators/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-DoEpnuXK14XV9btI1k8tzNGCutMclpj4yru8aXKoHlVmbO1s+2A+g2+h4JhcjrxkFJqzbymnLG6j/niOf3iFXQ==} + /@babel/plugin-proposal-decorators/7.16.4_@babel+core@7.16.12: + resolution: {integrity: sha512-RESBNX16eNqnBeEVR5sCJpnW0mHiNLNNvGA8PrRuK/4ZJ4TO+6bHleRUuGQYDERVySOKtOhSya/C4MIhwAMAgg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-create-class-features-plugin': 7.16.10_@babel+core@7.16.12 - '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-decorators': 7.16.7_@babel+core@7.16.12 + '@babel/helper-create-class-features-plugin': 7.16.0_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/plugin-syntax-decorators': 7.16.0_@babel+core@7.16.12 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-dynamic-import/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==} + /@babel/plugin-proposal-dynamic-import/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-QGSA6ExWk95jFQgwz5GQ2Dr95cf7eI7TKutIXXTb7B1gCLTCz5hTjFTQGfLFBBiC5WSNi7udNwWsqbbMh1c4yQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.12 dev: true - /@babel/plugin-proposal-export-default-from/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-+cENpW1rgIjExn+o5c8Jw/4BuH4eGKKYvkMB8/0ZxFQ9mC0t4z09VsPIwNg6waF69QYC81zxGeAsREGuqQoKeg==} + /@babel/plugin-proposal-export-default-from/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-kFAhaIbh5qbBwETRNa/cgGmPJ/BicXhIyrZhAkyYhf/Z9LXCTRGO1mvUwczto0Hl1q4YtzP9cRtTKT4wujm38Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-export-default-from': 7.16.7_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/plugin-syntax-export-default-from': 7.16.0_@babel+core@7.16.12 dev: true - /@babel/plugin-proposal-export-namespace-from/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==} + /@babel/plugin-proposal-export-namespace-from/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-CjI4nxM/D+5wCnhD11MHB1AwRSAYeDT+h8gCdcVJZ/OK7+wRzFsf7PFPWVpVpNRkHMmMkQWAHpTq+15IXQ1diA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.16.12 dev: true - /@babel/plugin-proposal-json-strings/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==} + /@babel/plugin-proposal-json-strings/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-kouIPuiv8mSi5JkEhzApg5Gn6hFyKPnlkO0a9YSzqRurH8wYzSlf6RJdzluAsbqecdW5pBvDJDfyDIUR/vLxvg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.16.12 dev: true - /@babel/plugin-proposal-logical-assignment-operators/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==} + /@babel/plugin-proposal-logical-assignment-operators/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-pbW0fE30sVTYXXm9lpVQQ/Vc+iTeQKiXlaNRZPPN2A2VdlWyAtsUrsQ3xydSlDW00TFMK7a8m3cDTkBF5WnV3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.16.12 dev: true - /@babel/plugin-proposal-nullish-coalescing-operator/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==} + /@babel/plugin-proposal-nullish-coalescing-operator/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-3bnHA8CAFm7cG93v8loghDYyQ8r97Qydf63BeYiGgYbjKKB/XP53W15wfRC7dvKfoiJ34f6Rbyyx2btExc8XsQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.16.12 dev: true - /@babel/plugin-proposal-numeric-separator/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==} + /@babel/plugin-proposal-numeric-separator/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-FAhE2I6mjispy+vwwd6xWPyEx3NYFS13pikDBWUAFGZvq6POGs5eNchw8+1CYoEgBl9n11I3NkzD7ghn25PQ9Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.16.12 dev: true @@ -1838,85 +1980,85 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.9 - '@babel/helper-plugin-utils': 7.10.4 + '@babel/helper-plugin-utils': 7.16.5 '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.12.9 - '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.12.9 + '@babel/plugin-transform-parameters': 7.16.3_@babel+core@7.12.9 dev: true - /@babel/plugin-proposal-object-rest-spread/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA==} + /@babel/plugin-proposal-object-rest-spread/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-LU/+jp89efe5HuWJLmMmFG0+xbz+I2rSI7iLc1AlaeSMDMOGzWlc5yJrMN1d04osXN4sSfpo4O+azkBNBes0jg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.16.8 + '@babel/compat-data': 7.16.4 '@babel/core': 7.16.12 '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.16.12 - '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-transform-parameters': 7.16.3_@babel+core@7.16.12 dev: true - /@babel/plugin-proposal-optional-catch-binding/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==} + /@babel/plugin-proposal-optional-catch-binding/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-kicDo0A/5J0nrsCPbn89mTG3Bm4XgYi0CZtvex9Oyw7gGZE3HXGD0zpQNH+mo+tEfbo8wbmMvJftOwpmPy7aVw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.16.12 dev: true - /@babel/plugin-proposal-optional-chaining/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==} + /@babel/plugin-proposal-optional-chaining/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-Y4rFpkZODfHrVo70Uaj6cC1JJOt3Pp0MdWSwIKtb8z1/lsjl9AmnB7ErRFV+QNGIfcY1Eruc2UMx5KaRnXjMyg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.16.12 dev: true - /@babel/plugin-proposal-private-methods/7.16.11_@babel+core@7.16.12: - resolution: {integrity: sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==} + /@babel/plugin-proposal-private-methods/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-IvHmcTHDFztQGnn6aWq4t12QaBXTKr1whF/dgp9kz84X6GUcwq9utj7z2wFCUfeOup/QKnOlt2k0zxkGFx9ubg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-create-class-features-plugin': 7.16.10_@babel+core@7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-create-class-features-plugin': 7.16.0_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-private-property-in-object/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==} + /@babel/plugin-proposal-private-property-in-object/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-3jQUr/HBbMVZmi72LpjQwlZ55i1queL8KcDTQEkAHihttJnAPrcvG9ZNXIfsd2ugpizZo595egYV6xy+pv4Ofw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-annotate-as-pure': 7.16.7 - '@babel/helper-create-class-features-plugin': 7.16.10_@babel+core@7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.0 + '@babel/helper-create-class-features-plugin': 7.16.0_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.16.12 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-unicode-property-regex/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==} + /@babel/plugin-proposal-unicode-property-regex/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-ti7IdM54NXv29cA4+bNNKEMS4jLMCbJgl+Drv+FgYy0erJLAxNAIXcNjNjrRZEcWq0xJHsNVwQezskMFpF8N9g==} engines: {node: '>=4'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-create-regexp-features-plugin': 7.16.0_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.16.12: @@ -1925,7 +2067,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.16.12: @@ -1934,7 +2076,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.16.12: @@ -1943,7 +2085,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.16.12: @@ -1953,17 +2095,17 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-syntax-decorators/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-vQ+PxL+srA7g6Rx6I1e15m55gftknl2X8GCUW1JTlkTaXZLJOS0UcaY0eK9jYT7IYf4awn6qwyghVHLDz1WyMw==} + /@babel/plugin-syntax-decorators/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-nxnnngZClvlY13nHJAIDow0S7Qzhq64fQ/NlqS+VER3kjW/4F0jLhXjeL8jcwSwz6Ca3rotT5NJD2T9I7lcv7g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.16.12: @@ -1972,17 +2114,17 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-syntax-export-default-from/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-4C3E4NsrLOgftKaTYTULhHsuQrGv3FHrBzOMDiS7UYKIpgGBkAdawg4h+EI8zPeK9M0fiIIh72hIwsI24K7MbA==} + /@babel/plugin-syntax-export-default-from/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-xllLOdBj77mFSw8s02I+2SSQGHOftbWTlGmagheuNk/gjQsk7IrYsR/EosXVAVpgIUFffLckB/iPRioQYLHSrQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.16.12: @@ -1991,26 +2133,26 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-syntax-flow/7.16.7: - resolution: {integrity: sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ==} + /@babel/plugin-syntax-flow/7.16.0: + resolution: {integrity: sha512-dH91yCo0RyqfzWgoM5Ji9ir8fQ+uFbt9KHM3d2x4jZOuHS6wNA+CRmRUP/BWCsHG2bjc7A2Way6AvH1eQk0wig==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-syntax-flow/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ==} + /@babel/plugin-syntax-flow/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-dH91yCo0RyqfzWgoM5Ji9ir8fQ+uFbt9KHM3d2x4jZOuHS6wNA+CRmRUP/BWCsHG2bjc7A2Way6AvH1eQk0wig==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.16.12: @@ -2019,7 +2161,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.16.12: @@ -2028,7 +2170,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-jsx/7.12.1_@babel+core@7.12.9: @@ -2037,7 +2179,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.9 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-jsx/7.16.0: @@ -2047,25 +2189,15 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/helper-plugin-utils': 7.14.5 - dev: false - /@babel/plugin-syntax-jsx/7.16.7: - resolution: {integrity: sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/helper-plugin-utils': 7.16.7 - dev: true - - /@babel/plugin-syntax-jsx/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==} + /@babel/plugin-syntax-jsx/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-8zv2+xiPHwly31RK4RmnEYY5zziuF3O7W2kIDW+07ewWDh6Oi0dRq8kwvulRkFgt6DB97RlKs5c1y068iPlCUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.14.5 dev: true /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.16.12: @@ -2074,7 +2206,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.16.12: @@ -2083,7 +2215,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.16.12: @@ -2092,7 +2224,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.12.9: @@ -2101,7 +2233,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.9 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.16.12: @@ -2110,7 +2242,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.16.12: @@ -2119,7 +2251,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.16.12: @@ -2128,7 +2260,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.16.12: @@ -2138,7 +2270,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.16.12: @@ -2148,228 +2280,226 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-syntax-typescript/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==} + /@babel/plugin-syntax-typescript/7.16.5_@babel+core@7.16.12: + resolution: {integrity: sha512-/d4//lZ1Vqb4mZ5xTep3dDK888j7BGM/iKqBmndBaoYAFPlPKrGU608VVBz5JeyAb6YQDjRu1UKqj86UhwWVgw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-arrow-functions/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==} + /@babel/plugin-transform-arrow-functions/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-vIFb5250Rbh7roWARvCLvIJ/PtAU5Lhv7BtZ1u24COwpI9Ypjsh+bZcKk6rlIyalK+r0jOc1XQ8I4ovNxNrWrA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-async-to-generator/7.16.8_@babel+core@7.16.12: - resolution: {integrity: sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==} + /@babel/plugin-transform-async-to-generator/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-PbIr7G9kR8tdH6g8Wouir5uVjklETk91GMVSUq+VaOgiinbCkBP6Q7NN/suM/QutZkMJMvcyAriogcYAdhg8Gw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 '@babel/helper-module-imports': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 - '@babel/helper-remap-async-to-generator': 7.16.8 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/helper-remap-async-to-generator': 7.16.4 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-block-scoped-functions/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==} + /@babel/plugin-transform-block-scoped-functions/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-V14As3haUOP4ZWrLJ3VVx5rCnrYhMSHN/jX7z6FAt5hjRkLsb0snPCmJwSOML5oxkKO4FNoNv7V5hw/y2bjuvg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-block-scoping/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==} + /@babel/plugin-transform-block-scoping/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-27n3l67/R3UrXfizlvHGuTwsRIFyce3D/6a37GRxn28iyTPvNXaW4XvznexRh1zUNLPjbLL22Id0XQElV94ruw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-classes/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==} + /@babel/plugin-transform-classes/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-HUxMvy6GtAdd+GKBNYDWCIA776byUQH8zjnfjxwT1P1ARv/wFu8eBDpmXQcLS/IwRtrxIReGiplOwMeyO7nsDQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-annotate-as-pure': 7.16.7 - '@babel/helper-environment-visitor': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.0 '@babel/helper-function-name': 7.16.7 - '@babel/helper-optimise-call-expression': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 - '@babel/helper-replace-supers': 7.16.7 + '@babel/helper-optimise-call-expression': 7.16.0 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/helper-replace-supers': 7.16.0 '@babel/helper-split-export-declaration': 7.16.7 globals: 11.12.0 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-computed-properties/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==} + /@babel/plugin-transform-computed-properties/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-63l1dRXday6S8V3WFY5mXJwcRAnPYxvFfTlt67bwV1rTyVTM5zrp0DBBb13Kl7+ehkCVwIZPumPpFP/4u70+Tw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-destructuring/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A==} + /@babel/plugin-transform-destructuring/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-Q7tBUwjxLTsHEoqktemHBMtb3NYwyJPTJdM+wDwb0g8PZ3kQUIzNvwD5lPaqW/p54TXBc/MXZu9Jr7tbUEUM8Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-dotall-regex/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==} + /@babel/plugin-transform-dotall-regex/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-FXlDZfQeLILfJlC6I1qyEwcHK5UpRCFkaoVyA1nk9A1L1Yu583YO4un2KsLBsu3IJb4CUbctZks8tD9xPQubLw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-create-regexp-features-plugin': 7.16.0_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-duplicate-keys/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==} + /@babel/plugin-transform-duplicate-keys/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-LIe2kcHKAZOJDNxujvmp6z3mfN6V9lJxubU4fJIGoQCkKe3Ec2OcbdlYP+vW++4MpxwG0d1wSDOJtQW5kLnkZQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-exponentiation-operator/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==} + /@babel/plugin-transform-exponentiation-operator/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-OwYEvzFI38hXklsrbNivzpO3fh87skzx8Pnqi4LoSYeav0xHlueSoCJrSgTPfnbyzopo5b3YVAJkFIcUpK2wsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.16.0 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-flow-strip-types/7.16.7: - resolution: {integrity: sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg==} + /@babel/plugin-transform-flow-strip-types/7.16.0: + resolution: {integrity: sha512-vs/F5roOaO/+WxKfp9PkvLsAyj0G+Q0zbFimHm9X2KDgabN2XmNFoAafmeGEYspUlIF9+MvVmyek9UyHiqeG/w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-flow': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/plugin-syntax-flow': 7.16.0 dev: true - /@babel/plugin-transform-flow-strip-types/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg==} + /@babel/plugin-transform-flow-strip-types/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-vs/F5roOaO/+WxKfp9PkvLsAyj0G+Q0zbFimHm9X2KDgabN2XmNFoAafmeGEYspUlIF9+MvVmyek9UyHiqeG/w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-flow': 7.16.7_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/plugin-syntax-flow': 7.16.0_@babel+core@7.16.12 dev: true - /@babel/plugin-transform-for-of/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==} + /@babel/plugin-transform-for-of/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-5QKUw2kO+GVmKr2wMYSATCTTnHyscl6sxFRAY+rvN7h7WB0lcG0o4NoV6ZQU32OZGVsYUsfLGgPQpDFdkfjlJQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-function-name/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==} + /@babel/plugin-transform-function-name/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-lBzMle9jcOXtSOXUpc7tvvTpENu/NuekNJVova5lCCWCV9/U1ho2HH2y0p6mBg8fPm/syEAbfaaemYGOHCY3mg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.12 '@babel/helper-function-name': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-literals/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==} + /@babel/plugin-transform-literals/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-gQDlsSF1iv9RU04clgXqRjrPyyoJMTclFt3K1cjLmTKikc0s/6vE3hlDeEVC71wLTRu72Fq7650kABrdTc2wMQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-member-expression-literals/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==} + /@babel/plugin-transform-member-expression-literals/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-WRpw5HL4Jhnxw8QARzRvwojp9MIE7Tdk3ez6vRyUk1MwgjJN0aNpRoXainLR5SgxmoXx/vsXGZ6OthP6t/RbUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-modules-amd/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==} + /@babel/plugin-transform-modules-amd/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-rWFhWbCJ9Wdmzln1NmSCqn7P0RAD+ogXG/bd9Kg5c7PKWkJtkiXmYsMBeXjDlzHpVTJ4I/hnjs45zX4dEv81xw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 '@babel/helper-module-transforms': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 babel-plugin-dynamic-import-node: 2.3.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-commonjs/7.16.8_@babel+core@7.16.12: - resolution: {integrity: sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==} + /@babel/plugin-transform-modules-commonjs/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-Dzi+NWqyEotgzk/sb7kgQPJQf7AJkQBWsVp1N6JWc1lBVo0vkElUnGdr1PzUBmfsCCN5OOFya3RtpeHk15oLKQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 '@babel/helper-module-transforms': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/helper-simple-access': 7.16.7 babel-plugin-dynamic-import-node: 2.3.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-systemjs/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==} + /@babel/plugin-transform-modules-systemjs/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-yuGBaHS3lF1m/5R+6fjIke64ii5luRUg97N2wr+z1sF0V+sNSXPxXDdEEL/iYLszsN5VKxVB1IPfEqhzVpiqvg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2377,177 +2507,177 @@ packages: '@babel/core': 7.16.12 '@babel/helper-hoist-variables': 7.16.7 '@babel/helper-module-transforms': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/helper-validator-identifier': 7.16.7 babel-plugin-dynamic-import-node: 2.3.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-umd/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==} + /@babel/plugin-transform-modules-umd/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-nx4f6no57himWiHhxDM5pjwhae5vLpTK2zCnDH8+wNLJy0TVER/LJRHl2bkt6w9Aad2sPD5iNNoUpY3X9sTGDg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 '@babel/helper-module-transforms': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-named-capturing-groups-regex/7.16.8_@babel+core@7.16.12: - resolution: {integrity: sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==} + /@babel/plugin-transform-named-capturing-groups-regex/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-LogN88uO+7EhxWc8WZuQ8vxdSyVGxhkh8WTC3tzlT8LccMuQdA81e9SGV6zY7kY2LjDhhDOFdQVxdGwPyBCnvg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.12 + '@babel/helper-create-regexp-features-plugin': 7.16.0_@babel+core@7.16.12 dev: true - /@babel/plugin-transform-new-target/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==} + /@babel/plugin-transform-new-target/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-fhjrDEYv2DBsGN/P6rlqakwRwIp7rBGLPbrKxwh7oVt5NNkIhZVOY2GRV+ULLsQri1bDqwDWnU3vhlmx5B2aCw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-object-super/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==} + /@babel/plugin-transform-object-super/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-fds+puedQHn4cPLshoHcR1DTMN0q1V9ou0mUjm8whx9pGcNvDrVVrgw+KJzzCaiTdaYhldtrUps8DWVMgrSEyg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 - '@babel/helper-replace-supers': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/helper-replace-supers': 7.16.0 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-parameters/7.16.7_@babel+core@7.12.9: - resolution: {integrity: sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==} + /@babel/plugin-transform-parameters/7.16.3_@babel+core@7.12.9: + resolution: {integrity: sha512-3MaDpJrOXT1MZ/WCmkOFo7EtmVVC8H4EUZVrHvFOsmwkk4lOjQj8rzv8JKUZV4YoQKeoIgk07GO+acPU9IMu/w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.9 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-parameters/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==} + /@babel/plugin-transform-parameters/7.16.3_@babel+core@7.16.12: + resolution: {integrity: sha512-3MaDpJrOXT1MZ/WCmkOFo7EtmVVC8H4EUZVrHvFOsmwkk4lOjQj8rzv8JKUZV4YoQKeoIgk07GO+acPU9IMu/w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-property-literals/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==} + /@babel/plugin-transform-property-literals/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-XLldD4V8+pOqX2hwfWhgwXzGdnDOThxaNTgqagOcpBgIxbUvpgU2FMvo5E1RyHbk756WYgdbS0T8y0Cj9FKkWQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-react-display-name/7.16.7: - resolution: {integrity: sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==} + /@babel/plugin-transform-react-display-name/7.16.0: + resolution: {integrity: sha512-FJFdJAqaCpndL+pIf0aeD/qlQwT7QXOvR6Cc8JPvNhKJBi2zc/DPc4g05Y3fbD/0iWAMQFGij4+Xw+4L/BMpTg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-react-display-name/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==} + /@babel/plugin-transform-react-display-name/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-FJFdJAqaCpndL+pIf0aeD/qlQwT7QXOvR6Cc8JPvNhKJBi2zc/DPc4g05Y3fbD/0iWAMQFGij4+Xw+4L/BMpTg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-react-jsx-development/7.16.7: - resolution: {integrity: sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==} + /@babel/plugin-transform-react-jsx-development/7.16.0: + resolution: {integrity: sha512-qq65iSqBRq0Hr3wq57YG2AmW0H6wgTnIzpffTphrUWUgLCOK+zf1f7G0vuOiXrp7dU1qq+fQBoqZ3wCDAkhFzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/plugin-transform-react-jsx': 7.16.7 + '@babel/plugin-transform-react-jsx': 7.16.0 dev: true - /@babel/plugin-transform-react-jsx-development/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==} + /@babel/plugin-transform-react-jsx-development/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-qq65iSqBRq0Hr3wq57YG2AmW0H6wgTnIzpffTphrUWUgLCOK+zf1f7G0vuOiXrp7dU1qq+fQBoqZ3wCDAkhFzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-transform-react-jsx': 7.16.0_@babel+core@7.16.12 dev: true - /@babel/plugin-transform-react-jsx/7.16.7: - resolution: {integrity: sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag==} + /@babel/plugin-transform-react-jsx/7.16.0: + resolution: {integrity: sha512-rqDgIbukZ44pqq7NIRPGPGNklshPkvlmvqjdx3OZcGPk4zGIenYkxDTvl3LsSL8gqcc3ZzGmXPE6hR/u/voNOw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.0 '@babel/helper-module-imports': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-jsx': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/plugin-syntax-jsx': 7.16.0 '@babel/types': 7.16.8 dev: true - /@babel/plugin-transform-react-jsx/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag==} + /@babel/plugin-transform-react-jsx/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-rqDgIbukZ44pqq7NIRPGPGNklshPkvlmvqjdx3OZcGPk4zGIenYkxDTvl3LsSL8gqcc3ZzGmXPE6hR/u/voNOw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-annotate-as-pure': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.0 '@babel/helper-module-imports': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-jsx': 7.16.7_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/plugin-syntax-jsx': 7.16.0_@babel+core@7.16.12 '@babel/types': 7.16.8 dev: true - /@babel/plugin-transform-react-pure-annotations/7.16.7: - resolution: {integrity: sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==} + /@babel/plugin-transform-react-pure-annotations/7.16.0: + resolution: {integrity: sha512-NC/Bj2MG+t8Ef5Pdpo34Ay74X4Rt804h5y81PwOpfPtmAK3i6CizmQqwyBQzIepz1Yt8wNr2Z2L7Lu3qBMfZMA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/helper-annotate-as-pure': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.0 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-react-pure-annotations/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==} + /@babel/plugin-transform-react-pure-annotations/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-NC/Bj2MG+t8Ef5Pdpo34Ay74X4Rt804h5y81PwOpfPtmAK3i6CizmQqwyBQzIepz1Yt8wNr2Z2L7Lu3qBMfZMA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-annotate-as-pure': 7.16.7 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-annotate-as-pure': 7.16.0 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-regenerator/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==} + /@babel/plugin-transform-regenerator/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-JAvGxgKuwS2PihiSFaDrp94XOzzTUeDeOQlcKzVAyaPap7BnZXK/lvMDiubkPTdotPKOIZq9xWXWnggUMYiExg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2556,14 +2686,14 @@ packages: regenerator-transform: 0.14.5 dev: true - /@babel/plugin-transform-reserved-words/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==} + /@babel/plugin-transform-reserved-words/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-Dgs8NNCehHSvXdhEhln8u/TtJxfVwGYCgP2OOr5Z3Ar+B+zXicEOKNTyc+eca2cuEOMtjW6m9P9ijOt8QdqWkg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true /@babel/plugin-transform-runtime/7.15.0_@babel+core@7.16.12: @@ -2574,7 +2704,7 @@ packages: dependencies: '@babel/core': 7.16.12 '@babel/helper-module-imports': 7.16.0 - '@babel/helper-plugin-utils': 7.16.5 + '@babel/helper-plugin-utils': 7.14.5 babel-plugin-polyfill-corejs2: 0.2.3_@babel+core@7.16.12 babel-plugin-polyfill-corejs3: 0.2.4_@babel+core@7.16.12 babel-plugin-polyfill-regenerator: 0.2.3_@babel+core@7.16.12 @@ -2583,120 +2713,120 @@ packages: - supports-color dev: false - /@babel/plugin-transform-shorthand-properties/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==} + /@babel/plugin-transform-shorthand-properties/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-iVb1mTcD8fuhSv3k99+5tlXu5N0v8/DPm2mO3WACLG6al1CGZH7v09HJyUb1TtYl/Z+KrM6pHSIJdZxP5A+xow==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-spread/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==} + /@babel/plugin-transform-spread/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-Ao4MSYRaLAQczZVp9/7E7QHsCuK92yHRrmVNRe/SlEJjhzivq0BSn8mEraimL8wizHZ3fuaHxKH0iwzI13GyGg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 dev: true - /@babel/plugin-transform-sticky-regex/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==} + /@babel/plugin-transform-sticky-regex/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-/ntT2NljR9foobKk4E/YyOSwcGUXtYWv5tinMK/3RkypyNBNdhHUaq6Orw5DWq9ZcNlS03BIlEALFeQgeVAo4Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-template-literals/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==} + /@babel/plugin-transform-template-literals/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-Rd4Ic89hA/f7xUSJQk5PnC+4so50vBoBfxjdQAdvngwidM8jYIBVxBZ/sARxD4e0yMXRbJVDrYf7dyRtIIKT6Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-typeof-symbol/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==} + /@babel/plugin-transform-typeof-symbol/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-++V2L8Bdf4vcaHi2raILnptTBjGEFxn5315YU+e8+EqXIucA+q349qWngCLpUYqqv233suJ6NOienIVUpS9cqg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-typescript/7.16.8_@babel+core@7.16.12: - resolution: {integrity: sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==} + /@babel/plugin-transform-typescript/7.16.1_@babel+core@7.16.12: + resolution: {integrity: sha512-NO4XoryBng06jjw/qWEU2LhcLJr1tWkhpMam/H4eas/CDKMX/b2/Ylb6EI256Y7+FVPCawwSM1rrJNOpDiz+Lg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-create-class-features-plugin': 7.16.10_@babel+core@7.16.12 - '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-typescript': 7.16.7_@babel+core@7.16.12 + '@babel/helper-create-class-features-plugin': 7.16.0_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/plugin-syntax-typescript': 7.16.5_@babel+core@7.16.12 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-unicode-escapes/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==} + /@babel/plugin-transform-unicode-escapes/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-VFi4dhgJM7Bpk8lRc5CMaRGlKZ29W9C3geZjt9beuzSUrlJxsNwX7ReLwaL6WEvsOf2EQkyIJEPtF8EXjB/g2A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/plugin-transform-unicode-regex/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==} + /@babel/plugin-transform-unicode-regex/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-jHLK4LxhHjvCeZDWyA9c+P9XH1sOxRd1RO9xMtDVRAOND/PczPqizEtVdx4TQF/wyPaewqpT+tgQFYMnN/P94A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-create-regexp-features-plugin': 7.16.7_@babel+core@7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-create-regexp-features-plugin': 7.16.0_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 dev: true - /@babel/preset-env/7.16.11_@babel+core@7.16.12: - resolution: {integrity: sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==} + /@babel/preset-env/7.16.4_@babel+core@7.16.12: + resolution: {integrity: sha512-v0QtNd81v/xKj4gNKeuAerQ/azeNn/G1B1qMLeXOcV8+4TWlD2j3NV1u8q29SDFBXx/NBq5kyEAO+0mpRgacjA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.16.8 + '@babel/compat-data': 7.16.4 '@babel/core': 7.16.12 '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/helper-validator-option': 7.16.7 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-async-generator-functions': 7.16.8_@babel+core@7.16.12 - '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-class-static-block': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-dynamic-import': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-export-namespace-from': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-json-strings': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-logical-assignment-operators': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-numeric-separator': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-object-rest-spread': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-optional-catch-binding': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-private-methods': 7.16.11_@babel+core@7.16.12 - '@babel/plugin-proposal-private-property-in-object': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.16.2_@babel+core@7.16.12 + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-async-generator-functions': 7.16.4_@babel+core@7.16.12 + '@babel/plugin-proposal-class-properties': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-class-static-block': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-dynamic-import': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-export-namespace-from': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-json-strings': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-logical-assignment-operators': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-numeric-separator': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-object-rest-spread': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-optional-catch-binding': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-optional-chaining': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-private-methods': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-private-property-in-object': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-unicode-property-regex': 7.16.0_@babel+core@7.16.12 '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.16.12 '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.16.12 '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.16.12 @@ -2711,70 +2841,70 @@ packages: '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.16.12 '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.16.12 '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.16.12 - '@babel/plugin-transform-arrow-functions': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-async-to-generator': 7.16.8_@babel+core@7.16.12 - '@babel/plugin-transform-block-scoped-functions': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-computed-properties': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-destructuring': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-duplicate-keys': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-exponentiation-operator': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-for-of': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-function-name': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-literals': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-member-expression-literals': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-modules-amd': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-modules-commonjs': 7.16.8_@babel+core@7.16.12 - '@babel/plugin-transform-modules-systemjs': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-modules-umd': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-named-capturing-groups-regex': 7.16.8_@babel+core@7.16.12 - '@babel/plugin-transform-new-target': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-object-super': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-property-literals': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-regenerator': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-reserved-words': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-spread': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-sticky-regex': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-template-literals': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-typeof-symbol': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-unicode-escapes': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-unicode-regex': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-transform-arrow-functions': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-async-to-generator': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-block-scoped-functions': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-block-scoping': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-classes': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-computed-properties': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-destructuring': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-dotall-regex': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-duplicate-keys': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-exponentiation-operator': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-for-of': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-function-name': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-literals': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-member-expression-literals': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-modules-amd': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-modules-commonjs': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-modules-systemjs': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-modules-umd': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-named-capturing-groups-regex': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-new-target': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-object-super': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-parameters': 7.16.3_@babel+core@7.16.12 + '@babel/plugin-transform-property-literals': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-regenerator': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-reserved-words': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-shorthand-properties': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-spread': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-sticky-regex': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-template-literals': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-typeof-symbol': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-unicode-escapes': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-unicode-regex': 7.16.0_@babel+core@7.16.12 '@babel/preset-modules': 0.1.5_@babel+core@7.16.12 '@babel/types': 7.16.8 - babel-plugin-polyfill-corejs2: 0.3.1_@babel+core@7.16.12 - babel-plugin-polyfill-corejs3: 0.5.1_@babel+core@7.16.12 - babel-plugin-polyfill-regenerator: 0.3.1_@babel+core@7.16.12 + babel-plugin-polyfill-corejs2: 0.3.0_@babel+core@7.16.12 + babel-plugin-polyfill-corejs3: 0.4.0_@babel+core@7.16.12 + babel-plugin-polyfill-regenerator: 0.3.0_@babel+core@7.16.12 core-js-compat: 3.20.3 semver: 6.3.0 transitivePeerDependencies: - supports-color dev: true - /@babel/preset-flow/7.16.7: - resolution: {integrity: sha512-6ceP7IyZdUYQ3wUVqyRSQXztd1YmFHWI4Xv11MIqAlE4WqxBSd/FZ61V9k+TS5Gd4mkHOtQtPp9ymRpxH4y1Ug==} + /@babel/preset-flow/7.16.0: + resolution: {integrity: sha512-e5NE1EoPMpoHFkyFkMSj2h9tu7OolARcUHki8mnBv4NiFK9so+UrhbvT9mV99tMJOUEx8BOj67T6dXvGcTeYeQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/helper-validator-option': 7.16.7 - '@babel/plugin-transform-flow-strip-types': 7.16.7 + '@babel/plugin-transform-flow-strip-types': 7.16.0 dev: true - /@babel/preset-flow/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-6ceP7IyZdUYQ3wUVqyRSQXztd1YmFHWI4Xv11MIqAlE4WqxBSd/FZ61V9k+TS5Gd4mkHOtQtPp9ymRpxH4y1Ug==} + /@babel/preset-flow/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-e5NE1EoPMpoHFkyFkMSj2h9tu7OolARcUHki8mnBv4NiFK9so+UrhbvT9mV99tMJOUEx8BOj67T6dXvGcTeYeQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/helper-validator-option': 7.16.7 - '@babel/plugin-transform-flow-strip-types': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-transform-flow-strip-types': 7.16.0_@babel+core@7.16.12 dev: true /@babel/preset-modules/0.1.5_@babel+core@7.16.12: @@ -2783,58 +2913,58 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.16.12 + '@babel/helper-plugin-utils': 7.16.5 + '@babel/plugin-proposal-unicode-property-regex': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-dotall-regex': 7.16.0_@babel+core@7.16.12 '@babel/types': 7.16.8 esutils: 2.0.3 dev: true - /@babel/preset-react/7.16.7: - resolution: {integrity: sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==} + /@babel/preset-react/7.16.0: + resolution: {integrity: sha512-d31IFW2bLRB28uL1WoElyro8RH5l6531XfxMtCeCmp6RVAF1uTfxxUA0LH1tXl+psZdwfmIbwoG4U5VwgbhtLw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/helper-validator-option': 7.16.7 - '@babel/plugin-transform-react-display-name': 7.16.7 - '@babel/plugin-transform-react-jsx': 7.16.7 - '@babel/plugin-transform-react-jsx-development': 7.16.7 - '@babel/plugin-transform-react-pure-annotations': 7.16.7 + '@babel/plugin-transform-react-display-name': 7.16.0 + '@babel/plugin-transform-react-jsx': 7.16.0 + '@babel/plugin-transform-react-jsx-development': 7.16.0 + '@babel/plugin-transform-react-pure-annotations': 7.16.0 dev: true - /@babel/preset-react/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==} + /@babel/preset-react/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-d31IFW2bLRB28uL1WoElyro8RH5l6531XfxMtCeCmp6RVAF1uTfxxUA0LH1tXl+psZdwfmIbwoG4U5VwgbhtLw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/helper-validator-option': 7.16.7 - '@babel/plugin-transform-react-display-name': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-react-jsx-development': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-react-pure-annotations': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-transform-react-display-name': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-react-jsx': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-react-jsx-development': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-react-pure-annotations': 7.16.0_@babel+core@7.16.12 dev: true - /@babel/preset-typescript/7.16.7_@babel+core@7.16.12: - resolution: {integrity: sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==} + /@babel/preset-typescript/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-txegdrZYgO9DlPbv+9QOVpMnKbOtezsLHWsnsRF4AjbSIsVaujrq1qg8HK0mxQpWv0jnejt0yEoW1uWpvbrDTg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@babel/helper-validator-option': 7.16.7 - '@babel/plugin-transform-typescript': 7.16.8_@babel+core@7.16.12 + '@babel/plugin-transform-typescript': 7.16.1_@babel+core@7.16.12 transitivePeerDependencies: - supports-color dev: true - /@babel/register/7.16.9_@babel+core@7.16.12: - resolution: {integrity: sha512-jJ72wcghdRIlENfvALcyODhNoGE5j75cYHdC+aQMh6cU/P86tiiXTp9XYZct1UxUMo/4+BgQRyNZEGx0KWGS+g==} + /@babel/register/7.16.0_@babel+core@7.16.12: + resolution: {integrity: sha512-lzl4yfs0zVXnooeLE0AAfYaT7F3SPA8yB2Bj4W1BiZwLbMS3MZH35ZvCWSRHvneUugwuM+Wsnrj7h0F7UmU3NQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2843,7 +2973,7 @@ packages: clone-deep: 4.0.1 find-cache-dir: 2.1.0 make-dir: 2.1.0 - pirates: 4.0.5 + pirates: 4.0.4 source-map-support: 0.5.21 dev: true @@ -2867,11 +2997,14 @@ packages: dependencies: regenerator-runtime: 0.13.9 - /@babel/runtime/7.16.7: - resolution: {integrity: sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==} + /@babel/template/7.16.0: + resolution: {integrity: sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==} engines: {node: '>=6.9.0'} dependencies: - regenerator-runtime: 0.13.9 + '@babel/code-frame': 7.16.0 + '@babel/parser': 7.16.6 + '@babel/types': 7.16.0 + dev: false /@babel/template/7.16.7: resolution: {integrity: sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==} @@ -2880,6 +3013,24 @@ packages: '@babel/code-frame': 7.16.7 '@babel/parser': 7.16.12 '@babel/types': 7.16.8 + dev: true + + /@babel/traverse/7.16.0: + resolution: {integrity: sha512-qQ84jIs1aRQxaGaxSysII9TuDaguZ5yVrEuC0BN2vcPlalwfLovVmCjbFDPECPXcYM/wLvNFfp8uDOliLxIoUQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.16.0 + '@babel/generator': 7.16.0 + '@babel/helper-function-name': 7.16.0 + '@babel/helper-hoist-variables': 7.16.0 + '@babel/helper-split-export-declaration': 7.16.0 + '@babel/parser': 7.16.2 + '@babel/types': 7.16.0 + debug: 4.3.2 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: false /@babel/traverse/7.16.10: resolution: {integrity: sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==} @@ -2897,6 +3048,15 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color + dev: true + + /@babel/types/7.16.0: + resolution: {integrity: sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.15.7 + to-fast-properties: 2.0.0 + dev: false /@babel/types/7.16.8: resolution: {integrity: sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==} @@ -2904,6 +3064,7 @@ packages: dependencies: '@babel/helper-validator-identifier': 7.16.7 to-fast-properties: 2.0.0 + dev: true /@balancer-labs/sor/1.0.0: resolution: {integrity: sha512-EF4RvwCHGIa3gqRKMBlrq19FS4X+4g3NAJkJf9k21oIUp1XAhdV3/aMlAoJ25OigafCjPFEHn7wOHrtZNKHc3A==} @@ -3052,10 +3213,10 @@ packages: '@commitlint/types': 16.0.0 chalk: 4.1.2 cosmiconfig: 7.0.1 - cosmiconfig-typescript-loader: 1.0.4_typescript@4.5.5 + cosmiconfig-typescript-loader: 1.0.2_typescript@4.5.4 lodash: 4.17.21 resolve-from: 5.0.0 - typescript: 4.5.5 + typescript: 4.5.4 transitivePeerDependencies: - '@swc/core' - '@swc/wasm' @@ -3073,7 +3234,7 @@ packages: dependencies: '@commitlint/types': 16.0.0 conventional-changelog-angular: 5.0.13 - conventional-commits-parser: 3.2.4 + conventional-commits-parser: 3.2.3 dev: true /@commitlint/read/16.0.0: @@ -3083,7 +3244,7 @@ packages: '@commitlint/top-level': 16.0.0 '@commitlint/types': 16.0.0 fs-extra: 10.0.0 - git-raw-commits: 2.0.11 + git-raw-commits: 2.0.10 dev: true /@commitlint/resolve-extends/16.1.0: @@ -3139,7 +3300,7 @@ packages: '@cspell/dict-cpp': 1.1.40 '@cspell/dict-cryptocurrencies': 1.0.10 '@cspell/dict-csharp': 2.0.1 - '@cspell/dict-css': 1.0.13 + '@cspell/dict-css': 1.0.12 '@cspell/dict-django': 1.0.26 '@cspell/dict-dotnet': 1.0.32 '@cspell/dict-elixir': 1.0.26 @@ -3204,8 +3365,8 @@ packages: resolution: {integrity: sha512-ZzAr+WRP2FUtXHZtfhe8f3j9vPjH+5i44Hcr5JqbWxmqciGoTbWBPQXwu9y+J4mbdC69HSWRrVGkNJ8rQk8pSw==} dev: true - /@cspell/dict-css/1.0.13: - resolution: {integrity: sha512-HU8RbFRoGanFH85mT01Ot/Ay48ixr/gG25VPLtdq56QTrmPsw79gxYm/5Qay16eQbpoPIxaj5CAWNam+DX4GbA==} + /@cspell/dict-css/1.0.12: + resolution: {integrity: sha512-K6yuxej7n454O7dwKG6lHacHrAOMZ0PhMEbmV6qH2JH0U4TtWXfBASYugHvXZCDDx1UObpiJP+3tQJiBqfGpHA==} dev: true /@cspell/dict-django/1.0.26: @@ -3390,8 +3551,8 @@ packages: '@msgpack/msgpack': 1.12.2 dev: false - /@dimensiondev/eslint-plugin/0.0.1-20220117062517-fd3cb01_24acdcee9b05b2b5fa08cf9fa2608e46: - resolution: {integrity: sha512-WtUberb1MC1s554Lm3C3mno3Nf/TdVJP80htgpNWiGOcIk+WYwQi+gWqi5IlnqGd71bYRZPYpYs2MH+GS+dbuw==, tarball: download/@dimensiondev/eslint-plugin/0.0.1-20220117062517-fd3cb01/8298f20d707432bcb777cd5084173fc894362a3496e8f8bc6a5c85070adb77cf} + /@dimensiondev/eslint-plugin/0.0.1-20220117073238-5be2759_24acdcee9b05b2b5fa08cf9fa2608e46: + resolution: {integrity: sha512-/tJSdaZMWDBk/uZF7LgMNWleyqjwFFTnOP4YuTmxopZiJ6i3bTs+c9/klqqFonjPkMGf0fz1SrjI8TXmbTJmGw==, tarball: download/@dimensiondev/eslint-plugin/0.0.1-20220117073238-5be2759/5fba85c9906ce429dd110d7f4142f99b9f5532d9e5af30625becdf330d247c33} engines: {node: '>= 14'} peerDependencies: '@typescript-eslint/experimental-utils': '*' @@ -3548,7 +3709,7 @@ packages: peerDependencies: react: '>=16.3.0' dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 '@emotion/cache': 10.0.29 '@emotion/css': 10.0.27 '@emotion/serialize': 0.11.16 @@ -3659,7 +3820,7 @@ packages: '@emotion/core': ^10.0.28 react: '>=16.3.0' dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 '@emotion/core': 10.3.1_react@18.0.0-rc.0 '@emotion/is-prop-valid': 0.8.8 '@emotion/serialize': 0.11.16 @@ -3755,7 +3916,7 @@ packages: resolution: {integrity: sha512-UdkhFWzWcJCZVsj1O/H8/oqj/0RVYjLc1OhPjBrQdALAkQHpCp8xXI4WLnuGTADqTdJZww0NtgwG+TRPkXt27w==} dependencies: crc-32: 1.2.0 - ethereumjs-util: 7.1.0 + ethereumjs-util: 7.1.3 /@ethereumjs/tx/3.3.0: resolution: {integrity: sha512-yTwEj2lVzSMgE6Hjw9Oa1DZks/nKTWM8Wn4ykDNapBPua2f4nXO3qKnni86O6lgDj5fVNRqbDsD0yy7/XNGDEA==} @@ -4280,7 +4441,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 chalk: 4.1.2 jest-message-util: 27.4.6 jest-util: 27.4.2 @@ -4301,7 +4462,7 @@ packages: '@jest/test-result': 27.4.6 '@jest/transform': 27.4.6 '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.8.1 @@ -4338,7 +4499,7 @@ packages: dependencies: '@jest/fake-timers': 27.4.6 '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 jest-mock: 27.4.6 dev: true @@ -4348,7 +4509,7 @@ packages: dependencies: '@jest/types': 27.4.2 '@sinonjs/fake-timers': 8.1.0 - '@types/node': 16.11.21 + '@types/node': 16.11.17 jest-message-util: 27.4.6 jest-mock: 27.4.6 jest-util: 27.4.2 @@ -4377,7 +4538,7 @@ packages: '@jest/test-result': 27.4.6 '@jest/transform': 27.4.6 '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 @@ -4396,7 +4557,7 @@ packages: source-map: 0.6.1 string-length: 4.0.2 terminal-link: 2.1.1 - v8-to-istanbul: 8.1.1 + v8-to-istanbul: 8.1.0 transitivePeerDependencies: - supports-color dev: true @@ -4447,7 +4608,7 @@ packages: jest-regex-util: 26.0.0 jest-util: 26.6.2 micromatch: 4.0.4 - pirates: 4.0.5 + pirates: 4.0.4 slash: 3.0.0 source-map: 0.6.1 write-file-atomic: 3.0.3 @@ -4470,7 +4631,7 @@ packages: jest-regex-util: 27.4.0 jest-util: 27.4.2 micromatch: 4.0.4 - pirates: 4.0.5 + pirates: 4.0.4 slash: 3.0.0 source-map: 0.6.1 write-file-atomic: 3.0.3 @@ -4484,7 +4645,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/yargs': 15.0.14 chalk: 4.1.2 dev: true @@ -4495,7 +4656,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/yargs': 16.0.4 chalk: 4.1.2 dev: true @@ -5111,7 +5272,7 @@ packages: error-stack-parser: 2.0.6 find-up: 5.0.0 html-entities: 2.3.2 - loader-utils: 2.0.1 + loader-utils: 2.0.2 react-refresh: 0.11.0 schema-utils: 3.1.1 source-map: 0.7.3 @@ -5150,7 +5311,7 @@ packages: error-stack-parser: 2.0.6 find-up: 5.0.0 html-entities: 2.3.2 - loader-utils: 2.0.1 + loader-utils: 2.0.2 react-refresh: 0.11.0 schema-utils: 3.1.1 source-map: 0.7.3 @@ -5160,11 +5321,6 @@ packages: /@popperjs/core/2.11.0: resolution: {integrity: sha512-zrsUxjLOKAzdewIDRWy9nsV1GQsKBCWaGwsZQlCgr6/q+vjyZhFgqedLfFBuI9anTPEUT4APq9Mu0SZBTzIcGQ==} - dev: false - - /@popperjs/core/2.11.2: - resolution: {integrity: sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==} - dev: true /@portto/sdk/0.0.56-alpha.1: resolution: {integrity: sha512-EqNS5k0FMWEESn0Fn1jU0ygFkhdhQpDdmP5RjN7cDMGaYcoCG69uEArL/m4dk0JRnQ/9rITtQffTH16KSycudQ==} @@ -5272,7 +5428,7 @@ packages: builtin-modules: 3.2.0 deepmerge: 4.2.2 is-module: 1.0.0 - resolve: 1.22.0 + resolve: 1.20.0 rollup: 2.66.1 dev: true @@ -5292,7 +5448,7 @@ packages: peerDependencies: rollup: ^2.53.1 dependencies: - '@rollup/pluginutils': 4.1.2 + '@rollup/pluginutils': 4.1.1 rollup: 2.66.1 sucrase: 3.20.3 dev: true @@ -5309,12 +5465,12 @@ packages: rollup: 2.66.1 dev: true - /@rollup/pluginutils/4.1.2: - resolution: {integrity: sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ==} + /@rollup/pluginutils/4.1.1: + resolution: {integrity: sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==} engines: {node: '>= 8.0.0'} dependencies: estree-walker: 2.0.2 - picomatch: 2.3.1 + picomatch: 2.3.0 dev: true /@servie/events/1.0.0: @@ -5373,8 +5529,8 @@ packages: buffer: 6.0.3 dev: false - /@solana/spl-token-registry/0.2.1301: - resolution: {integrity: sha512-6T5AL18n9PxhGAA3useBON1DVxZg8QbrmkD9dNTzvPZQdrzSi8Hha2GmJst4kZSPAQ77l6GlcIw8ibQTAm3SZQ==} + /@solana/spl-token-registry/0.2.1550: + resolution: {integrity: sha512-q6pfwU65mWmAUtchzv65gunfGHvvVsn2bKA4NMG/XahWflafN6OF7Horjt0AOo5+rjgbHNdukF4Z/7lkSlfh8Q==} engines: {node: '>=10'} dependencies: cross-fetch: 3.0.6 @@ -5399,7 +5555,7 @@ packages: resolution: {integrity: sha512-7nHHx1JNFnrt15e9y8m38I/EJCbaB+bFC3KZVM1+QhybCikFxGMtGA5r7PDC3GEL1R2RZA8yKoLkDKo3vzzqnw==} engines: {node: '>=12.20.0'} dependencies: - '@babel/runtime': 7.16.3 + '@babel/runtime': 7.16.5 '@ethersproject/sha2': 5.5.0 '@solana/buffer-layout': 3.0.0 bn.js: 5.2.0 @@ -5407,7 +5563,7 @@ packages: bs58: 4.0.1 buffer: 6.0.1 cross-fetch: 3.1.4 - jayson: 3.6.5 + jayson: 3.6.6 js-sha3: 0.8.0 rpc-websockets: 7.4.16 secp256k1: 4.0.2 @@ -5439,8 +5595,8 @@ packages: fast-deep-equal: 3.1.3 global: 4.4.0 lodash: 4.17.21 - polished: 4.1.4 - prop-types: 15.8.1 + polished: 4.1.3 + prop-types: 15.8.0 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 react-inspector: 5.1.1_react@18.0.0-rc.0 @@ -5568,8 +5724,8 @@ packages: '@babel/core': 7.16.12 '@babel/generator': 7.16.8 '@babel/parser': 7.16.12 - '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.16.12 - '@babel/preset-env': 7.16.11_@babel+core@7.16.12 + '@babel/plugin-transform-react-jsx': 7.16.0_@babel+core@7.16.12 + '@babel/preset-env': 7.16.4_@babel+core@7.16.12 '@jest/transform': 26.6.2 '@mdx-js/loader': 1.6.22_react@18.0.0-rc.0 '@mdx-js/mdx': 1.6.22 @@ -5602,7 +5758,7 @@ packages: js-string-escape: 1.0.1 loader-utils: 2.0.2 lodash: 4.17.21 - nanoid: 3.2.0 + nanoid: 3.1.30 p-limit: 3.1.0 prettier: 2.3.0 prop-types: 15.8.1 @@ -5620,7 +5776,6 @@ packages: - '@storybook/manager-webpack5' - '@types/react' - bufferutil - - encoding - eslint - supports-color - typescript @@ -5683,7 +5838,6 @@ packages: - '@storybook/vue3' - '@types/react' - bufferutil - - encoding - eslint - lit - supports-color @@ -5717,7 +5871,7 @@ packages: core-js: 3.20.3 global: 4.4.0 prop-types: 15.8.1 - qs: 6.10.3 + qs: 6.10.2 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 regenerator-runtime: 0.13.9 @@ -5869,7 +6023,7 @@ packages: react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 regenerator-runtime: 0.13.9 - store2: 2.13.1 + store2: 2.12.0 telejson: 5.3.3 ts-dedent: 2.2.0 util-deprecate: 1.0.2 @@ -5886,26 +6040,26 @@ packages: optional: true dependencies: '@babel/core': 7.16.12 - '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-decorators': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-export-default-from': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-object-rest-spread': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-private-methods': 7.16.11_@babel+core@7.16.12 + '@babel/plugin-proposal-class-properties': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-decorators': 7.16.4_@babel+core@7.16.12 + '@babel/plugin-proposal-export-default-from': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-object-rest-spread': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-optional-chaining': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-private-methods': 7.16.0_@babel+core@7.16.12 '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.12 - '@babel/plugin-transform-arrow-functions': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-destructuring': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-for-of': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-spread': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-template-literals': 7.16.7_@babel+core@7.16.12 - '@babel/preset-env': 7.16.11_@babel+core@7.16.12 - '@babel/preset-react': 7.16.7_@babel+core@7.16.12 - '@babel/preset-typescript': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-transform-arrow-functions': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-block-scoping': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-classes': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-destructuring': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-for-of': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-parameters': 7.16.3_@babel+core@7.16.12 + '@babel/plugin-transform-shorthand-properties': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-spread': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-template-literals': 7.16.0_@babel+core@7.16.12 + '@babel/preset-env': 7.16.4_@babel+core@7.16.12 + '@babel/preset-react': 7.16.0_@babel+core@7.16.12 + '@babel/preset-typescript': 7.16.0_@babel+core@7.16.12 '@storybook/addons': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/api': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/channel-postmessage': 6.4.14 @@ -5922,7 +6076,7 @@ packages: '@storybook/store': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/theming': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/ui': 6.4.14_2f50eb45a1501445764b3dbbd8573d7c - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/webpack': 4.41.32 autoprefixer: 9.8.8 babel-loader: 8.2.3_2ca4133eaad1ede48c0159d2a9c3555f @@ -5978,26 +6132,26 @@ packages: optional: true dependencies: '@babel/core': 7.16.12 - '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-decorators': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-export-default-from': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-object-rest-spread': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-private-methods': 7.16.11_@babel+core@7.16.12 + '@babel/plugin-proposal-class-properties': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-decorators': 7.16.4_@babel+core@7.16.12 + '@babel/plugin-proposal-export-default-from': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-object-rest-spread': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-optional-chaining': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-private-methods': 7.16.0_@babel+core@7.16.12 '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.12 - '@babel/plugin-transform-arrow-functions': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-destructuring': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-for-of': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-spread': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-template-literals': 7.16.7_@babel+core@7.16.12 - '@babel/preset-env': 7.16.11_@babel+core@7.16.12 - '@babel/preset-react': 7.16.7_@babel+core@7.16.12 - '@babel/preset-typescript': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-transform-arrow-functions': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-block-scoping': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-classes': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-destructuring': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-for-of': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-parameters': 7.16.3_@babel+core@7.16.12 + '@babel/plugin-transform-shorthand-properties': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-spread': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-template-literals': 7.16.0_@babel+core@7.16.12 + '@babel/preset-env': 7.16.4_@babel+core@7.16.12 + '@babel/preset-react': 7.16.0_@babel+core@7.16.12 + '@babel/preset-typescript': 7.16.0_@babel+core@7.16.12 '@storybook/addons': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/api': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/channel-postmessage': 6.4.14 @@ -6014,7 +6168,7 @@ packages: '@storybook/store': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/theming': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/ui': 6.4.14_2f50eb45a1501445764b3dbbd8573d7c - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/webpack': 4.41.32 autoprefixer: 9.8.8 babel-loader: 8.2.3_2ca4133eaad1ede48c0159d2a9c3555f @@ -6070,25 +6224,25 @@ packages: optional: true dependencies: '@babel/core': 7.16.12 - '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-decorators': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-export-default-from': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-object-rest-spread': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-private-methods': 7.16.11_@babel+core@7.16.12 + '@babel/plugin-proposal-class-properties': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-decorators': 7.16.4_@babel+core@7.16.12 + '@babel/plugin-proposal-export-default-from': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-object-rest-spread': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-optional-chaining': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-private-methods': 7.16.0_@babel+core@7.16.12 '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.12 - '@babel/plugin-transform-arrow-functions': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-destructuring': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-for-of': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-spread': 7.16.7_@babel+core@7.16.12 - '@babel/preset-env': 7.16.11_@babel+core@7.16.12 - '@babel/preset-react': 7.16.7_@babel+core@7.16.12 - '@babel/preset-typescript': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-transform-arrow-functions': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-block-scoping': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-classes': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-destructuring': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-for-of': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-parameters': 7.16.3_@babel+core@7.16.12 + '@babel/plugin-transform-shorthand-properties': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-spread': 7.16.0_@babel+core@7.16.12 + '@babel/preset-env': 7.16.4_@babel+core@7.16.12 + '@babel/preset-react': 7.16.0_@babel+core@7.16.12 + '@babel/preset-typescript': 7.16.0_@babel+core@7.16.12 '@storybook/addons': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/api': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/channel-postmessage': 6.4.14 @@ -6104,7 +6258,7 @@ packages: '@storybook/semver': 7.3.2 '@storybook/store': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/theming': 6.4.14_757a802188413a36d4f24237d13b8e90 - '@types/node': 16.11.21 + '@types/node': 16.11.17 babel-loader: 8.2.3_e748cba1f5e972defd8ae51292b4033f babel-plugin-macros: 3.1.0 babel-plugin-polyfill-corejs3: 0.1.7_@babel+core@7.16.12 @@ -6121,7 +6275,7 @@ packages: react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 stable: 0.1.8 style-loader: 2.0.0_webpack@5.67.0 - terser-webpack-plugin: 5.3.0_webpack@5.67.0 + terser-webpack-plugin: 5.2.5_webpack@5.67.0 ts-dedent: 2.2.0 typescript: 4.6.0-dev.20211202 util-deprecate: 1.0.2 @@ -6150,7 +6304,7 @@ packages: '@storybook/core-events': 6.4.14 core-js: 3.20.3 global: 4.4.0 - qs: 6.10.3 + qs: 6.10.2 telejson: 5.3.3 dev: true @@ -6192,11 +6346,11 @@ packages: global: 4.4.0 lodash: 4.17.21 memoizerific: 1.11.3 - qs: 6.10.3 + qs: 6.10.2 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 regenerator-runtime: 0.13.9 - store2: 2.13.1 + store2: 2.12.0 synchronous-promise: 2.0.15 ts-dedent: 2.2.0 util-deprecate: 1.0.2 @@ -6215,7 +6369,7 @@ packages: react: ^16.8.0 || ^17.0.0 react-dom: ^16.8.0 || ^17.0.0 dependencies: - '@popperjs/core': 2.11.2 + '@popperjs/core': 2.11.0 '@storybook/client-logger': 6.4.14 '@storybook/csf': 0.0.2--canary.87bc651.0 '@storybook/theming': 6.4.14_757a802188413a36d4f24237d13b8e90 @@ -6227,10 +6381,10 @@ packages: fast-deep-equal: 3.1.3 global: 4.4.0 lodash: 4.17.21 - markdown-to-jsx: 7.1.6_react@18.0.0-rc.0 + markdown-to-jsx: 7.1.5_react@18.0.0-rc.0 memoizerific: 1.11.3 overlayscrollbars: 1.13.1 - polished: 4.1.4 + polished: 4.1.3 prop-types: 15.8.1 react: 18.0.0-rc.0 react-colorful: 5.5.1_757a802188413a36d4f24237d13b8e90 @@ -6271,7 +6425,7 @@ packages: core-js: 3.20.3 global: 4.4.0 lodash: 4.17.21 - qs: 6.10.3 + qs: 6.10.2 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 regenerator-runtime: 0.13.9 @@ -6310,7 +6464,7 @@ packages: core-js: 3.20.3 global: 4.4.0 lodash: 4.17.21 - qs: 6.10.3 + qs: 6.10.2 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 regenerator-runtime: 0.13.9 @@ -6334,29 +6488,29 @@ packages: optional: true dependencies: '@babel/core': 7.16.12 - '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-decorators': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-export-default-from': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-object-rest-spread': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-proposal-private-methods': 7.16.11_@babel+core@7.16.12 + '@babel/plugin-proposal-class-properties': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-decorators': 7.16.4_@babel+core@7.16.12 + '@babel/plugin-proposal-export-default-from': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-object-rest-spread': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-optional-chaining': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-proposal-private-methods': 7.16.0_@babel+core@7.16.12 '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.16.12 - '@babel/plugin-transform-arrow-functions': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-destructuring': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-for-of': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.16.12 - '@babel/plugin-transform-spread': 7.16.7_@babel+core@7.16.12 - '@babel/preset-env': 7.16.11_@babel+core@7.16.12 - '@babel/preset-react': 7.16.7_@babel+core@7.16.12 - '@babel/preset-typescript': 7.16.7_@babel+core@7.16.12 - '@babel/register': 7.16.9_@babel+core@7.16.12 + '@babel/plugin-transform-arrow-functions': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-block-scoping': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-classes': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-destructuring': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-for-of': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-parameters': 7.16.3_@babel+core@7.16.12 + '@babel/plugin-transform-shorthand-properties': 7.16.0_@babel+core@7.16.12 + '@babel/plugin-transform-spread': 7.16.0_@babel+core@7.16.12 + '@babel/preset-env': 7.16.4_@babel+core@7.16.12 + '@babel/preset-react': 7.16.0_@babel+core@7.16.12 + '@babel/preset-typescript': 7.16.0_@babel+core@7.16.12 + '@babel/register': 7.16.0_@babel+core@7.16.12 '@storybook/node-logger': 6.4.14 '@storybook/semver': 7.3.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/pretty-hrtime': 1.0.1 babel-loader: 8.2.3_2ca4133eaad1ede48c0159d2a9c3555f babel-plugin-macros: 3.1.0 @@ -6373,7 +6527,7 @@ packages: interpret: 2.2.0 json5: 2.2.0 lazy-universal-dotenv: 3.0.1 - picomatch: 2.3.1 + picomatch: 2.3.0 pkg-dir: 5.0.0 pretty-hrtime: 1.0.3 react: 18.0.0-rc.0 @@ -6428,7 +6582,7 @@ packages: '@storybook/node-logger': 6.4.14 '@storybook/semver': 7.3.2 '@storybook/store': 6.4.14_757a802188413a36d4f24237d13b8e90 - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/node-fetch': 2.5.12 '@types/pretty-hrtime': 1.0.1 '@types/webpack': 4.41.32 @@ -6444,10 +6598,10 @@ packages: express: 4.17.2 file-system-cache: 1.0.5 fs-extra: 9.1.0 - globby: 11.1.0 + globby: 11.0.4 ip: 1.1.5 lodash: 4.17.21 - node-fetch: 2.6.7 + node-fetch: 2.6.6 pretty-hrtime: 1.0.3 prompts: 2.4.2 react: 18.0.0-rc.0 @@ -6461,12 +6615,11 @@ packages: util-deprecate: 1.0.2 watchpack: 2.3.1 webpack: 4.46.0 - ws: 8.4.2 + ws: 8.4.0 transitivePeerDependencies: - '@types/react' - acorn - bufferutil - - encoding - eslint - supports-color - utf-8-validate @@ -6504,7 +6657,7 @@ packages: '@storybook/node-logger': 6.4.14 '@storybook/semver': 7.3.2 '@storybook/store': 6.4.14_757a802188413a36d4f24237d13b8e90 - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/node-fetch': 2.5.12 '@types/pretty-hrtime': 1.0.1 '@types/webpack': 4.41.32 @@ -6520,10 +6673,10 @@ packages: express: 4.17.2 file-system-cache: 1.0.5 fs-extra: 9.1.0 - globby: 11.1.0 + globby: 11.0.4 ip: 1.1.5 lodash: 4.17.21 - node-fetch: 2.6.7 + node-fetch: 2.6.6 pretty-hrtime: 1.0.3 prompts: 2.4.2 react: 18.0.0-rc.0 @@ -6537,12 +6690,11 @@ packages: util-deprecate: 1.0.2 watchpack: 2.3.1 webpack: 4.46.0 - ws: 8.4.2 + ws: 8.4.0 transitivePeerDependencies: - '@types/react' - acorn - bufferutil - - encoding - eslint - supports-color - utf-8-validate @@ -6578,7 +6730,7 @@ packages: '@storybook/node-logger': 6.4.14 '@storybook/semver': 7.3.2 '@storybook/store': 6.4.14_757a802188413a36d4f24237d13b8e90 - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/node-fetch': 2.5.12 '@types/pretty-hrtime': 1.0.1 '@types/webpack': 4.41.32 @@ -6594,10 +6746,10 @@ packages: express: 4.17.2 file-system-cache: 1.0.5 fs-extra: 9.1.0 - globby: 11.1.0 + globby: 11.0.4 ip: 1.1.5 lodash: 4.17.21 - node-fetch: 2.6.7 + node-fetch: 2.6.6 pretty-hrtime: 1.0.3 prompts: 2.4.2 react: 18.0.0-rc.0 @@ -6611,12 +6763,11 @@ packages: util-deprecate: 1.0.2 watchpack: 2.3.1 webpack: 4.46.0 - ws: 8.4.2 + ws: 8.4.0 transitivePeerDependencies: - '@types/react' - acorn - bufferutil - - encoding - eslint - supports-color - utf-8-validate @@ -6650,7 +6801,6 @@ packages: - '@types/react' - acorn - bufferutil - - encoding - eslint - supports-color - utf-8-validate @@ -6685,7 +6835,6 @@ packages: - '@types/react' - acorn - bufferutil - - encoding - eslint - supports-color - utf-8-validate @@ -6720,7 +6869,6 @@ packages: - '@types/react' - acorn - bufferutil - - encoding - eslint - supports-color - utf-8-validate @@ -6735,8 +6883,8 @@ packages: '@babel/core': 7.16.12 '@babel/generator': 7.16.8 '@babel/parser': 7.16.12 - '@babel/plugin-transform-react-jsx': 7.16.7_@babel+core@7.16.12 - '@babel/preset-env': 7.16.11_@babel+core@7.16.12 + '@babel/plugin-transform-react-jsx': 7.16.0_@babel+core@7.16.12 + '@babel/preset-env': 7.16.4_@babel+core@7.16.12 '@babel/traverse': 7.16.10 '@babel/types': 7.16.8 '@mdx-js/mdx': 1.6.22 @@ -6770,15 +6918,15 @@ packages: optional: true dependencies: '@babel/core': 7.16.12 - '@babel/plugin-transform-template-literals': 7.16.7_@babel+core@7.16.12 - '@babel/preset-react': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-transform-template-literals': 7.16.0_@babel+core@7.16.12 + '@babel/preset-react': 7.16.0_@babel+core@7.16.12 '@storybook/addons': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/core-client': 6.4.14_17851d71d1f251dcbff27ebb6f3ec2df '@storybook/core-common': 6.4.14_c4177559f6413a84d8022a867d5dce45 '@storybook/node-logger': 6.4.14 '@storybook/theming': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/ui': 6.4.14_2f50eb45a1501445764b3dbbd8573d7c - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/webpack': 4.41.32 babel-loader: 8.2.3_2ca4133eaad1ede48c0159d2a9c3555f case-sensitive-paths-webpack-plugin: 2.4.0 @@ -6791,7 +6939,7 @@ packages: find-up: 5.0.0 fs-extra: 9.1.0 html-webpack-plugin: 4.5.2_webpack@4.46.0 - node-fetch: 2.6.7 + node-fetch: 2.6.6 pnp-webpack-plugin: 1.6.4_typescript@4.6.0-dev.20211202 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 @@ -6811,7 +6959,6 @@ packages: transitivePeerDependencies: - '@types/react' - acorn - - encoding - eslint - supports-color - vue-template-compiler @@ -6830,15 +6977,15 @@ packages: optional: true dependencies: '@babel/core': 7.16.12 - '@babel/plugin-transform-template-literals': 7.16.7_@babel+core@7.16.12 - '@babel/preset-react': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-transform-template-literals': 7.16.0_@babel+core@7.16.12 + '@babel/preset-react': 7.16.0_@babel+core@7.16.12 '@storybook/addons': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/core-client': 6.4.14_17851d71d1f251dcbff27ebb6f3ec2df '@storybook/core-common': 6.4.14_c4177559f6413a84d8022a867d5dce45 '@storybook/node-logger': 6.4.14 '@storybook/theming': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/ui': 6.4.14_2f50eb45a1501445764b3dbbd8573d7c - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/webpack': 4.41.32 babel-loader: 8.2.3_2ca4133eaad1ede48c0159d2a9c3555f case-sensitive-paths-webpack-plugin: 2.4.0 @@ -6851,7 +6998,7 @@ packages: find-up: 5.0.0 fs-extra: 9.1.0 html-webpack-plugin: 4.5.2_webpack@4.46.0 - node-fetch: 2.6.7 + node-fetch: 2.6.6 pnp-webpack-plugin: 1.6.4_typescript@4.6.0-dev.20211202 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 @@ -6871,7 +7018,6 @@ packages: transitivePeerDependencies: - '@types/react' - acorn - - encoding - eslint - supports-color - vue-template-compiler @@ -6890,15 +7036,15 @@ packages: optional: true dependencies: '@babel/core': 7.16.12 - '@babel/plugin-transform-template-literals': 7.16.7_@babel+core@7.16.12 - '@babel/preset-react': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-transform-template-literals': 7.16.0_@babel+core@7.16.12 + '@babel/preset-react': 7.16.0_@babel+core@7.16.12 '@storybook/addons': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/core-client': 6.4.14_c9c1482dfad043e1bffbe44bab8a0d76 '@storybook/core-common': 6.4.14_c4177559f6413a84d8022a867d5dce45 '@storybook/node-logger': 6.4.14 '@storybook/theming': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/ui': 6.4.14_2f50eb45a1501445764b3dbbd8573d7c - '@types/node': 16.11.21 + '@types/node': 16.11.17 babel-loader: 8.2.3_e748cba1f5e972defd8ae51292b4033f case-sensitive-paths-webpack-plugin: 2.4.0 chalk: 4.1.2 @@ -6909,7 +7055,7 @@ packages: find-up: 5.0.0 fs-extra: 9.1.0 html-webpack-plugin: 5.5.0_webpack@5.67.0 - node-fetch: 2.6.7 + node-fetch: 2.6.6 process: 0.11.10 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 @@ -6918,7 +7064,7 @@ packages: resolve-from: 5.0.0 style-loader: 2.0.0_webpack@5.67.0 telejson: 5.3.3 - terser-webpack-plugin: 5.3.0_webpack@5.67.0 + terser-webpack-plugin: 5.2.5_webpack@5.67.0 ts-dedent: 2.2.0 typescript: 4.6.0-dev.20211202 util-deprecate: 1.0.2 @@ -6929,7 +7075,6 @@ packages: - '@swc/core' - '@types/react' - acorn - - encoding - esbuild - eslint - supports-color @@ -6942,7 +7087,7 @@ packages: /@storybook/node-logger/6.4.14: resolution: {integrity: sha512-mowC0adx4hLtCqGMQKRfNmiRYAL2PYdk3ojc91qzIKNrjSYnE4U8d9qlw5WLx1PKEnZVji3+QiYfNHpA/8PoKw==} dependencies: - '@types/npmlog': 4.1.4 + '@types/npmlog': 4.1.3 chalk: 4.1.2 core-js: 3.20.3 npmlog: 5.0.1 @@ -6971,7 +7116,7 @@ packages: core-js: 3.20.3 global: 4.4.0 lodash: 4.17.21 - qs: 6.10.3 + qs: 6.10.2 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 regenerator-runtime: 0.13.9 @@ -7016,8 +7161,8 @@ packages: optional: true dependencies: '@babel/core': 7.16.12 - '@babel/preset-flow': 7.16.7_@babel+core@7.16.12 - '@babel/preset-react': 7.16.7_@babel+core@7.16.12 + '@babel/preset-flow': 7.16.0_@babel+core@7.16.12 + '@babel/preset-react': 7.16.0_@babel+core@7.16.12 '@pmmmwh/react-refresh-webpack-plugin': 0.5.4_06cd85ae30adde416cafc06517ba554d '@storybook/addons': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/core': 6.4.14_ad84e7bc2f1cd698bd14fe3b093cd366 @@ -7029,12 +7174,12 @@ packages: '@storybook/store': 6.4.14_757a802188413a36d4f24237d13b8e90 '@types/webpack-env': 1.16.3 babel-plugin-add-react-displayname: 0.0.5 - babel-plugin-named-asset-import: 0.3.8_@babel+core@7.16.12 + babel-plugin-named-asset-import: 0.3.7_@babel+core@7.16.12 babel-plugin-react-docgen: 4.2.1 core-js: 3.20.3 global: 4.4.0 lodash: 4.17.21 - prop-types: 15.8.1 + prop-types: 15.8.0 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 react-refresh: 0.11.0 @@ -7050,7 +7195,6 @@ packages: - '@types/webpack' - acorn - bufferutil - - encoding - eslint - sockjs-client - supports-color @@ -7079,8 +7223,8 @@ packages: typescript: optional: true dependencies: - '@babel/preset-flow': 7.16.7 - '@babel/preset-react': 7.16.7 + '@babel/preset-flow': 7.16.0 + '@babel/preset-react': 7.16.0 '@pmmmwh/react-refresh-webpack-plugin': 0.5.4_06cd85ae30adde416cafc06517ba554d '@storybook/addons': 6.4.14_757a802188413a36d4f24237d13b8e90 '@storybook/core': 6.4.14_20682c4eb0db26cc77101378579cfe3c @@ -7092,12 +7236,12 @@ packages: '@storybook/store': 6.4.14_757a802188413a36d4f24237d13b8e90 '@types/webpack-env': 1.16.3 babel-plugin-add-react-displayname: 0.0.5 - babel-plugin-named-asset-import: 0.3.8 + babel-plugin-named-asset-import: 0.3.7 babel-plugin-react-docgen: 4.2.1 core-js: 3.20.3 global: 4.4.0 lodash: 4.17.21 - prop-types: 15.8.1 + prop-types: 15.8.0 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 react-refresh: 0.11.0 @@ -7113,7 +7257,6 @@ packages: - '@types/webpack' - acorn - bufferutil - - encoding - eslint - sockjs-client - supports-color @@ -7140,11 +7283,11 @@ packages: history: 5.0.0 lodash: 4.17.21 memoizerific: 1.11.3 - qs: 6.10.3 + qs: 6.10.2 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 - react-router: 6.2.1_react@18.0.0-rc.0 - react-router-dom: 6.2.1_757a802188413a36d4f24237d13b8e90 + react-router: 6.1.1_react@18.0.0-rc.0 + react-router-dom: 6.1.1_757a802188413a36d4f24237d13b8e90 ts-dedent: 2.2.0 dev: true @@ -7213,11 +7356,11 @@ packages: '@emotion/styled': 10.3.0_e02dd3725849cbb6b1072425c9ec0b91 '@storybook/client-logger': 6.4.14 core-js: 3.20.3 - deep-object-diff: 1.1.7 + deep-object-diff: 1.1.0 emotion-theming: 10.3.0_e02dd3725849cbb6b1072425c9ec0b91 global: 4.4.0 memoizerific: 1.11.3 - polished: 4.1.4 + polished: 4.1.3 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 resolve-from: 5.0.0 @@ -7242,16 +7385,16 @@ packages: '@storybook/theming': 6.4.14_757a802188413a36d4f24237d13b8e90 copy-to-clipboard: 3.3.1 core-js: 3.20.3 - core-js-pure: 3.20.3 + core-js-pure: 3.20.1 downshift: 6.1.7_react@18.0.0-rc.0 emotion-theming: 10.3.0_e02dd3725849cbb6b1072425c9ec0b91 fuse.js: 3.6.1 global: 4.4.0 lodash: 4.17.21 - markdown-to-jsx: 7.1.6_react@18.0.0-rc.0 + markdown-to-jsx: 7.1.5_react@18.0.0-rc.0 memoizerific: 1.11.3 - polished: 4.1.4 - qs: 6.10.3 + polished: 4.1.3 + qs: 6.10.2 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 react-draggable: 4.4.4_757a802188413a36d4f24237d13b8e90 @@ -7259,7 +7402,7 @@ packages: react-sizeme: 3.0.2 regenerator-runtime: 0.13.9 resolve-from: 5.0.0 - store2: 2.13.1 + store2: 2.12.0 transitivePeerDependencies: - '@types/react' dev: true @@ -7446,8 +7589,8 @@ packages: resolution: {integrity: sha512-t4YHCgtD+ERvH0FyxvNlYwJ2ezhqw7t+Ygh4urQ7dJER8i185JPv6oIM3ey5YQmGN6Zp9EMbpohkjZi9t3UxwA==} dev: false - /@types/babel__core/7.1.18: - resolution: {integrity: sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==} + /@types/babel__core/7.1.17: + resolution: {integrity: sha512-6zzkezS9QEIL8yCBvXWxPTJPNuMeECJVxSOhxNY/jfq9LxOTHivaYTqr37n9LknWWRTIkzqH2UilS5QFvfa90A==} dependencies: '@babel/parser': 7.16.12 '@babel/types': 7.16.8 @@ -7478,24 +7621,24 @@ packages: /@types/bn.js/4.11.6: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 /@types/bn.js/5.1.0: resolution: {integrity: sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 /@types/body-parser/1.19.2: resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} dependencies: '@types/connect': 3.4.35 - '@types/node': 16.11.21 + '@types/node': 16.11.17 dev: true /@types/bonjour/3.5.10: resolution: {integrity: sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 dev: true /@types/bs58/4.0.1: @@ -7528,8 +7671,8 @@ packages: /@types/connect-history-api-fallback/1.3.5: resolution: {integrity: sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==} dependencies: - '@types/express-serve-static-core': 4.17.28 - '@types/node': 16.11.21 + '@types/express-serve-static-core': 4.17.25 + '@types/node': 16.11.17 dev: true /@types/connect/3.4.35: @@ -7740,12 +7883,12 @@ packages: /@types/eslint-scope/3.7.1: resolution: {integrity: sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==} dependencies: - '@types/eslint': 7.28.2 + '@types/eslint': 8.2.0 '@types/estree': 0.0.50 dev: true - /@types/eslint/7.28.2: - resolution: {integrity: sha512-KubbADPkfoU75KgKeKLsFHXnU4ipH7wYg0TRT33NK3N3yiu7jlFAAoygIWBV+KbuHx/G+AvuGX6DllnK35gfJA==} + /@types/eslint/8.2.0: + resolution: {integrity: sha512-74hbvsnc+7TEDa1z5YLSe4/q8hGYB3USNvCuzHUJrjPV6hXaq8IXcngCrHkuvFt0+8rFz7xYXrHgNayIX0UZvQ==} dependencies: '@types/estree': 0.0.50 '@types/json-schema': 7.0.9 @@ -7773,21 +7916,12 @@ packages: '@types/node': 16.11.17 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 - dev: false - - /@types/express-serve-static-core/4.17.28: - resolution: {integrity: sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==} - dependencies: - '@types/node': 16.11.21 - '@types/qs': 6.9.7 - '@types/range-parser': 1.2.4 - dev: true /@types/express/4.17.13: resolution: {integrity: sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==} dependencies: '@types/body-parser': 1.19.2 - '@types/express-serve-static-core': 4.17.28 + '@types/express-serve-static-core': 4.17.25 '@types/qs': 6.9.7 '@types/serve-static': 1.13.10 dev: true @@ -7823,13 +7957,13 @@ packages: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: '@types/minimatch': 3.0.5 - '@types/node': 16.11.21 + '@types/node': 16.11.17 dev: true /@types/graceful-fs/4.1.5: resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 dev: true /@types/gulp/4.0.9: @@ -7866,10 +8000,10 @@ packages: resolution: {integrity: sha512-NZwaaynfs1oIoLAV1vg18e7QMVDvw+6SQrdJc8w3BwUaoroVSf6EBj/Sk4PBWGxsq0dzhA2drbsuMC1/6C6KgQ==} dev: true - /@types/http-proxy/1.17.8: - resolution: {integrity: sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==} + /@types/http-proxy/1.17.7: + resolution: {integrity: sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 dev: true /@types/is-function/1.0.1: @@ -7907,7 +8041,7 @@ packages: /@types/json2csv/5.0.3: resolution: {integrity: sha512-ZJEv6SzhPhgpBpxZU4n/TZekbZqI4EcyXXRwms1lAITG2kIAtj85PfNYafUOY1zy8bWs5ujaub0GU4copaA0sw==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 dev: false /@types/json5/0.0.29: @@ -7922,6 +8056,7 @@ packages: /@types/lodash/4.14.177: resolution: {integrity: sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==} + dev: true /@types/lodash/4.14.178: resolution: {integrity: sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==} @@ -7949,28 +8084,29 @@ packages: /@types/node-fetch/2.5.12: resolution: {integrity: sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 form-data: 3.0.1 dev: true + /@types/node/16.11.10: + resolution: {integrity: sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==} + dev: false + + /@types/node/16.11.12: + resolution: {integrity: sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==} + dev: true + /@types/node/16.11.17: resolution: {integrity: sha512-C1vTZME8cFo8uxY2ui41xcynEotVkczIVI5AjLmy5pkpBv/FtG+jhtOlfcPysI8VRVwoOMv6NJm44LGnoMSWkw==} - /@types/node/16.11.21: - resolution: {integrity: sha512-Pf8M1XD9i1ksZEcCP8vuSNwooJ/bZapNmIzpmsMaL+jMI+8mEYU3PKvs+xDNuQcJWF/x24WzY4qxLtB0zNow9A==} - /@types/node/16.11.6: resolution: {integrity: sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==} - /@types/node/16.11.7: - resolution: {integrity: sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==} - dev: false - /@types/normalize-package-data/2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} - /@types/npmlog/4.1.4: - resolution: {integrity: sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==} + /@types/npmlog/4.1.3: + resolution: {integrity: sha512-1TcL7YDYCtnHmLhTWbum+IIwLlvpaHoEKS2KNIngEwLzwgDeHaebaEHHbQp8IqzNQ9IYiboLKUjAf7MZqG63+w==} dev: true /@types/overlayscrollbars/1.12.1: @@ -7987,14 +8123,14 @@ packages: /@types/pbkdf2/3.1.0: resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 /@types/prettier/2.3.2: resolution: {integrity: sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==} dev: false - /@types/prettier/2.4.3: - resolution: {integrity: sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w==} + /@types/prettier/2.4.2: + resolution: {integrity: sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA==} dev: true /@types/pretty-hrtime/1.0.1: @@ -8055,11 +8191,11 @@ packages: dependencies: '@types/history': 4.7.11 '@types/react': 17.0.38 - '@types/react-router': 5.1.18 + '@types/react-router': 5.1.17 dev: false - /@types/react-router/5.1.18: - resolution: {integrity: sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==} + /@types/react-router/5.1.17: + resolution: {integrity: sha512-RNSXOyb3VyRs/EOGmjBhhGKTbnN6fHWvy5FNLzWfOWOGjgVUKqJZXfpKzLmgoU8h6Hj8mpALj/mbXQASOb92wQ==} dependencies: '@types/history': 4.7.11 '@types/react': 17.0.38 @@ -8122,7 +8258,7 @@ packages: /@types/resolve/1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 dev: true /@types/retry/0.12.1: @@ -8142,7 +8278,7 @@ packages: /@types/secp256k1/4.0.3: resolution: {integrity: sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 /@types/serve-index/1.9.1: resolution: {integrity: sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==} @@ -8154,7 +8290,7 @@ packages: resolution: {integrity: sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==} dependencies: '@types/mime': 1.3.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 dev: true /@types/socket.io-client/1.4.36: @@ -8164,7 +8300,7 @@ packages: /@types/sockjs/0.3.33: resolution: {integrity: sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 dev: true /@types/source-list-map/0.1.2: @@ -8241,7 +8377,6 @@ packages: dependencies: webpack-dev-server: 4.7.3_webpack-cli@4.9.2+webpack@5.67.0 transitivePeerDependencies: - - '@types/express' - bufferutil - debug - supports-color @@ -8257,7 +8392,7 @@ packages: /@types/webpack-sources/3.2.0: resolution: {integrity: sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/source-list-map': 0.1.2 source-map: 0.7.3 dev: true @@ -8265,7 +8400,7 @@ packages: /@types/webpack/4.41.32: resolution: {integrity: sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 '@types/tapable': 1.0.8 '@types/uglify-js': 3.13.1 '@types/webpack-sources': 3.2.0 @@ -8276,13 +8411,13 @@ packages: /@types/ws/7.4.7: resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} dependencies: - '@types/node': 16.11.7 + '@types/node': 16.11.17 dev: false /@types/ws/8.2.2: resolution: {integrity: sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 dev: true /@types/yargs-parser/20.2.1: @@ -8405,7 +8540,7 @@ packages: '@typescript-eslint/types': 5.10.1 '@typescript-eslint/visitor-keys': 5.10.1 debug: 4.3.3 - globby: 11.1.0 + globby: 11.0.4 is-glob: 4.0.3 semver: 7.3.5 tsutils: 3.21.0_typescript@4.6.0-dev.20211202 @@ -9016,7 +9151,7 @@ packages: array-includes: 3.1.4 array.prototype.flat: 1.2.5 array.prototype.flatmap: 1.2.5 - es5-shim: 4.6.4 + es5-shim: 4.6.2 es6-shim: 0.35.6 function.prototype.name: 1.1.5 globalthis: 1.0.2 @@ -9055,12 +9190,12 @@ packages: dependencies: ajv: 6.12.6 - /ajv-keywords/5.1.0_ajv@8.9.0: + /ajv-keywords/5.1.0_ajv@8.8.2: resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} peerDependencies: ajv: ^8.8.2 dependencies: - ajv: 8.9.0 + ajv: 8.8.2 fast-deep-equal: 3.1.3 dev: true @@ -9072,6 +9207,15 @@ packages: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + /ajv/8.8.2: + resolution: {integrity: sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + /ajv/8.9.0: resolution: {integrity: sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==} dependencies: @@ -9137,7 +9281,6 @@ packages: /ansi-regex/3.0.0: resolution: {integrity: sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=} engines: {node: '>=4'} - dev: false /ansi-regex/5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -9443,8 +9586,8 @@ packages: minimalistic-assert: 1.0.1 safer-buffer: 2.1.2 - /asn1/0.2.4: - resolution: {integrity: sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==} + /asn1/0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} dependencies: safer-buffer: 2.1.2 dev: false @@ -9562,7 +9705,7 @@ packages: hasBin: true dependencies: browserslist: 4.19.1 - caniuse-lite: 1.0.30001302 + caniuse-lite: 1.0.30001292 normalize-range: 0.1.2 num2fraction: 1.2.2 picocolors: 0.2.1 @@ -9778,7 +9921,7 @@ packages: '@babel/core': 7.16.12 '@jest/transform': 27.4.6 '@jest/types': 27.4.2 - '@types/babel__core': 7.1.18 + '@types/babel__core': 7.1.17 babel-plugin-istanbul: 6.1.1 babel-preset-jest: 27.4.0_@babel+core@7.16.12 chalk: 4.1.2 @@ -9875,7 +10018,7 @@ packages: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} dependencies: - '@babel/helper-plugin-utils': 7.16.7 + '@babel/helper-plugin-utils': 7.16.5 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 5.1.0 @@ -9890,7 +10033,7 @@ packages: dependencies: '@babel/template': 7.16.7 '@babel/types': 7.16.8 - '@types/babel__core': 7.1.18 + '@types/babel__core': 7.1.17 '@types/babel__traverse': 7.14.2 dev: true @@ -9905,19 +10048,19 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 cosmiconfig: 7.0.1 - resolve: 1.22.0 + resolve: 1.20.0 dev: true - /babel-plugin-named-asset-import/0.3.8: - resolution: {integrity: sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==} + /babel-plugin-named-asset-import/0.3.7: + resolution: {integrity: sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw==} peerDependencies: '@babel/core': ^7.1.0 dev: true - /babel-plugin-named-asset-import/0.3.8_@babel+core@7.16.12: - resolution: {integrity: sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==} + /babel-plugin-named-asset-import/0.3.7_@babel+core@7.16.12: + resolution: {integrity: sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw==} peerDependencies: '@babel/core': ^7.1.0 dependencies: @@ -9929,7 +10072,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.16.8 + '@babel/compat-data': 7.16.0 '@babel/core': 7.16.12 '@babel/helper-define-polyfill-provider': 0.2.4_@babel+core@7.16.12 semver: 6.3.0 @@ -9937,14 +10080,14 @@ packages: - supports-color dev: false - /babel-plugin-polyfill-corejs2/0.3.1_@babel+core@7.16.12: - resolution: {integrity: sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==} + /babel-plugin-polyfill-corejs2/0.3.0_@babel+core@7.16.12: + resolution: {integrity: sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.16.8 + '@babel/compat-data': 7.16.4 '@babel/core': 7.16.12 - '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.16.12 + '@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.12 semver: 6.3.0 transitivePeerDependencies: - supports-color @@ -9968,19 +10111,19 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-define-polyfill-provider': 0.2.4_@babel+core@7.16.12 - core-js-compat: 3.20.1 + '@babel/helper-define-polyfill-provider': 0.2.3_@babel+core@7.16.12 + core-js-compat: 3.17.3 transitivePeerDependencies: - supports-color dev: false - /babel-plugin-polyfill-corejs3/0.5.1_@babel+core@7.16.12: - resolution: {integrity: sha512-TihqEe4sQcb/QcPJvxe94/9RZuLQuF1+To4WqQcRvc+3J3gLCPIPgDKzGLG6zmQLfH3nn25heRuDNkS2KR4I8A==} + /babel-plugin-polyfill-corejs3/0.4.0_@babel+core@7.16.12: + resolution: {integrity: sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.16.12 + '@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.12 core-js-compat: 3.20.3 transitivePeerDependencies: - supports-color @@ -9997,13 +10140,13 @@ packages: - supports-color dev: false - /babel-plugin-polyfill-regenerator/0.3.1_@babel+core@7.16.12: - resolution: {integrity: sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==} + /babel-plugin-polyfill-regenerator/0.3.0_@babel+core@7.16.12: + resolution: {integrity: sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.16.12 - '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.16.12 + '@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.12 transitivePeerDependencies: - supports-color dev: true @@ -10492,7 +10635,7 @@ packages: /bip39/3.0.4: resolution: {integrity: sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 create-hash: 1.2.0 pbkdf2: 3.1.2 randombytes: 2.1.0 @@ -10600,7 +10743,7 @@ packages: engines: {node: '>=10'} dependencies: ansi-align: 3.0.1 - camelcase: 6.3.0 + camelcase: 6.2.1 chalk: 4.1.2 cli-boxes: 2.2.1 string-width: 4.2.3 @@ -10699,8 +10842,20 @@ packages: resolution: {integrity: sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==} hasBin: true dependencies: - caniuse-lite: 1.0.30001302 - electron-to-chromium: 1.4.53 + caniuse-lite: 1.0.30001292 + electron-to-chromium: 1.4.28 + dev: false + + /browserslist/4.18.1: + resolution: {integrity: sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001286 + electron-to-chromium: 1.4.16 + escalade: 3.1.1 + node-releases: 2.0.1 + picocolors: 1.0.0 dev: false /browserslist/4.19.1: @@ -10713,6 +10868,7 @@ packages: escalade: 3.1.1 node-releases: 2.0.1 picocolors: 1.0.0 + dev: true /bs-logger/0.2.6: resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} @@ -10803,15 +10959,6 @@ packages: dependencies: node-gyp-build: 4.3.0 - /bufferutil/4.0.6: - resolution: {integrity: sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==} - engines: {node: '>=6.14.2'} - requiresBuild: true - dependencies: - node-gyp-build: 4.3.0 - dev: false - optional: true - /builtin-modules/1.1.1: resolution: {integrity: sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=} engines: {node: '>=0.10.0'} @@ -10840,8 +10987,8 @@ packages: engines: {node: '>= 0.8'} dev: true - /c8/7.11.0: - resolution: {integrity: sha512-XqPyj1uvlHMr+Y1IeRndC2X5P7iJzJlEJwBpCdBbq2JocXOgJfr+JVfJkyNMGROke5LfKrhSFXGFXnwnRJAUJw==} + /c8/7.10.0: + resolution: {integrity: sha512-OAwfC5+emvA6R7pkYFVBTOtI5ruf9DahffGmIqUc9l6wEh0h7iAFP6dt/V9Ioqlr2zW5avX9U9/w1I4alTRHkA==} engines: {node: '>=10.12.0'} hasBin: true dependencies: @@ -10854,7 +11001,7 @@ packages: istanbul-reports: 3.1.3 rimraf: 3.0.2 test-exclude: 6.0.0 - v8-to-istanbul: 8.1.1 + v8-to-istanbul: 8.1.0 yargs: 16.2.0 yargs-parser: 20.2.9 dev: true @@ -10961,7 +11108,7 @@ packages: engines: {node: '>=8'} dependencies: camelcase: 5.3.1 - map-obj: 4.3.0 + map-obj: 4.2.1 quick-lru: 4.0.1 /camelcase/1.2.1: @@ -10982,17 +11129,18 @@ packages: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} - /camelcase/6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + /camelcase/6.2.1: + resolution: {integrity: sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==} engines: {node: '>=10'} dev: true + /caniuse-lite/1.0.30001286: + resolution: {integrity: sha512-zaEMRH6xg8ESMi2eQ3R4eZ5qw/hJiVsO/HlLwniIwErij0JDr9P+8V4dtx1l+kLq6j3yy8l8W4fst1lBnat5wQ==} + dev: false + /caniuse-lite/1.0.30001292: resolution: {integrity: sha512-jnT4Tq0Q4ma+6nncYQVe7d73kmDmE9C3OGTx3MvW7lBM/eY1S1DZTMBON7dqV481RhNiS5OxD7k9JQvmDOTirw==} - /caniuse-lite/1.0.30001302: - resolution: {integrity: sha512-YYTMO+tfwvgUN+1ZnRViE53Ma1S/oETg+J2lISsqi/ZTNThj3ZYBOKP2rHwJc37oCsPqAzJ3w2puZHn0xlLPPw==} - /capture-exit/2.0.0: resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==} engines: {node: 6.* || 8.* || >= 10.*} @@ -11109,21 +11257,6 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.2 - dev: true - - /chokidar/3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.2 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.2 /chownr/1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} @@ -11258,7 +11391,7 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: slice-ansi: 5.0.0 - string-width: 5.1.0 + string-width: 5.0.1 dev: true /clipboard-polyfill/3.0.3: @@ -11612,8 +11745,8 @@ packages: q: 1.5.1 dev: true - /conventional-commits-parser/3.2.4: - resolution: {integrity: sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==} + /conventional-commits-parser/3.2.3: + resolution: {integrity: sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw==} engines: {node: '>=10'} hasBin: true dependencies: @@ -11676,9 +11809,9 @@ packages: peerDependencies: webpack: ^5.1.0 dependencies: - fast-glob: 3.2.11 + fast-glob: 3.2.7 glob-parent: 6.0.2 - globby: 12.2.0 + globby: 12.0.2 normalize-path: 3.0.0 schema-utils: 4.0.0 serialize-javascript: 6.0.0 @@ -11698,10 +11831,10 @@ packages: - webpack-command dev: true - /core-js-compat/3.20.1: - resolution: {integrity: sha512-AVhKZNpqMV3Jz8hU0YEXXE06qoxtQGsAqU0u1neUngz5IusDJRX/ZJ6t3i7mS7QxNyEONbCo14GprkBrxPlTZA==} + /core-js-compat/3.17.3: + resolution: {integrity: sha512-+in61CKYs4hQERiADCJsdgewpdl/X0GhEX77pjKgbeibXviIt2oxEjTc8O2fqHX8mDdBrDvX8MYD/RYsBv4OiA==} dependencies: - browserslist: 4.19.1 + browserslist: 4.18.1 semver: 7.0.0 dev: false @@ -11717,11 +11850,6 @@ packages: requiresBuild: true dev: true - /core-js-pure/3.20.3: - resolution: {integrity: sha512-Q2H6tQ5MtPtcC7f3HxJ48i4Q7T9ybPKgvWyuH7JXIoNa2pm0KuBnycsET/qw1SLLZYfbsbrZQNMeIOClb+6WIA==} - requiresBuild: true - dev: true - /core-js/1.2.7: resolution: {integrity: sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=} deprecated: core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js. @@ -11752,16 +11880,16 @@ packages: vary: 1.1.2 dev: false - /cosmiconfig-typescript-loader/1.0.4_typescript@4.5.5: - resolution: {integrity: sha512-ulv2dvwurP/MZAIthXm69bO7EzzIUThZ6RJ1qXhdlXM6to3F+IKBL/17EnhYSG52A5N1KcAUu66vSG/3/77KrA==} + /cosmiconfig-typescript-loader/1.0.2_typescript@4.5.4: + resolution: {integrity: sha512-27ZehvijYqAKVzta5xtZBS3PAliC8CmnWkGXN0vgxAZz7yqxpMjf3aG7flxF5rEiu8FAD7nZZXtOI+xUGn+bVg==} engines: {node: '>=12', npm: '>=6'} peerDependencies: '@types/node': '*' typescript: '>=3' dependencies: cosmiconfig: 7.0.1 - ts-node: 10.4.0_typescript@4.5.5 - typescript: 4.5.5 + ts-node: 10.4.0_typescript@4.5.4 + typescript: 4.5.4 transitivePeerDependencies: - '@swc/core' - '@swc/wasm' @@ -12066,16 +12194,6 @@ packages: nth-check: 2.0.1 dev: true - /css-select/4.2.1: - resolution: {integrity: sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==} - dependencies: - boolbase: 1.0.0 - css-what: 5.1.0 - domhandler: 4.3.0 - domutils: 2.8.0 - nth-check: 2.0.1 - dev: true - /css-tree/1.1.3: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} engines: {node: '>=8.0.0'} @@ -12488,13 +12606,13 @@ packages: is-regex: 1.1.4 object-is: 1.1.5 object-keys: 1.1.1 - regexp.prototype.flags: 1.4.1 + regexp.prototype.flags: 1.3.1 /deep-is/0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - /deep-object-diff/1.1.7: - resolution: {integrity: sha512-QkgBca0mL08P6HiOjoqvmm6xOAl2W6CT2+34Ljhg0OeFan8cwlcdq8jrLKsBBuUFAZLsN5b6y491KdKEoSo9lg==} + /deep-object-diff/1.1.0: + resolution: {integrity: sha512-b+QLs5vHgS+IoSNcUE4n9HP2NwcHj7aqnJWsjPtuG75Rh5TOaGt0OjAYInh77d5T16V5cRDC+Pw/6ZZZiETBGw==} dev: true /deepmerge/4.2.2: @@ -12568,7 +12686,7 @@ packages: resolution: {integrity: sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==} engines: {node: '>=10'} dependencies: - globby: 11.1.0 + globby: 11.0.4 graceful-fs: 4.2.9 is-glob: 4.0.3 is-path-cwd: 2.2.0 @@ -12831,7 +12949,7 @@ packages: peerDependencies: react: '>=16.12.0' dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 compute-scroll-into-view: 1.0.17 prop-types: 15.8.1 react: 18.0.0-rc.0 @@ -12865,10 +12983,6 @@ packages: object.defaults: 1.1.0 dev: true - /eastasianwidth/0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - /ecc-jsbn/0.1.2: resolution: {integrity: sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=} dependencies: @@ -12894,15 +13008,15 @@ packages: resolution: {integrity: sha512-Hj+GY0mf2NNBcgg0v6DsV0/EYI5xDLUICZ5BSLVC+8uFEzoWpWw2VR6e3eWKgGjL2YEybUdg89UXDEHaBmi03Q==} dev: false + /electron-to-chromium/1.4.16: + resolution: {integrity: sha512-BQb7FgYwnu6haWLU63/CdVW+9xhmHls3RCQUFiV4lvw3wimEHTVcUk2hkuZo76QhR8nnDdfZE7evJIZqijwPdA==} + dev: false + /electron-to-chromium/1.4.28: resolution: {integrity: sha512-Gzbf0wUtKfyPaqf0Plz+Ctinf9eQIzxEqBHwSvbGfeOm9GMNdLxyu1dNiCUfM+x6r4BE0xUJNh3Nmg9gfAtTmg==} - /electron-to-chromium/1.4.53: - resolution: {integrity: sha512-rFveSKQczlcav+H3zkKqykU6ANseFwXwkl855jOIap5/0gnEcuIhv2ecz6aoTrXavF6I/CEBeRnBnkB51k06ew==} - dev: false - - /element-resize-detector/1.2.4: - resolution: {integrity: sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==} + /element-resize-detector/1.2.3: + resolution: {integrity: sha512-+dhNzUgLpq9ol5tyhoG7YLoXL3ssjfFW+0gpszXPwRU6NjGr1fVHMEAF8fVzIiRJq57Nre0RFeIjJwI8Nh2NmQ==} dependencies: batch-processor: 1.0.0 dev: true @@ -12963,7 +13077,7 @@ packages: '@emotion/core': ^10.0.27 react: '>=16.3.0' dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 '@emotion/core': 10.3.1_react@18.0.0-rc.0 '@emotion/weak-memoize': 0.2.5 hoist-non-react-statics: 3.3.2 @@ -13157,8 +13271,8 @@ packages: es6-symbol: 3.1.3 next-tick: 1.0.0 - /es5-shim/4.6.4: - resolution: {integrity: sha512-Z0f7OUYZ8JfqT12d3Tgh2ErxIH5Shaz97GE8qyDG9quxb2Hmh2vvFHlOFjx6lzyD0CRgvJfnNYcisjdbRp7MPw==} + /es5-shim/4.6.2: + resolution: {integrity: sha512-n0XTVMGps+Deyr38jtqKPR5F5hb9owYeRQcKJW39eFvzUk/u/9Ww315werRzbiNMnHCUw/YHDPBphTlEnzdi+A==} engines: {node: '>=0.4.0'} dev: true @@ -13284,7 +13398,7 @@ packages: resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==} dependencies: debug: 3.2.7 - resolve: 1.22.0 + resolve: 1.20.0 dev: true /eslint-module-utils/2.7.2: @@ -13309,11 +13423,11 @@ packages: eslint-import-resolver-node: 0.3.6 eslint-module-utils: 2.7.2 has: 1.0.3 - is-core-module: 2.8.1 + is-core-module: 2.8.0 is-glob: 4.0.3 minimatch: 3.0.4 object.values: 1.1.5 - resolve: 1.22.0 + resolve: 1.20.0 tsconfig-paths: 3.12.0 dev: true @@ -13372,7 +13486,7 @@ packages: peerDependencies: eslint: '>=7.32.0' dependencies: - '@babel/helper-validator-identifier': 7.16.7 + '@babel/helper-validator-identifier': 7.15.7 ci-info: 3.3.0 clean-regexp: 1.0.0 eslint: 8.7.0 @@ -13537,7 +13651,7 @@ packages: dependencies: '@babel/traverse': 7.16.10 '@babel/types': 7.16.8 - c8: 7.11.0 + c8: 7.10.0 transitivePeerDependencies: - supports-color dev: true @@ -13618,7 +13732,7 @@ packages: /eth-rpc-errors/4.0.3: resolution: {integrity: sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg==} dependencies: - fast-safe-stringify: 2.1.1 + fast-safe-stringify: 2.0.8 dev: false /eth-sig-util/1.4.2: @@ -13779,6 +13893,7 @@ packages: ethereum-cryptography: 0.1.3 ethjs-util: 0.1.6 rlp: 2.2.7 + dev: false /ethereumjs-util/7.1.3: resolution: {integrity: sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw==} @@ -13789,7 +13904,6 @@ packages: create-hash: 1.2.0 ethereum-cryptography: 0.1.3 rlp: 2.2.7 - dev: false /ethereumjs-vm/2.6.0: resolution: {integrity: sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==} @@ -13929,6 +14043,7 @@ packages: dependencies: is-hex-prefixed: 1.0.0 strip-hex-prefix: 1.0.0 + dev: false /event-emitter/0.3.5: resolution: {integrity: sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=} @@ -14214,9 +14329,9 @@ packages: micromatch: 3.1.10 dev: true - /fast-glob/3.2.11: - resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} - engines: {node: '>=8.6.0'} + /fast-glob/3.2.7: + resolution: {integrity: sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==} + engines: {node: '>=8'} dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 @@ -14239,8 +14354,8 @@ packages: /fast-levenshtein/2.0.6: resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} - /fast-safe-stringify/2.1.1: - resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + /fast-safe-stringify/2.0.8: + resolution: {integrity: sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==} dev: false /fast-shallow-equal/1.0.0: @@ -14580,13 +14695,13 @@ packages: '@babel/code-frame': 7.16.7 '@types/json-schema': 7.0.9 chalk: 4.1.2 - chokidar: 3.5.3 + chokidar: 3.5.2 cosmiconfig: 6.0.0 deepmerge: 4.2.2 eslint: 8.7.0 fs-extra: 9.1.0 glob: 7.2.0 - memfs: 3.4.1 + memfs: 3.4.0 minimatch: 3.0.4 schema-utils: 2.7.0 semver: 7.3.5 @@ -14612,13 +14727,13 @@ packages: '@babel/code-frame': 7.16.7 '@types/json-schema': 7.0.9 chalk: 4.1.2 - chokidar: 3.5.3 + chokidar: 3.5.2 cosmiconfig: 6.0.0 deepmerge: 4.2.2 eslint: 8.7.0 fs-extra: 9.1.0 glob: 7.2.0 - memfs: 3.4.1 + memfs: 3.4.0 minimatch: 3.0.4 schema-utils: 2.7.0 semver: 7.3.5 @@ -14744,7 +14859,7 @@ packages: resolution: {integrity: sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=} engines: {node: '>= 0.10'} dependencies: - graceful-fs: 4.2.9 + graceful-fs: 4.2.8 through2: 2.0.5 dev: true @@ -14812,8 +14927,8 @@ packages: engines: {node: '>=10'} dev: false - /gauge/3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + /gauge/3.0.1: + resolution: {integrity: sha512-6STz6KdQgxO4S/ko+AbjlFGGdGcknluoqU+79GOFCDqqyYj5OanQf9AjxwN0jCidtT+ziPMmPSt9E4hfQ0CwIQ==} engines: {node: '>=10'} dependencies: aproba: 2.0.0 @@ -14822,8 +14937,8 @@ packages: has-unicode: 2.0.1 object-assign: 4.1.1 signal-exit: 3.0.6 - string-width: 4.2.3 - strip-ansi: 6.0.1 + string-width: 2.1.1 + strip-ansi: 4.0.0 wide-align: 1.1.5 dev: true @@ -14901,8 +15016,8 @@ packages: assert-plus: 1.0.0 dev: false - /git-raw-commits/2.0.11: - resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==} + /git-raw-commits/2.0.10: + resolution: {integrity: sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==} engines: {node: '>=10'} hasBin: true dependencies: @@ -15071,25 +15186,25 @@ packages: define-properties: 1.1.3 dev: true - /globby/11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + /globby/11.0.4: + resolution: {integrity: sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==} engines: {node: '>=10'} dependencies: array-union: 2.1.0 dir-glob: 3.0.1 - fast-glob: 3.2.11 + fast-glob: 3.2.7 ignore: 5.2.0 merge2: 1.4.1 slash: 3.0.0 dev: true - /globby/12.2.0: - resolution: {integrity: sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==} + /globby/12.0.2: + resolution: {integrity: sha512-lAsmb/5Lww4r7MM9nCCliDZVIKbZTavrsunAsHLr9oHthrZP1qi7/gAnHOsUs9bLvEt2vKVJhHmxuL7QbDuPdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: array-union: 3.0.1 dir-glob: 3.0.1 - fast-glob: 3.2.11 + fast-glob: 3.2.7 ignore: 5.2.0 merge2: 1.4.1 slash: 4.0.0 @@ -15239,15 +15354,14 @@ packages: glogg: 1.0.2 dev: true - /gun/0.2020.1234: - resolution: {integrity: sha512-RqlGDDze1U7gdRZCHx8VMBi0dzyJL4C6jQHwOuFjH9aldGcCQPN0HyVaKVn6jNHgS1AAbTBod4KCfMRXda+eZg==} + /gun/0.2020.1235: + resolution: {integrity: sha512-aba6s0X/MCCOByt0T3VrMzMMUEblfN2aLV2bAmIQWjkB7SKnm07zAZWigljwI69Rb5sOw7C1G116UyvCM2p9kA==} engines: {node: '>=0.8.4'} dependencies: - ws: 7.5.5 + ws: 7.5.6 optionalDependencies: '@peculiar/webcrypto': 1.2.3 emailjs: 2.2.0 - text-encoding: 0.7.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -15267,7 +15381,7 @@ packages: source-map: 0.6.1 wordwrap: 1.0.0 optionalDependencies: - uglify-js: 3.15.0 + uglify-js: 3.14.5 /har-schema/2.0.0: resolution: {integrity: sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=} @@ -15320,11 +15434,6 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - /has-flag/5.0.1: - resolution: {integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==} - engines: {node: '>=12'} - dev: true - /has-glob/1.0.0: resolution: {integrity: sha1-mqqe7b/7G6OZCnsAEPtnjuAIEgc=} engines: {node: '>=0.10.0'} @@ -15503,7 +15612,7 @@ packages: /history/5.0.0: resolution: {integrity: sha512-3NyRMKIiFSJmIPdq7FxkNMJkQ7ZEtVblOQ38VtKaA0zZMW1Eo6Q6W8oDKEflr1kNNTItSnk4JMCO1deeSgbLLg==} dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 dev: true /history/5.2.0: @@ -15541,8 +15650,8 @@ packages: /hosted-git-info/2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - /hosted-git-info/4.1.0: - resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + /hosted-git-info/4.0.2: + resolution: {integrity: sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==} engines: {node: '>=10'} dependencies: lru-cache: 6.0.0 @@ -15603,9 +15712,7 @@ packages: he: 1.2.0 param-case: 3.0.4 relateurl: 0.2.7 - terser: 5.10.0 - transitivePeerDependencies: - - acorn + terser: 5.9.0 dev: true /html-parse-stringify/3.0.1: @@ -15668,8 +15775,6 @@ packages: pretty-error: 4.0.0 tapable: 2.2.1 webpack: 5.67.0 - transitivePeerDependencies: - - acorn dev: true /htmlparser2/6.1.0: @@ -15761,13 +15866,11 @@ packages: - supports-color dev: false - /http-proxy-middleware/2.0.2: - resolution: {integrity: sha512-XtmDN5w+vdFTBZaYhdJAbMqn0DP/EhkUaAeo963mojwpKMMbw6nivtFKw07D7DDOH745L5k0VL0P8KRYNEVF/g==} + /http-proxy-middleware/2.0.1: + resolution: {integrity: sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg==} engines: {node: '>=12.0.0'} - peerDependencies: - '@types/express': ^4.17.13 dependencies: - '@types/http-proxy': 1.17.8 + '@types/http-proxy': 1.17.7 http-proxy: 1.18.1 is-glob: 4.0.3 is-plain-obj: 3.0.0 @@ -15826,7 +15929,7 @@ packages: /i18next-browser-languagedetector/6.1.3: resolution: {integrity: sha512-T+oGXHXtrur14CGnZZ7qQ07X38XJQEI00b/4ILrtO6xPbwTlQ1wtMZC2H+tBULixHuVUXv8LKbxfjyITJkezUg==} dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 dev: false /i18next-translation-parser/1.0.1: @@ -15838,7 +15941,7 @@ packages: /i18next/21.6.9: resolution: {integrity: sha512-oS82WMEwBFLGzq18RGwm7XRkRUMngXr92LqOjC1Z1txfueotPBPcN2bU2GWC3010fgjdhsQMFqrEqEf8a+R/oQ==} dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 dev: false /iconv-lite/0.4.24: @@ -15931,6 +16034,10 @@ packages: resolution: {integrity: sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==} dev: false + /immer/9.0.7: + resolution: {integrity: sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA==} + dev: false + /immutable/3.8.1: resolution: {integrity: sha1-IAgH8Rqw9ycQ6khVQt4IgHX2jNI=} engines: {node: '>=0.10.0'} @@ -15943,8 +16050,8 @@ packages: parent-module: 1.0.1 resolve-from: 4.0.0 - /import-local/3.1.0: - resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + /import-local/3.0.3: + resolution: {integrity: sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==} engines: {node: '>=8'} hasBin: true dependencies: @@ -15992,8 +16099,8 @@ packages: resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} dev: true - /inline-style-prefixer/6.0.1: - resolution: {integrity: sha512-AsqazZ8KcRzJ9YPN1wMH2aNM7lkWQ8tSPrW5uDk1ziYwiAPWSZnUsC7lfZq+BDqLqz0B4Pho5wscWcJzVvRzDQ==} + /inline-style-prefixer/6.0.0: + resolution: {integrity: sha512-XTHvRUS4ZJNzC1GixJRmOlWSS45fSt+DJoyQC9ytj0WxQfcgofQtDtyKKYxHUqEsWCs+LIWftPF1ie7+i012Fg==} dependencies: css-in-js-utils: 2.0.1 dev: false @@ -16142,11 +16249,6 @@ packages: dependencies: has: 1.0.3 - /is-core-module/2.8.1: - resolution: {integrity: sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==} - dependencies: - has: 1.0.3 - /is-data-descriptor/0.1.4: resolution: {integrity: sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=} engines: {node: '>=0.10.0'} @@ -16231,7 +16333,6 @@ packages: /is-fullwidth-code-point/2.0.0: resolution: {integrity: sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=} engines: {node: '>=4'} - dev: false /is-fullwidth-code-point/3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} @@ -16548,12 +16649,12 @@ packages: unfetch: 3.1.2 dev: false - /isomorphic-ws/4.0.1_ws@7.5.5: + /isomorphic-ws/4.0.1_ws@7.5.6: resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} peerDependencies: ws: '*' dependencies: - ws: 7.5.5 + ws: 7.5.6 dev: false /isstream/0.1.2: @@ -16625,26 +16726,26 @@ packages: iterate-iterator: 1.0.2 dev: true - /jayson/3.6.5: - resolution: {integrity: sha512-wmOjX+eQcnCDyPF4KORomaIj9wj3h0B5VEbeD0+2VHfTfErB+h1zpR7oBkgCZp36AFjp3+a4CLz6U72BYpFHAw==} + /jayson/3.6.6: + resolution: {integrity: sha512-f71uvrAWTtrwoww6MKcl9phQTC+56AopLyEenWvKVAIMz+q0oVGj6tenLZ7Z6UiPBkJtKLj4kt0tACllFQruGQ==} engines: {node: '>=8'} hasBin: true dependencies: '@types/connect': 3.4.35 '@types/express-serve-static-core': 4.17.25 - '@types/lodash': 4.14.177 - '@types/node': 16.11.7 + '@types/lodash': 4.14.178 + '@types/node': 16.11.17 '@types/ws': 7.4.7 commander: 2.20.3 delay: 5.0.0 es6-promisify: 5.0.0 eyes: 0.1.8 - isomorphic-ws: 4.0.1_ws@7.5.5 + isomorphic-ws: 4.0.1_ws@7.5.6 json-stringify-safe: 5.0.1 JSONStream: 1.3.5 lodash: 4.17.21 - uuid: 3.4.0 - ws: 7.5.5 + uuid: 8.3.2 + ws: 7.5.6 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -16666,7 +16767,7 @@ packages: '@jest/environment': 27.4.6 '@jest/test-result': 27.4.6 '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -16702,7 +16803,7 @@ packages: chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.9 - import-local: 3.1.0 + import-local: 3.0.3 jest-config: 27.4.7_ts-node@10.4.0 jest-util: 27.4.2 jest-validate: 27.4.6 @@ -16755,6 +16856,16 @@ packages: - utf-8-validate dev: true + /jest-diff/27.4.2: + resolution: {integrity: sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 27.4.0 + jest-get-type: 27.4.0 + pretty-format: 27.4.2 + dev: true + /jest-diff/27.4.6: resolution: {integrity: sha512-zjaB0sh0Lb13VyPsd92V7HkqF6yKRH9vm33rwBt7rPYrpQvS1nCvlIy2pICbKta+ZjWngYLNn4cCK4nyZkjS/w==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -16790,7 +16901,7 @@ packages: '@jest/environment': 27.4.6 '@jest/fake-timers': 27.4.6 '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 jest-mock: 27.4.6 jest-util: 27.4.2 jsdom: 16.7.0 @@ -16808,7 +16919,7 @@ packages: '@jest/environment': 27.4.6 '@jest/fake-timers': 27.4.6 '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 jest-mock: 27.4.6 jest-util: 27.4.2 dev: true @@ -16824,7 +16935,7 @@ packages: dependencies: '@jest/types': 26.6.2 '@types/graceful-fs': 4.1.5 - '@types/node': 16.11.21 + '@types/node': 16.11.17 anymatch: 3.1.2 fb-watchman: 2.0.1 graceful-fs: 4.2.9 @@ -16845,7 +16956,7 @@ packages: dependencies: '@jest/types': 27.4.2 '@types/graceful-fs': 4.1.5 - '@types/node': 16.11.21 + '@types/node': 16.11.17 anymatch: 3.1.2 fb-watchman: 2.0.1 graceful-fs: 4.2.9 @@ -16867,7 +16978,7 @@ packages: '@jest/source-map': 27.4.0 '@jest/test-result': 27.4.6 '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 chalk: 4.1.2 co: 4.6.0 expect: 27.4.6 @@ -16922,7 +17033,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 dev: true /jest-pnp-resolver/1.2.2_jest-resolve@27.4.6: @@ -16969,7 +17080,7 @@ packages: jest-pnp-resolver: 1.2.2_jest-resolve@27.4.6 jest-util: 27.4.2 jest-validate: 27.4.6 - resolve: 1.22.0 + resolve: 1.20.0 resolve.exports: 1.1.0 slash: 3.0.0 dev: true @@ -16983,7 +17094,7 @@ packages: '@jest/test-result': 27.4.6 '@jest/transform': 27.4.6 '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 chalk: 4.1.2 emittery: 0.8.1 exit: 0.1.2 @@ -17041,7 +17152,7 @@ packages: resolution: {integrity: sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==} engines: {node: '>= 10.14.2'} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 graceful-fs: 4.2.9 dev: true @@ -17049,7 +17160,7 @@ packages: resolution: {integrity: sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 graceful-fs: 4.2.9 dev: true @@ -17059,13 +17170,13 @@ packages: dependencies: '@babel/core': 7.16.12 '@babel/generator': 7.16.8 - '@babel/plugin-syntax-typescript': 7.16.7_@babel+core@7.16.12 + '@babel/plugin-syntax-typescript': 7.16.5_@babel+core@7.16.12 '@babel/traverse': 7.16.10 '@babel/types': 7.16.8 '@jest/transform': 27.4.6 '@jest/types': 27.4.2 '@types/babel__traverse': 7.14.2 - '@types/prettier': 2.4.3 + '@types/prettier': 2.4.2 babel-preset-current-node-syntax: 1.0.1_@babel+core@7.16.12 chalk: 4.1.2 expect: 27.4.6 @@ -17088,7 +17199,7 @@ packages: engines: {node: '>= 10.14.2'} dependencies: '@jest/types': 26.6.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 chalk: 4.1.2 graceful-fs: 4.2.9 is-ci: 2.0.0 @@ -17100,11 +17211,11 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 chalk: 4.1.2 ci-info: 3.3.0 graceful-fs: 4.2.9 - picomatch: 2.3.1 + picomatch: 2.3.0 dev: true /jest-validate/27.4.6: @@ -17112,7 +17223,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.4.2 - camelcase: 6.3.0 + camelcase: 6.2.1 chalk: 4.1.2 jest-get-type: 27.4.0 leven: 3.1.0 @@ -17125,7 +17236,7 @@ packages: dependencies: '@jest/test-result': 27.4.6 '@jest/types': 27.4.2 - '@types/node': 16.11.21 + '@types/node': 16.11.17 ansi-escapes: 4.3.2 chalk: 4.1.2 jest-util: 27.4.2 @@ -17135,7 +17246,7 @@ packages: /jest-websocket-mock/2.3.0: resolution: {integrity: sha512-kXhRRApRdT4hLG/4rhsfcR0Ke0OzqIsDj0P5t0dl5aiAftShSgoRqp/0pyjS5bh+b9GrIzmfkrV2cn9LxxvSvA==} dependencies: - jest-diff: 27.4.6 + jest-diff: 27.4.2 mock-socket: 9.1.2 dev: true @@ -17143,7 +17254,7 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 16.11.17 + '@types/node': 16.11.12 merge-stream: 2.0.0 supports-color: 7.2.0 dev: true @@ -17161,7 +17272,7 @@ packages: resolution: {integrity: sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 16.11.21 + '@types/node': 16.11.17 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -17177,7 +17288,7 @@ packages: optional: true dependencies: '@jest/core': 27.4.7_ts-node@10.4.0 - import-local: 3.1.0 + import-local: 3.0.3 jest-cli: 27.4.7_ts-node@10.4.0 transitivePeerDependencies: - bufferutil @@ -17576,7 +17687,7 @@ packages: /klaw-sync/6.0.0: resolution: {integrity: sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==} dependencies: - graceful-fs: 4.2.9 + graceful-fs: 4.2.8 dev: true /klaw/1.3.1: @@ -17611,7 +17722,7 @@ packages: resolution: {integrity: sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ==} engines: {node: '>=6.0.0', npm: '>=6.0.0', yarn: '>=1.0.0'} dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 app-root-dir: 1.0.2 core-js: 3.20.3 dotenv: 8.6.0 @@ -17805,15 +17916,6 @@ packages: json5: 2.2.0 dev: true - /loader-utils/2.0.1: - resolution: {integrity: sha512-g4miPa9uUrZz4iElkaVJgDFwKJGh8aQGM7pUL4ejXl6cu7kSb30seQOVGNMP6sW8j7DW77X68hJZ+GM7UGhXeQ==} - engines: {node: '>=8.9.0'} - dependencies: - big.js: 5.2.2 - emojis-list: 3.0.0 - json5: 2.2.0 - dev: true - /loader-utils/2.0.2: resolution: {integrity: sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==} engines: {node: '>=8.9.0'} @@ -18033,8 +18135,8 @@ packages: resolution: {integrity: sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=} engines: {node: '>=0.10.0'} - /map-obj/4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + /map-obj/4.2.1: + resolution: {integrity: sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==} engines: {node: '>=8'} /map-or-similar/1.5.0: @@ -18051,8 +18153,8 @@ packages: resolution: {integrity: sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==} dev: true - /markdown-to-jsx/7.1.6_react@18.0.0-rc.0: - resolution: {integrity: sha512-1wrIGZYwIG2gR3yfRmbr4FlQmhaAKoKTpRo4wur4fp9p0njU1Hi7vR8fj0AUKKIcPduiJmPprzmCB5B/GvlC7g==} + /markdown-to-jsx/7.1.5_react@18.0.0-rc.0: + resolution: {integrity: sha512-YQEMMMCX3PYOWtUAQu8Fmz5/sH09s17eyQnDubwaAo8sWmnRTT1og96EFv1vL59l4nWfmtF3L91pqkuheVqRlA==} engines: {node: '>= 10'} peerDependencies: react: '>= 0.14.0' @@ -18144,8 +18246,8 @@ packages: safe-buffer: 5.1.2 dev: false - /memfs/3.4.1: - resolution: {integrity: sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==} + /memfs/3.4.0: + resolution: {integrity: sha512-o/RfP0J1d03YwsAxyHxAYs2kyJp55AFkMazlFAZFR2I2IXkxiUTXRabJ6RmNNCQ83LAD2jy52Khj0m3OffpNdA==} engines: {node: '>= 4.0.0'} dependencies: fs-monkey: 1.0.3 @@ -18578,8 +18680,8 @@ packages: resolution: {integrity: sha1-ulSMh578+5DaHE2eCX20pGySVe8=} dev: false - /nano-css/5.3.4_757a802188413a36d4f24237d13b8e90: - resolution: {integrity: sha512-wfcviJB6NOxDIDfr7RFn/GlaN7I/Bhe4d39ZRCJ3xvZX60LVe2qZ+rDqM49nm4YT81gAjzS+ZklhKP/Gnfnubg==} + /nano-css/5.3.1_757a802188413a36d4f24237d13b8e90: + resolution: {integrity: sha512-ENPIyNzANQRyYVvb62ajDd7PAyIgS2LIUnT9ewih4yrXSZX4hKoUwssy8WjUH++kEOA5wUTMgNnV7ko5n34kUA==} peerDependencies: react: '*' react-dom: '*' @@ -18587,10 +18689,10 @@ packages: css-tree: 1.1.3 csstype: 3.0.10 fastest-stable-stringify: 2.0.2 - inline-style-prefixer: 6.0.1 + inline-style-prefixer: 6.0.0 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 - rtl-css-js: 1.15.0 + rtl-css-js: 1.14.2 sourcemap-codec: 1.4.8 stacktrace-js: 2.0.2 stylis: 4.0.13 @@ -18600,8 +18702,8 @@ packages: resolution: {integrity: sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=} dev: false - /nanoid/3.2.0: - resolution: {integrity: sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==} + /nanoid/3.1.30: + resolution: {integrity: sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true dev: true @@ -18686,19 +18788,6 @@ packages: engines: {node: 4.x || >=6.0.0} dependencies: whatwg-url: 5.0.0 - dev: false - - /node-fetch/2.6.7: - resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: true /node-forge/1.2.1: resolution: {integrity: sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==} @@ -18760,8 +18849,8 @@ packages: resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} engines: {node: '>=10'} dependencies: - hosted-git-info: 4.1.0 - is-core-module: 2.8.1 + hosted-git-info: 4.0.2 + is-core-module: 2.8.0 semver: 7.3.5 validate-npm-package-license: 3.0.4 dev: true @@ -18834,7 +18923,7 @@ packages: dependencies: are-we-there-yet: 2.0.0 console-control-strings: 1.1.0 - gauge: 3.0.2 + gauge: 3.0.1 set-blocking: 2.0.0 dev: true @@ -19490,11 +19579,6 @@ packages: resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==} engines: {node: '>=8.6'} - /picomatch/2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - /pify/2.3.0: resolution: {integrity: sha1-7RQaasBDqEnqWISY59yosVMw6Qw=} engines: {node: '>=0.10.0'} @@ -19519,8 +19603,8 @@ packages: resolution: {integrity: sha1-clVrgM+g1IqXToDnckjoDtT3+HA=} engines: {node: '>=0.10.0'} - /pirates/4.0.5: - resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==} + /pirates/4.0.4: + resolution: {integrity: sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==} engines: {node: '>= 6'} dev: true @@ -19574,11 +19658,11 @@ packages: - typescript dev: true - /polished/4.1.4: - resolution: {integrity: sha512-Nq5Mbza+Auo7N3sQb1QMFaQiDO+4UexWuSGR7Cjb4Sw11SZIJcrrFtiZ+L0jT9MBsUsxDboHVASbCLbE1rnECg==} + /polished/4.1.3: + resolution: {integrity: sha512-ocPAcVBUOryJEKe0z2KLd1l9EBa1r5mSwlKpExmrLzsnIzJo4axsoU9O2BjOTkDGDT4mZ0WFE5XKTlR3nLnZOA==} engines: {node: '>=10'} dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 dev: true /portfinder/1.0.28: @@ -19638,7 +19722,7 @@ packages: dependencies: icss-utils: 4.1.1 postcss: 7.0.39 - postcss-selector-parser: 6.0.9 + postcss-selector-parser: 6.0.7 postcss-value-parser: 4.2.0 dev: true @@ -19650,7 +19734,7 @@ packages: dependencies: icss-utils: 5.1.0_postcss@8.4.5 postcss: 8.4.5 - postcss-selector-parser: 6.0.9 + postcss-selector-parser: 6.0.7 postcss-value-parser: 4.2.0 dev: true @@ -19659,7 +19743,7 @@ packages: engines: {node: '>= 6'} dependencies: postcss: 7.0.39 - postcss-selector-parser: 6.0.9 + postcss-selector-parser: 6.0.7 dev: true /postcss-modules-scope/3.0.0_postcss@8.4.5: @@ -19669,7 +19753,7 @@ packages: postcss: ^8.1.0 dependencies: postcss: 8.4.5 - postcss-selector-parser: 6.0.9 + postcss-selector-parser: 6.0.7 dev: true /postcss-modules-values/3.0.0: @@ -19689,8 +19773,8 @@ packages: postcss: 8.4.5 dev: true - /postcss-selector-parser/6.0.9: - resolution: {integrity: sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==} + /postcss-selector-parser/6.0.7: + resolution: {integrity: sha512-U+b/Deoi4I/UmE6KOVPpnhS7I7AYdKbhGcat+qTQ27gycvaACvNEw11ba6RrkwVmDVRW7sigWgLj4/KbbJjeDA==} engines: {node: '>=4'} dependencies: cssesc: 3.0.0 @@ -19713,9 +19797,9 @@ packages: resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==} engines: {node: ^10 || ^12 || >=14} dependencies: - nanoid: 3.2.0 + nanoid: 3.1.30 picocolors: 1.0.0 - source-map-js: 1.0.2 + source-map-js: 1.0.1 dev: true /prelude-ls/1.1.2: @@ -19776,6 +19860,16 @@ packages: renderkid: 3.0.0 dev: true + /pretty-format/27.4.2: + resolution: {integrity: sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@jest/types': 27.4.2 + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + dev: true + /pretty-format/27.4.6: resolution: {integrity: sha512-NblstegA1y/RJW2VyML+3LlpFjzx62cUrtBIKIWDXEDkjNeleA7Od7nrzcs/VLQvAeV4CgSYhrN39DRN88Qi/g==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -19799,11 +19893,6 @@ packages: resolution: {integrity: sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==} dev: true - /prismjs/1.26.0: - resolution: {integrity: sha512-HUoH9C5Z3jKkl3UunCyiD5jwk0+Hz0fIgQ2nbwU2Oo/ceuTAQAg+pPVnfdt2TJWRVLcxKh9iuoYDUSc8clb5UQ==} - engines: {node: '>=6'} - dev: true - /private/0.1.8: resolution: {integrity: sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==} engines: {node: '>= 0.6'} @@ -19917,7 +20006,7 @@ packages: '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 '@types/long': 4.0.1 - '@types/node': 16.11.21 + '@types/node': 16.11.17 long: 4.0.0 dev: false @@ -20015,8 +20104,8 @@ packages: yargs: 15.4.1 dev: false - /qs/6.10.3: - resolution: {integrity: sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==} + /qs/6.10.2: + resolution: {integrity: sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw==} engines: {node: '>=0.6'} dependencies: side-channel: 1.0.4 @@ -20143,8 +20232,8 @@ packages: react-dom: '>=0.14.0' dependencies: '@babel/plugin-transform-runtime': 7.15.0_@babel+core@7.16.12 - '@babel/runtime': 7.16.5 - prop-types: 15.8.0 + '@babel/runtime': 7.16.3 + prop-types: 15.7.2 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 transitivePeerDependencies: @@ -20187,7 +20276,7 @@ packages: dependencies: '@babel/core': 7.16.12 '@babel/generator': 7.16.8 - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 ast-types: 0.14.2 commander: 2.20.3 doctrine: 3.0.0 @@ -20253,7 +20342,7 @@ packages: react: ^16.6.0 || ^17.0.0 react-dom: ^16.6.0 || ^17.0.0 dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 invariant: 2.2.4 prop-types: 15.8.1 react: 18.0.0-rc.0 @@ -20295,7 +20384,7 @@ packages: react-native: optional: true dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 html-escaper: 2.0.2 html-parse-stringify: 3.0.1 i18next: 21.6.9 @@ -20308,7 +20397,7 @@ packages: peerDependencies: react: ^16.8.4 || ^17.0.0 dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 is-dom: 1.1.0 prop-types: 15.8.1 react: 18.0.0-rc.0 @@ -20326,20 +20415,20 @@ packages: react: ^16.6.0 || ^17.0.0 react-dom: ^16.6.0 || ^17.0.0 dependencies: - '@babel/runtime': 7.16.7 - '@popperjs/core': 2.11.2 + '@babel/runtime': 7.16.5 + '@popperjs/core': 2.11.0 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 - react-popper: 2.2.5_1294749af9bd9192dc615c20cf5f75e1 + react-popper: 2.2.5_667a73996e94b90f095c6ade8b3de17d dev: true - /react-popper/2.2.5_1294749af9bd9192dc615c20cf5f75e1: + /react-popper/2.2.5_667a73996e94b90f095c6ade8b3de17d: resolution: {integrity: sha512-kxGkS80eQGtLl18+uig1UIf9MKixFSyPxglsgLBxlYnyDf65BiY9B3nZSc6C9XUNDgStROB0fMQlTEz1KxGddw==} peerDependencies: '@popperjs/core': ^2.0.0 react: ^16.8.0 || ^17 dependencies: - '@popperjs/core': 2.11.2 + '@popperjs/core': 2.11.0 react: 18.0.0-rc.0 react-fast-compare: 3.2.0 warning: 4.0.3 @@ -20391,8 +20480,8 @@ packages: react-router: 6.0.0-beta.0_history@5.2.0+react@18.0.0-rc.0 dev: false - /react-router-dom/6.2.1_757a802188413a36d4f24237d13b8e90: - resolution: {integrity: sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==} + /react-router-dom/6.1.1_757a802188413a36d4f24237d13b8e90: + resolution: {integrity: sha512-O3UH89DI4o+swd2q6lF4dSmpuNCxwkUXcj0zAFcVc1H+YoPE6T7uwoFMX0ws1pUvCY8lYDucFpOqCCdal6VFzg==} peerDependencies: react: '>=16.8' react-dom: '>=16.8' @@ -20400,7 +20489,7 @@ packages: history: 5.2.0 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 - react-router: 6.2.1_react@18.0.0-rc.0 + react-router: 6.1.1_react@18.0.0-rc.0 dev: true /react-router/5.2.1_react@18.0.0-rc.0: @@ -20432,8 +20521,8 @@ packages: react: 18.0.0-rc.0 dev: false - /react-router/6.2.1_react@18.0.0-rc.0: - resolution: {integrity: sha512-2fG0udBtxou9lXtK97eJeET2ki5//UWfQSl1rlJ7quwe6jrktK9FCCc8dQb5QY6jAv3jua8bBQRhhDOM/kVRsg==} + /react-router/6.1.1_react@18.0.0-rc.0: + resolution: {integrity: sha512-55o96RiDZmC0uD17DPqVmzzfdNd2Dc+EjkYvMAmHl43du/GItaTdFr5WwjTryNWPXZ+OOVQxQhwAX25UwxpHtw==} peerDependencies: react: '>=16.8' dependencies: @@ -20444,7 +20533,7 @@ packages: /react-sizeme/3.0.2: resolution: {integrity: sha512-xOIAOqqSSmKlKFJLO3inBQBdymzDuXx4iuwkNcJmC96jeiOg5ojByvL+g3MW9LPEsojLbC6pf68zOfobK8IPlw==} dependencies: - element-resize-detector: 1.2.4 + element-resize-detector: 1.2.3 invariant: 2.2.4 shallowequal: 1.1.0 throttle-debounce: 3.0.1 @@ -20455,10 +20544,10 @@ packages: peerDependencies: react: '>= 0.14.0' dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 highlight.js: 10.7.3 lowlight: 1.20.0 - prismjs: 1.26.0 + prismjs: 1.25.0 react: 18.0.0-rc.0 refractor: 3.5.0 dev: true @@ -20469,9 +20558,9 @@ packages: peerDependencies: react: ^16.8.0 || ^17.0.0 dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 react: 18.0.0-rc.0 - use-composed-ref: 1.2.1_react@18.0.0-rc.0 + use-composed-ref: 1.1.0_react@18.0.0-rc.0 use-latest: 1.2.0_2fa291bfae6e56080648438396754a97 transitivePeerDependencies: - '@types/react' @@ -20524,12 +20613,12 @@ packages: fast-deep-equal: 3.1.3 fast-shallow-equal: 1.0.0 js-cookie: 2.2.1 - nano-css: 5.3.4_757a802188413a36d4f24237d13b8e90 + nano-css: 5.3.1_757a802188413a36d4f24237d13b8e90 react: 18.0.0-rc.0 react-dom: 18.0.0-rc.0_react@18.0.0-rc.0 react-universal-interface: 0.6.2_react@18.0.0-rc.0+tslib@2.3.1 resize-observer-polyfill: 1.5.1 - screenfull: 5.2.0 + screenfull: 5.1.0 set-harmonic-interval: 1.0.1 throttle-debounce: 3.0.1 ts-easing: 0.2.0 @@ -20670,7 +20759,7 @@ packages: resolution: {integrity: sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==} engines: {node: '>= 0.10'} dependencies: - resolve: 1.22.0 + resolve: 1.20.0 dev: true /reconnecting-websocket/4.4.0: @@ -20726,7 +20815,7 @@ packages: /regenerator-transform/0.14.5: resolution: {integrity: sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==} dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 dev: true /regex-not/1.0.2: @@ -20747,14 +20836,6 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.1.3 - dev: true - - /regexp.prototype.flags/1.4.1: - resolution: {integrity: sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.3 /regexpp/3.2.0: resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} @@ -20904,7 +20985,7 @@ packages: /renderkid/2.0.7: resolution: {integrity: sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==} dependencies: - css-select: 4.2.1 + css-select: 4.1.3 dom-converter: 0.2.0 htmlparser2: 6.1.0 lodash: 4.17.21 @@ -21061,14 +21142,6 @@ packages: is-core-module: 2.8.0 path-parse: 1.0.7 - /resolve/1.22.0: - resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} - hasBin: true - dependencies: - is-core-module: 2.8.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - /resolve/2.0.0-next.3: resolution: {integrity: sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q==} dependencies: @@ -21182,13 +21255,11 @@ packages: peerDependencies: rollup: ^2.0.0 dependencies: - '@babel/code-frame': 7.16.0 + '@babel/code-frame': 7.15.8 jest-worker: 26.6.2 rollup: 2.66.1 serialize-javascript: 4.0.0 - terser: 5.10.0 - transitivePeerDependencies: - - acorn + terser: 5.8.0 dev: true /rollup/2.66.1: @@ -21206,10 +21277,10 @@ packages: circular-json: 0.5.9 eventemitter3: 4.0.7 uuid: 8.3.2 - ws: 7.5.5_bffff4271b89d628e8333ead80d3d8e8 + ws: 7.5.6_72ef9f06cb99540da679cbf1bf7a3256 optionalDependencies: - bufferutil: 4.0.6 - utf-8-validate: 5.0.8 + bufferutil: 4.0.3 + utf-8-validate: 5.0.5 dev: false /rss3-next/0.6.17_typescript@4.6.0-dev.20211202: @@ -21236,10 +21307,10 @@ packages: engines: {node: 6.* || >= 7.*} dev: true - /rtl-css-js/1.15.0: - resolution: {integrity: sha512-99Cu4wNNIhrI10xxUaABHsdDqzalrSRTie4GeCmbGVuehm4oj+fIy8fTzB+16pmKe8Bv9rl+hxIBez6KxExTew==} + /rtl-css-js/1.14.2: + resolution: {integrity: sha512-t6Wc/wpqm8s3kuXAV6tL/T7VS6n0XszzX58CgCsLj3O2xi9ITSLfzYhtl+GKyxCi/3QEqVctOJQwCiDzb2vteQ==} dependencies: - '@babel/runtime': 7.16.7 + '@babel/runtime': 7.16.5 dev: false /run-parallel/1.2.0: @@ -21378,13 +21449,13 @@ packages: engines: {node: '>= 12.13.0'} dependencies: '@types/json-schema': 7.0.9 - ajv: 8.9.0 + ajv: 8.8.2 ajv-formats: 2.1.1 - ajv-keywords: 5.1.0_ajv@8.9.0 + ajv-keywords: 5.1.0_ajv@8.8.2 dev: true - /screenfull/5.2.0: - resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} + /screenfull/5.1.0: + resolution: {integrity: sha512-dYaNuOdzr+kc6J6CFcBrzkLCfyGcMg+gWkJ8us93IQ7y1cevhQAugFsaCdMHb6lw8KV3xPzSxzH7zM1dQap9mA==} engines: {node: '>=0.10.0'} dev: false @@ -21816,8 +21887,8 @@ packages: /source-list-map/2.0.1: resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==} - /source-map-js/1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + /source-map-js/1.0.1: + resolution: {integrity: sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==} engines: {node: '>=0.10.0'} dev: true @@ -21829,12 +21900,13 @@ packages: dependencies: abab: 2.0.5 iconv-lite: 0.6.3 - source-map-js: 1.0.2 + source-map-js: 1.0.1 webpack: 5.67.0 dev: true /source-map-resolve/0.5.3: resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated dependencies: atob: 2.1.2 decode-uri-component: 0.2.0 @@ -21854,6 +21926,13 @@ packages: source-map: 0.5.7 dev: false + /source-map-support/0.5.20: + resolution: {integrity: sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + /source-map-support/0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} dependencies: @@ -21862,6 +21941,7 @@ packages: /source-map-url/0.4.1: resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} + deprecated: See https://github.com/lydell/source-map-url#deprecated /source-map/0.5.6: resolution: {integrity: sha1-dc449SvwczxafwwRjYEzSiu19BI=} @@ -21897,7 +21977,7 @@ packages: resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.10 + spdx-license-ids: 3.0.11 /spdx-exceptions/2.3.0: resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} @@ -21906,10 +21986,10 @@ packages: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} dependencies: spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.10 + spdx-license-ids: 3.0.11 - /spdx-license-ids/3.0.10: - resolution: {integrity: sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==} + /spdx-license-ids/3.0.11: + resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==} /spdy-transport/3.0.0: resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} @@ -21962,7 +22042,7 @@ packages: engines: {node: '>=0.10.0'} hasBin: true dependencies: - asn1: 0.2.4 + asn1: 0.2.6 assert-plus: 1.0.0 bcrypt-pbkdf: 1.0.2 dashdash: 1.14.1 @@ -22040,8 +22120,8 @@ packages: resolution: {integrity: sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=} engines: {node: '>= 0.6'} - /store2/2.13.1: - resolution: {integrity: sha512-iJtHSGmNgAUx0b/MCS6ASGxb//hGrHHRgzvN+K5bvkBTN7A9RTpPSf1WSp+nPGvWCJ1jRnvY7MKnuqfoi3OEqg==} + /store2/2.12.0: + resolution: {integrity: sha512-7t+/wpKLanLzSnQPX8WAcuLCCeuSHoWdQuh9SB3xD0kNOM38DNf+0Oa+wmvxmYueRzkmh6IcdKFtvTa+ecgPDw==} dev: true /stream-browserify/2.0.2: @@ -22116,7 +22196,6 @@ packages: dependencies: is-fullwidth-code-point: 2.0.0 strip-ansi: 4.0.0 - dev: false /string-width/4.2.2: resolution: {integrity: sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==} @@ -22135,12 +22214,12 @@ packages: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - /string-width/5.1.0: - resolution: {integrity: sha512-7x54QnN21P+XL/v8SuNKvfgsUre6PXpN7mc77N3HlZv+f1SBRGmjxtOud2Z6FZ8DmdkD/IdjCaf9XXbnqmTZGQ==} + /string-width/5.0.1: + resolution: {integrity: sha512-5ohWO/M4//8lErlUUtrFy3b11GtNOuMOU0ysKCDXFcfXuuvUXu95akgj/i8ofmaGdN0hCqyl6uu9i8dS/mQp5g==} engines: {node: '>=12'} dependencies: - eastasianwidth: 0.2.0 emoji-regex: 9.2.2 + is-fullwidth-code-point: 4.0.0 strip-ansi: 7.0.1 dev: true @@ -22221,7 +22300,6 @@ packages: engines: {node: '>=4'} dependencies: ansi-regex: 3.0.0 - dev: false /strip-ansi/6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} @@ -22322,7 +22400,7 @@ packages: glob: 7.1.6 lines-and-columns: 1.2.4 mz: 2.7.0 - pirates: 4.0.5 + pirates: 4.0.4 ts-interface-checker: 0.1.13 dev: true @@ -22364,8 +22442,6 @@ packages: /supports-color/9.2.1: resolution: {integrity: sha512-Obv7ycoCTG51N7y175StI9BlAXrmgZrFhZOb0/PyjHBher/NmsdBgbbQ1Inhq+gIhz6+7Gb+jWF2Vqi7Mf1xnQ==} engines: {node: '>=12'} - dependencies: - has-flag: 5.0.1 dev: true /supports-hyperlinks/2.2.0: @@ -22376,10 +22452,6 @@ packages: supports-color: 7.2.0 dev: true - /supports-preserve-symlinks-flag/1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - /sver-compat/1.5.0: resolution: {integrity: sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=} dependencies: @@ -22606,8 +22678,8 @@ packages: - acorn dev: true - /terser-webpack-plugin/5.3.0_webpack@5.67.0: - resolution: {integrity: sha512-LPIisi3Ol4chwAaPP8toUJ3L4qCM1G0wao7L3qNv57Drezxj6+VEyySpPw4B1HSO2Eg/hDY/MNF5XihCAoqnsQ==} + /terser-webpack-plugin/5.2.5_webpack@5.67.0: + resolution: {integrity: sha512-3luOVHku5l0QBeYS8r4CdHYWEGMmIj3H1U64jgkdZzECcSOJAyJ9TjuqcQZvw1Y+4AOBN9SeYJPJmFn2cM4/2g==} engines: {node: '>= 10.13.0'} peerDependencies: '@swc/core': '*' @@ -22622,7 +22694,7 @@ packages: uglify-js: optional: true dependencies: - jest-worker: 27.4.6 + jest-worker: 27.4.5 schema-utils: 3.1.1 serialize-javascript: 6.0.0 source-map: 0.6.1 @@ -22689,6 +22761,26 @@ packages: source-map-support: 0.5.21 dev: true + /terser/5.8.0: + resolution: {integrity: sha512-f0JH+6yMpneYcRJN314lZrSwu9eKkUFEHLN/kNy8ceh8gaRiLgFPJqrB9HsXjhEGdv4e/ekjTOFxIlL6xlma8A==} + engines: {node: '>=10'} + hasBin: true + dependencies: + commander: 2.20.3 + source-map: 0.7.3 + source-map-support: 0.5.20 + dev: true + + /terser/5.9.0: + resolution: {integrity: sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + commander: 2.20.3 + source-map: 0.7.3 + source-map-support: 0.5.21 + dev: true + /test-exclude/6.0.0: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} @@ -22991,6 +23083,10 @@ packages: resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==} dev: false + /ts-essentials/2.0.12: + resolution: {integrity: sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w==} + dev: true + /ts-essentials/7.0.2_typescript@4.6.0-dev.20211202: resolution: {integrity: sha512-qWPVC1xZGdefbsgFP7tPo+bsgSA2ZIXL1XeEe5M2WoMZxIOr/HbsHxP/Iv75IFhiMHMDGL7cOOwi5SXcgx9mHw==} peerDependencies: @@ -23036,7 +23132,7 @@ packages: yargs-parser: 20.2.9 dev: true - /ts-node/10.4.0_typescript@4.5.5: + /ts-node/10.4.0_typescript@4.5.4: resolution: {integrity: sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==} hasBin: true peerDependencies: @@ -23061,7 +23157,7 @@ packages: create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 4.5.5 + typescript: 4.5.4 yn: 3.1.1 dev: true @@ -23169,7 +23265,7 @@ packages: js-yaml: 3.14.1 minimatch: 3.0.4 mkdirp: 0.5.5 - resolve: 1.22.0 + resolve: 1.20.0 semver: 5.7.1 tslib: 1.14.1 tsutils: 2.29.0_typescript@2.9.2 @@ -23368,8 +23464,8 @@ packages: hasBin: true dev: false - /typescript/4.5.5: - resolution: {integrity: sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==} + /typescript/4.5.4: + resolution: {integrity: sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==} engines: {node: '>=4.2.0'} hasBin: true dev: true @@ -23413,8 +23509,8 @@ packages: uglify-to-browserify: 1.0.2 dev: false - /uglify-js/3.15.0: - resolution: {integrity: sha512-x+xdeDWq7FiORDvyIJ0q/waWd4PhjBNOm5dQUOq2AKC0IEjxOS66Ha9tctiVDGcRQuh69K7fgU5oRuTK4cysSg==} + /uglify-js/3.14.5: + resolution: {integrity: sha512-qZukoSxOG0urUTvjc2ERMTcAy+BiFh3weWAkeurLwjrCba73poHmG3E36XEjd/JGukMzwTL7uCxZiAexj8ppvQ==} engines: {node: '>=0.8.0'} hasBin: true requiresBuild: true @@ -23701,12 +23797,13 @@ packages: resolution: {integrity: sha512-12c4Vi40DHVdZ/8mOLjZjp0asCzM6hi8Gj116fpImRP1FN4gBMCtMi9XhLNOmre/FEQYNqHbZmX8iyYAtIcy8Q==} dev: false - /use-composed-ref/1.2.1_react@18.0.0-rc.0: - resolution: {integrity: sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw==} + /use-composed-ref/1.1.0_react@18.0.0-rc.0: + resolution: {integrity: sha512-my1lNHGWsSDAhhVAT4MKs6IjBUtG6ZG11uUqexPH9PptiIZDQOzaF4f5tEbJ2+7qvNbtXNBbU3SfmN+fXlWDhg==} peerDependencies: react: ^16.8.0 || ^17.0.0 dependencies: react: 18.0.0-rc.0 + ts-essentials: 2.0.12 dev: true /use-isomorphic-layout-effect/1.1.1_2fa291bfae6e56080648438396754a97: @@ -23755,15 +23852,6 @@ packages: dependencies: node-gyp-build: 4.3.0 - /utf-8-validate/5.0.8: - resolution: {integrity: sha512-k4dW/Qja1BYDl2qD4tOMB9PFVha/UJtxTc1cXYOe3WwA/2m0Yn4qB7wLMpJyLJ/7DR0XnTut3HsCSzDT4ZvKgA==} - engines: {node: '>=6.14.2'} - requiresBuild: true - dependencies: - node-gyp-build: 4.3.0 - dev: false - optional: true - /utf8/2.1.2: resolution: {integrity: sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=} dev: false @@ -23838,8 +23926,8 @@ packages: resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} dev: true - /v8-to-istanbul/8.1.1: - resolution: {integrity: sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==} + /v8-to-istanbul/8.1.0: + resolution: {integrity: sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA==} engines: {node: '>=10.12.0'} dependencies: '@types/istanbul-lib-coverage': 2.0.4 @@ -23921,7 +24009,7 @@ packages: dependencies: fs-mkdirp-stream: 1.0.0 glob-stream: 6.1.0 - graceful-fs: 4.2.9 + graceful-fs: 4.2.8 is-valid-glob: 1.0.0 lazystream: 1.0.0 lead: 1.0.0 @@ -23944,7 +24032,7 @@ packages: dependencies: append-buffer: 1.0.2 convert-source-map: 1.8.0 - graceful-fs: 4.2.9 + graceful-fs: 4.2.8 normalize-path: 2.1.1 now-and-later: 2.0.1 remove-bom-buffer: 3.0.0 @@ -24032,7 +24120,7 @@ packages: graceful-fs: 4.2.9 neo-async: 2.6.2 optionalDependencies: - chokidar: 3.5.3 + chokidar: 3.5.2 watchpack-chokidar2: 2.0.1 /watchpack/2.3.1: @@ -24061,7 +24149,7 @@ packages: engines: {node: '>=8.0.0'} requiresBuild: true dependencies: - '@types/node': 16.11.7 + '@types/node': 16.11.10 got: 9.6.0 swarm-js: 0.1.40 dev: false @@ -24181,7 +24269,7 @@ packages: resolution: {integrity: sha512-nH5N2GiVC0C5XeMEKU16PeFP3Hb3hkPvlR6Tf9WQ+pE+jw1c8eaXBO1CJQLr15ikhUF3s94ICyHcfjzkDsmRbA==} engines: {node: '>=8.0.0'} dependencies: - '@types/node': 16.11.7 + '@types/node': 16.11.10 web3-core: 1.5.2 web3-core-helpers: 1.5.2 web3-core-method: 1.5.2 @@ -24412,7 +24500,7 @@ packages: commander: 7.2.0 execa: 5.1.1 fastest-levenshtein: 1.0.12 - import-local: 3.1.0 + import-local: 3.0.3 interpret: 2.2.0 rechoir: 0.7.1 webpack: 5.67.0 @@ -24442,7 +24530,7 @@ packages: dependencies: colorette: 1.4.0 mem: 8.1.1 - memfs: 3.4.1 + memfs: 3.4.0 mime-types: 2.1.34 range-parser: 1.2.1 schema-utils: 3.1.1 @@ -24456,7 +24544,7 @@ packages: webpack: ^4.0.0 || ^5.0.0 dependencies: colorette: 2.0.16 - memfs: 3.4.1 + memfs: 3.4.0 mime-types: 2.1.34 range-parser: 1.2.1 schema-utils: 4.0.0 @@ -24481,16 +24569,16 @@ packages: '@types/ws': 8.2.2 ansi-html-community: 0.0.8 bonjour: 3.5.0 - chokidar: 3.5.3 + chokidar: 3.5.2 colorette: 2.0.16 compression: 1.7.4 connect-history-api-fallback: 1.6.0 default-gateway: 6.0.3 del: 6.0.0 express: 4.17.2 - graceful-fs: 4.2.9 + graceful-fs: 4.2.8 html-entities: 2.3.2 - http-proxy-middleware: 2.0.2 + http-proxy-middleware: 2.0.1 ipaddr.js: 2.0.1 open: 8.4.0 p-retry: 4.6.1 @@ -24504,9 +24592,8 @@ packages: webpack: 5.67.0 webpack-cli: 4.9.2_4df292f2573ba77e77217391b9684f0a webpack-dev-middleware: 5.3.0_webpack@5.67.0 - ws: 8.4.2 + ws: 8.4.0 transitivePeerDependencies: - - '@types/express' - bufferutil - debug - supports-color @@ -24946,8 +25033,8 @@ packages: optional: true dev: false - /ws/7.5.5: - resolution: {integrity: sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==} + /ws/7.5.6: + resolution: {integrity: sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==} engines: {node: '>=8.3.0'} peerDependencies: bufferutil: ^4.0.1 @@ -24957,10 +25044,9 @@ packages: optional: true utf-8-validate: optional: true - dev: false - /ws/7.5.5_bffff4271b89d628e8333ead80d3d8e8: - resolution: {integrity: sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==} + /ws/7.5.6_72ef9f06cb99540da679cbf1bf7a3256: + resolution: {integrity: sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==} engines: {node: '>=8.3.0'} peerDependencies: bufferutil: ^4.0.1 @@ -24971,23 +25057,10 @@ packages: utf-8-validate: optional: true dependencies: - bufferutil: 4.0.6 - utf-8-validate: 5.0.8 + bufferutil: 4.0.3 + utf-8-validate: 5.0.5 dev: false - /ws/7.5.6: - resolution: {integrity: sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - /ws/8.4.0: resolution: {integrity: sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==} engines: {node: '>=10.0.0'} @@ -24999,20 +25072,6 @@ packages: optional: true utf-8-validate: optional: true - dev: false - - /ws/8.4.2: - resolution: {integrity: sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true /xdg-basedir/4.0.0: resolution: {integrity: sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==} @@ -25360,7 +25419,7 @@ packages: '@0xproject/utils': 0.1.3 '@0xproject/web3-wrapper': 0.1.14 '@types/lodash': 4.14.178 - '@types/node': 16.11.21 + '@types/node': 16.11.17 0x.js: 0.29.2 awesome-typescript-loader: 3.5.0_typescript@2.9.2 bn.js: 4.12.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 03fa5787a12b..9cf4f9cff5b6 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -9,6 +9,8 @@ packages: - 'packages/dashboard' - 'packages/mask' - 'packages/injected-script' + - 'packages/gun-utils' + - 'packages/typed-message' - 'packages/mask-sdk' - 'packages/public-api' - 'packages/shared-base'