mirror of
https://iceshrimp.dev/crimekillz/iceshrimp-161sh.git
synced 2024-11-25 05:29:07 +01:00
Merge branch 'develop' of https://codeberg.org/calckey/calckey into upstream
This commit is contained in:
commit
170b60cefe
@ -118,6 +118,7 @@
|
|||||||
- Skin tone selection support
|
- Skin tone selection support
|
||||||
- [DragonflyDB](https://dragonflydb.io/) support as a Redis alternative
|
- [DragonflyDB](https://dragonflydb.io/) support as a Redis alternative
|
||||||
- Link verification
|
- Link verification
|
||||||
|
- Importing posts from other Calckey/Misskey/Mastodon/Akkoma/Pleroma instances
|
||||||
|
|
||||||
## Implemented (remote)
|
## Implemented (remote)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "calckey",
|
"name": "calckey",
|
||||||
"version": "14.0.0-dev79",
|
"version": "14.0.0-dev83",
|
||||||
"codename": "aqua",
|
"codename": "aqua",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
145
packages/backend/native-utils/Cargo.lock
generated
145
packages/backend/native-utils/Cargo.lock
generated
@ -458,6 +458,20 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "combine"
|
||||||
|
version = "4.6.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"memchr",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "console"
|
name = "console"
|
||||||
version = "0.15.7"
|
version = "0.15.7"
|
||||||
@ -486,6 +500,16 @@ dependencies = [
|
|||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "core-foundation-sys"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
@ -1278,11 +1302,14 @@ dependencies = [
|
|||||||
"futures",
|
"futures",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
"native-utils",
|
"native-utils",
|
||||||
|
"redis",
|
||||||
|
"sea-orm",
|
||||||
"sea-orm-migration",
|
"sea-orm-migration",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"url",
|
||||||
"urlencoding",
|
"urlencoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1509,6 +1536,12 @@ version = "1.18.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-probe"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_str_bytes"
|
name = "os_str_bytes"
|
||||||
version = "6.5.0"
|
version = "6.5.0"
|
||||||
@ -1843,6 +1876,29 @@ dependencies = [
|
|||||||
"rand_core",
|
"rand_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redis"
|
||||||
|
version = "0.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ea8c51b5dc1d8e5fd3350ec8167f464ec0995e79f2e90a075b63371500d557f"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"bytes",
|
||||||
|
"combine",
|
||||||
|
"futures-util",
|
||||||
|
"itoa",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project-lite",
|
||||||
|
"rustls 0.21.3",
|
||||||
|
"rustls-native-certs",
|
||||||
|
"ryu",
|
||||||
|
"sha1_smol",
|
||||||
|
"tokio",
|
||||||
|
"tokio-rustls 0.24.1",
|
||||||
|
"tokio-util",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@ -2043,6 +2099,30 @@ dependencies = [
|
|||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls"
|
||||||
|
version = "0.21.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b19faa85ecb5197342b54f987b142fb3e30d0c90da40f80ef4fa9a726e6676ed"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"ring",
|
||||||
|
"rustls-webpki",
|
||||||
|
"sct",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-native-certs"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00"
|
||||||
|
dependencies = [
|
||||||
|
"openssl-probe",
|
||||||
|
"rustls-pemfile",
|
||||||
|
"schannel",
|
||||||
|
"security-framework",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pemfile"
|
name = "rustls-pemfile"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@ -2052,6 +2132,16 @@ dependencies = [
|
|||||||
"base64 0.21.2",
|
"base64 0.21.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-webpki"
|
||||||
|
version = "0.101.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
@ -2076,6 +2166,15 @@ version = "1.0.13"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schannel"
|
||||||
|
version = "0.1.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schemars"
|
name = "schemars"
|
||||||
version = "0.8.12"
|
version = "0.8.12"
|
||||||
@ -2286,6 +2385,29 @@ version = "4.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "2.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"core-foundation",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework-sys"
|
||||||
|
version = "2.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.17"
|
version = "1.0.17"
|
||||||
@ -2370,6 +2492,12 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1_smol"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
@ -2518,7 +2646,7 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rand",
|
"rand",
|
||||||
"rust_decimal",
|
"rust_decimal",
|
||||||
"rustls",
|
"rustls 0.20.8",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -2564,7 +2692,7 @@ checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls 0.23.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2778,11 +2906,21 @@ version = "0.23.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls",
|
"rustls 0.20.8",
|
||||||
"tokio",
|
"tokio",
|
||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-rustls"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
|
||||||
|
dependencies = [
|
||||||
|
"rustls 0.21.3",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-stream"
|
name = "tokio-stream"
|
||||||
version = "0.1.14"
|
version = "0.1.14"
|
||||||
@ -2949,6 +3087,7 @@ dependencies = [
|
|||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"idna",
|
"idna",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -9,7 +9,7 @@ members = ["migration"]
|
|||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
noarray = []
|
noarray = []
|
||||||
napi = ["dep:napi", "dep:napi-derive", "dep:radix_fmt"]
|
napi = ["dep:napi", "dep:napi-derive"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib", "lib"]
|
crate-type = ["cdylib", "lib"]
|
||||||
@ -31,11 +31,11 @@ serde_json = "1.0.96"
|
|||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
tokio = { version = "1.28.1", features = ["full"] }
|
tokio = { version = "1.28.1", features = ["full"] }
|
||||||
utoipa = "3.3.0"
|
utoipa = "3.3.0"
|
||||||
|
radix_fmt = "1.0.0"
|
||||||
|
|
||||||
# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
|
# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
|
||||||
napi = { version = "2.13.1", default-features = false, features = ["napi6", "tokio_rt"], optional = true }
|
napi = { version = "2.13.1", default-features = false, features = ["napi6", "tokio_rt"], optional = true }
|
||||||
napi-derive = { version = "2.12.0", optional = true }
|
napi-derive = { version = "2.12.0", optional = true }
|
||||||
radix_fmt = { version = "1.0.0", optional = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "1.3.0"
|
pretty_assertions = "1.3.0"
|
||||||
|
@ -12,18 +12,18 @@ test("convert to mastodon id", (t) => {
|
|||||||
t.is(convertId("9gf61ehcxv", IdConvertType.MastodonId), "960365976481219");
|
t.is(convertId("9gf61ehcxv", IdConvertType.MastodonId), "960365976481219");
|
||||||
t.is(
|
t.is(
|
||||||
convertId("9fbr9z0wbrjqyd3u", IdConvertType.MastodonId),
|
convertId("9fbr9z0wbrjqyd3u", IdConvertType.MastodonId),
|
||||||
"3954607381600562394",
|
"2083785058661759970208986",
|
||||||
);
|
);
|
||||||
t.is(
|
t.is(
|
||||||
convertId("9fbs680oyviiqrol9md73p8g", IdConvertType.MastodonId),
|
convertId("9fbs680oyviiqrol9md73p8g", IdConvertType.MastodonId),
|
||||||
"3494513243013053824",
|
"5878598648988104013828532260828151168",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("create cuid2 with timestamp prefix", (t) => {
|
test("create cuid2 with timestamp prefix", (t) => {
|
||||||
nativeInitIdGenerator(16, "");
|
nativeInitIdGenerator(16, "");
|
||||||
t.not(nativeCreateId(BigInt(Date.now())), nativeCreateId(BigInt(Date.now())));
|
t.not(nativeCreateId(Date.now()), nativeCreateId(Date.now()));
|
||||||
t.is(nativeCreateId(BigInt(Date.now())).length, 16);
|
t.is(nativeCreateId(Date.now()).length, 16);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("create random string", (t) => {
|
test("create random string", (t) => {
|
||||||
|
@ -21,6 +21,9 @@ futures = { version = "0.3.28", optional = true }
|
|||||||
serde_yaml = "0.9.21"
|
serde_yaml = "0.9.21"
|
||||||
serde = { version = "1.0.163", features = ["derive"] }
|
serde = { version = "1.0.163", features = ["derive"] }
|
||||||
urlencoding = "2.1.2"
|
urlencoding = "2.1.2"
|
||||||
|
redis = { version = "0.23.0", features = ["tokio-rustls-comp"] }
|
||||||
|
sea-orm = "0.11.3"
|
||||||
|
url = { version = "2.4.0", features = ["serde"] }
|
||||||
|
|
||||||
[dependencies.sea-orm-migration]
|
[dependencies.sea-orm-migration]
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
@ -2,6 +2,7 @@ pub use sea_orm_migration::prelude::*;
|
|||||||
|
|
||||||
mod m20230531_180824_drop_reversi;
|
mod m20230531_180824_drop_reversi;
|
||||||
mod m20230627_185451_index_note_url;
|
mod m20230627_185451_index_note_url;
|
||||||
|
mod m20230709_000510_move_antenna_to_cache;
|
||||||
|
|
||||||
pub struct Migrator;
|
pub struct Migrator;
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ impl MigratorTrait for Migrator {
|
|||||||
vec![
|
vec![
|
||||||
Box::new(m20230531_180824_drop_reversi::Migration),
|
Box::new(m20230531_180824_drop_reversi::Migration),
|
||||||
Box::new(m20230627_185451_index_note_url::Migration),
|
Box::new(m20230627_185451_index_note_url::Migration),
|
||||||
|
Box::new(m20230709_000510_move_antenna_to_cache::Migration),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,248 @@
|
|||||||
|
use redis::streams::StreamMaxlen;
|
||||||
|
use sea_orm::Statement;
|
||||||
|
use sea_orm_migration::prelude::*;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
#[derive(DeriveMigrationName)]
|
||||||
|
pub struct Migration;
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl MigrationTrait for Migration {
|
||||||
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
let cache_url = env::var("CACHE_URL").unwrap();
|
||||||
|
let skip_copy = env::var("ANTENNA_MIGRATION_SKIP").unwrap_or_default();
|
||||||
|
let copy_limit = env::var("ANTENNA_MIGRATION_COPY_LIMIT").unwrap_or_default();
|
||||||
|
let read_limit: u64 = env::var("ANTENNA_MIGRATION_READ_LIMIT")
|
||||||
|
.unwrap_or("10000".to_string())
|
||||||
|
.parse()
|
||||||
|
.unwrap();
|
||||||
|
let copy_limit: i64 = match copy_limit.parse() {
|
||||||
|
Ok(limit) => limit,
|
||||||
|
Err(_) => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
if skip_copy == "true" {
|
||||||
|
println!("Skipped antenna migration");
|
||||||
|
} else {
|
||||||
|
let prefix = env::var("CACHE_PREFIX").unwrap();
|
||||||
|
|
||||||
|
let db = manager.get_connection();
|
||||||
|
let bk = manager.get_database_backend();
|
||||||
|
|
||||||
|
let count_stmt =
|
||||||
|
Statement::from_string(bk, "SELECT COUNT(1) FROM antenna_note".to_owned());
|
||||||
|
let total_num = db
|
||||||
|
.query_one(count_stmt)
|
||||||
|
.await?
|
||||||
|
.unwrap()
|
||||||
|
.try_get_by_index::<i64>(0)?;
|
||||||
|
let copy_limit = if copy_limit > 0 {
|
||||||
|
copy_limit
|
||||||
|
} else {
|
||||||
|
total_num
|
||||||
|
};
|
||||||
|
println!(
|
||||||
|
"Copying {} out of {} entries in antenna_note.",
|
||||||
|
copy_limit, total_num
|
||||||
|
);
|
||||||
|
|
||||||
|
let stmt_base = Query::select()
|
||||||
|
.column((AntennaNote::Table, AntennaNote::Id))
|
||||||
|
.column(AntennaNote::AntennaId)
|
||||||
|
.column(AntennaNote::NoteId)
|
||||||
|
.from(AntennaNote::Table)
|
||||||
|
.order_by((AntennaNote::Table, AntennaNote::Id), Order::Asc)
|
||||||
|
.limit(read_limit)
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
|
let mut stmt = stmt_base.clone();
|
||||||
|
|
||||||
|
let client = redis::Client::open(cache_url).unwrap();
|
||||||
|
let mut redis_conn = client.get_connection().unwrap();
|
||||||
|
|
||||||
|
let mut remaining = total_num;
|
||||||
|
let mut pagination: i64 = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let res = db.query_all(bk.build(&stmt)).await?;
|
||||||
|
if res.len() == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let val: Vec<(String, String, String)> = res
|
||||||
|
.iter()
|
||||||
|
.filter_map(|q| q.try_get_many_by_index().ok())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
remaining -= val.len() as i64;
|
||||||
|
if remaining <= copy_limit {
|
||||||
|
let mut pipe = redis::pipe();
|
||||||
|
for v in &val {
|
||||||
|
pipe.xadd_maxlen(
|
||||||
|
format!("{}:antennaTimeline:{}", prefix, v.1),
|
||||||
|
StreamMaxlen::Approx(200),
|
||||||
|
"*",
|
||||||
|
&[("note", v.2.to_owned())],
|
||||||
|
)
|
||||||
|
.ignore();
|
||||||
|
}
|
||||||
|
pipe.query::<()>(&mut redis_conn).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let copied = total_num - remaining;
|
||||||
|
let copied = std::cmp::min(copied, total_num);
|
||||||
|
pagination += 1;
|
||||||
|
if pagination % 10 == 0 {
|
||||||
|
println!(
|
||||||
|
"Migrating antenna [{:.2}%]",
|
||||||
|
(copied as f64 / total_num as f64) * 100_f64,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((last_id, _, _)) = val.last() {
|
||||||
|
stmt = stmt_base
|
||||||
|
.clone()
|
||||||
|
.and_where(
|
||||||
|
Expr::col((AntennaNote::Table, AntennaNote::Id)).gt(last_id.to_owned()),
|
||||||
|
)
|
||||||
|
.to_owned();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Migrating antenna [100.00%]");
|
||||||
|
}
|
||||||
|
|
||||||
|
manager
|
||||||
|
.drop_table(
|
||||||
|
Table::drop()
|
||||||
|
.table(AntennaNote::Table)
|
||||||
|
.if_exists()
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(AntennaNote::Table)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(AntennaNote::Id)
|
||||||
|
.string_len(32)
|
||||||
|
.not_null()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(AntennaNote::NoteId)
|
||||||
|
.string_len(32)
|
||||||
|
.not_null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(AntennaNote::AntennaId)
|
||||||
|
.string_len(32)
|
||||||
|
.not_null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(AntennaNote::Read)
|
||||||
|
.boolean()
|
||||||
|
.default(false)
|
||||||
|
.not_null(),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("IDX_0d775946662d2575dfd2068a5f")
|
||||||
|
.table(AntennaNote::Table)
|
||||||
|
.col(AntennaNote::AntennaId)
|
||||||
|
.if_not_exists()
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("IDX_bd0397be22147e17210940e125")
|
||||||
|
.table(AntennaNote::Table)
|
||||||
|
.col(AntennaNote::NoteId)
|
||||||
|
.if_not_exists()
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("IDX_335a0bf3f904406f9ef3dd51c2")
|
||||||
|
.table(AntennaNote::Table)
|
||||||
|
.col(AntennaNote::NoteId)
|
||||||
|
.col(AntennaNote::AntennaId)
|
||||||
|
.unique()
|
||||||
|
.if_not_exists()
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
manager
|
||||||
|
.create_index(
|
||||||
|
Index::create()
|
||||||
|
.name("IDX_9937ea48d7ae97ffb4f3f063a4")
|
||||||
|
.table(AntennaNote::Table)
|
||||||
|
.col(AntennaNote::Read)
|
||||||
|
.if_not_exists()
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
manager
|
||||||
|
.create_foreign_key(
|
||||||
|
ForeignKey::create()
|
||||||
|
.name("FK_0d775946662d2575dfd2068a5f5")
|
||||||
|
.from(AntennaNote::Table, AntennaNote::AntennaId)
|
||||||
|
.to(Antenna::Table, Antenna::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
manager
|
||||||
|
.create_foreign_key(
|
||||||
|
ForeignKey::create()
|
||||||
|
.name("FK_bd0397be22147e17210940e125b")
|
||||||
|
.from(AntennaNote::Table, AntennaNote::NoteId)
|
||||||
|
.to(Note::Table, Note::Id)
|
||||||
|
.on_delete(ForeignKeyAction::Cascade)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Learn more at https://docs.rs/sea-query#iden
|
||||||
|
#[derive(Iden)]
|
||||||
|
enum AntennaNote {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
#[iden = "noteId"]
|
||||||
|
NoteId,
|
||||||
|
#[iden = "antennaId"]
|
||||||
|
AntennaId,
|
||||||
|
Read,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Iden)]
|
||||||
|
enum Antenna {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Iden)]
|
||||||
|
enum Note {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
}
|
@ -5,6 +5,10 @@ use urlencoding::encode;
|
|||||||
|
|
||||||
use sea_orm_migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
|
const DB_URL_ENV: &str = "DATABASE_URL";
|
||||||
|
const CACHE_URL_ENV: &str = "CACHE_URL";
|
||||||
|
const CACHE_PREFIX_ENV: &str = "CACHE_PREFIX";
|
||||||
|
|
||||||
#[cfg(feature = "convert")]
|
#[cfg(feature = "convert")]
|
||||||
mod vec_to_json;
|
mod vec_to_json;
|
||||||
|
|
||||||
@ -15,8 +19,9 @@ async fn main() {
|
|||||||
.expect("Failed to open '.config/default.yml'");
|
.expect("Failed to open '.config/default.yml'");
|
||||||
let config: Config = serde_yaml::from_reader(yml).expect("Failed to parse yaml");
|
let config: Config = serde_yaml::from_reader(yml).expect("Failed to parse yaml");
|
||||||
|
|
||||||
|
if env::var_os(DB_URL_ENV).is_none() {
|
||||||
env::set_var(
|
env::set_var(
|
||||||
"DATABASE_URL",
|
DB_URL_ENV,
|
||||||
format!(
|
format!(
|
||||||
"postgres://{}:{}@{}:{}/{}",
|
"postgres://{}:{}@{}:{}/{}",
|
||||||
config.db.user,
|
config.db.user,
|
||||||
@ -26,6 +31,36 @@ async fn main() {
|
|||||||
config.db.db,
|
config.db.db,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if env::var_os(CACHE_URL_ENV).is_none() {
|
||||||
|
let redis_conf = match config.cache_server {
|
||||||
|
None => config.redis,
|
||||||
|
Some(conf) => conf,
|
||||||
|
};
|
||||||
|
let redis_proto = match redis_conf.tls {
|
||||||
|
None => "redis",
|
||||||
|
Some(_) => "rediss",
|
||||||
|
};
|
||||||
|
let redis_uri_userpass = match redis_conf.user {
|
||||||
|
None => "".to_string(),
|
||||||
|
Some(user) => format!("{}:{}@", user, encode(&redis_conf.pass.unwrap_or_default())),
|
||||||
|
};
|
||||||
|
let redis_uri_hostport = format!("{}:{}", redis_conf.host, redis_conf.port);
|
||||||
|
let redis_uri = format!(
|
||||||
|
"{}://{}{}/{}",
|
||||||
|
redis_proto, redis_uri_userpass, redis_uri_hostport, redis_conf.db
|
||||||
|
);
|
||||||
|
env::set_var(CACHE_URL_ENV, redis_uri);
|
||||||
|
env::set_var(
|
||||||
|
CACHE_PREFIX_ENV,
|
||||||
|
if redis_conf.prefix.is_empty() {
|
||||||
|
config.url.host_str().unwrap()
|
||||||
|
} else {
|
||||||
|
&redis_conf.prefix
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
cli::run_cli(migration::Migrator).await;
|
cli::run_cli(migration::Migrator).await;
|
||||||
|
|
||||||
@ -34,13 +69,15 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Deserialize)]
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
#[serde(rename = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
pub url: url::Url,
|
||||||
pub db: DbConfig,
|
pub db: DbConfig,
|
||||||
|
pub redis: RedisConfig,
|
||||||
|
pub cache_server: Option<RedisConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Deserialize)]
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
#[serde(rename = "camelCase")]
|
|
||||||
pub struct DbConfig {
|
pub struct DbConfig {
|
||||||
pub host: String,
|
pub host: String,
|
||||||
pub port: u32,
|
pub port: u32,
|
||||||
@ -48,3 +85,23 @@ pub struct DbConfig {
|
|||||||
pub user: String,
|
pub user: String,
|
||||||
pub pass: String,
|
pub pass: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
|
pub struct RedisConfig {
|
||||||
|
pub host: String,
|
||||||
|
pub port: u32,
|
||||||
|
pub user: Option<String>,
|
||||||
|
pub pass: Option<String>,
|
||||||
|
pub tls: Option<TlsConfig>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub db: u32,
|
||||||
|
#[serde(default)]
|
||||||
|
pub prefix: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct TlsConfig {
|
||||||
|
pub host: String,
|
||||||
|
pub reject_unauthorized: bool,
|
||||||
|
}
|
||||||
|
@ -8,7 +8,6 @@ pub mod ad;
|
|||||||
pub mod announcement;
|
pub mod announcement;
|
||||||
pub mod announcement_read;
|
pub mod announcement_read;
|
||||||
pub mod antenna;
|
pub mod antenna;
|
||||||
pub mod antenna_note;
|
|
||||||
pub mod app;
|
pub mod app;
|
||||||
pub mod attestation_challenge;
|
pub mod attestation_challenge;
|
||||||
pub mod auth_session;
|
pub mod auth_session;
|
||||||
|
@ -15,6 +15,10 @@ pub struct Model {
|
|||||||
pub image_url: Option<String>,
|
pub image_url: Option<String>,
|
||||||
#[sea_orm(column_name = "updatedAt")]
|
#[sea_orm(column_name = "updatedAt")]
|
||||||
pub updated_at: Option<DateTimeWithTimeZone>,
|
pub updated_at: Option<DateTimeWithTimeZone>,
|
||||||
|
#[sea_orm(column_name = "showPopup")]
|
||||||
|
pub show_popup: bool,
|
||||||
|
#[sea_orm(column_name = "isGoodNews")]
|
||||||
|
pub is_good_news: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
@ -37,8 +37,6 @@ pub struct Model {
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
pub enum Relation {
|
pub enum Relation {
|
||||||
#[sea_orm(has_many = "super::antenna_note::Entity")]
|
|
||||||
AntennaNote,
|
|
||||||
#[sea_orm(
|
#[sea_orm(
|
||||||
belongs_to = "super::user::Entity",
|
belongs_to = "super::user::Entity",
|
||||||
from = "Column::UserId",
|
from = "Column::UserId",
|
||||||
@ -65,12 +63,6 @@ pub enum Relation {
|
|||||||
UserList,
|
UserList,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Related<super::antenna_note::Entity> for Entity {
|
|
||||||
fn to() -> RelationDef {
|
|
||||||
Relation::AntennaNote.def()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Related<super::user::Entity> for Entity {
|
impl Related<super::user::Entity> for Entity {
|
||||||
fn to() -> RelationDef {
|
fn to() -> RelationDef {
|
||||||
Relation::User.def()
|
Relation::User.def()
|
||||||
|
@ -189,6 +189,10 @@ pub struct Model {
|
|||||||
pub silenced_hosts: StringVec,
|
pub silenced_hosts: StringVec,
|
||||||
#[sea_orm(column_name = "experimentalFeatures", column_type = "JsonBinary")]
|
#[sea_orm(column_name = "experimentalFeatures", column_type = "JsonBinary")]
|
||||||
pub experimental_features: Json,
|
pub experimental_features: Json,
|
||||||
|
#[sea_orm(column_name = "enableServerMachineStats")]
|
||||||
|
pub enable_server_machine_stats: bool,
|
||||||
|
#[sea_orm(column_name = "enableIdenticonGeneration")]
|
||||||
|
pub enable_identicon_generation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
@ -67,8 +67,6 @@ pub struct Model {
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
pub enum Relation {
|
pub enum Relation {
|
||||||
#[sea_orm(has_many = "super::antenna_note::Entity")]
|
|
||||||
AntennaNote,
|
|
||||||
#[sea_orm(
|
#[sea_orm(
|
||||||
belongs_to = "super::channel::Entity",
|
belongs_to = "super::channel::Entity",
|
||||||
from = "Column::ChannelId",
|
from = "Column::ChannelId",
|
||||||
@ -131,12 +129,6 @@ pub enum Relation {
|
|||||||
UserNotePining,
|
UserNotePining,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Related<super::antenna_note::Entity> for Entity {
|
|
||||||
fn to() -> RelationDef {
|
|
||||||
Relation::AntennaNote.def()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Related<super::channel::Entity> for Entity {
|
impl Related<super::channel::Entity> for Entity {
|
||||||
fn to() -> RelationDef {
|
fn to() -> RelationDef {
|
||||||
Relation::Channel.def()
|
Relation::Channel.def()
|
||||||
|
@ -6,7 +6,6 @@ pub use super::ad::Entity as Ad;
|
|||||||
pub use super::announcement::Entity as Announcement;
|
pub use super::announcement::Entity as Announcement;
|
||||||
pub use super::announcement_read::Entity as AnnouncementRead;
|
pub use super::announcement_read::Entity as AnnouncementRead;
|
||||||
pub use super::antenna::Entity as Antenna;
|
pub use super::antenna::Entity as Antenna;
|
||||||
pub use super::antenna_note::Entity as AntennaNote;
|
|
||||||
pub use super::app::Entity as App;
|
pub use super::app::Entity as App;
|
||||||
pub use super::attestation_challenge::Entity as AttestationChallenge;
|
pub use super::attestation_challenge::Entity as AttestationChallenge;
|
||||||
pub use super::auth_session::Entity as AuthSession;
|
pub use super::auth_session::Entity as AuthSession;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
|
use sea_orm::EntityTrait;
|
||||||
|
|
||||||
use crate::database;
|
use crate::database;
|
||||||
use crate::model::entity::{antenna, antenna_note, user_group_joining};
|
use crate::model::entity::{antenna, user_group_joining};
|
||||||
use crate::model::error::Error;
|
use crate::model::error::Error;
|
||||||
use crate::model::schema::Antenna;
|
use crate::model::schema::Antenna;
|
||||||
|
|
||||||
@ -14,12 +14,6 @@ use super::Repository;
|
|||||||
impl Repository<Antenna> for antenna::Model {
|
impl Repository<Antenna> for antenna::Model {
|
||||||
async fn pack(self) -> Result<Antenna, Error> {
|
async fn pack(self) -> Result<Antenna, Error> {
|
||||||
let db = database::get_database()?;
|
let db = database::get_database()?;
|
||||||
let has_unread_note = antenna_note::Entity::find()
|
|
||||||
.filter(antenna_note::Column::AntennaId.eq(self.id.to_owned()))
|
|
||||||
.filter(antenna_note::Column::Read.eq(false))
|
|
||||||
.one(db)
|
|
||||||
.await?
|
|
||||||
.is_some();
|
|
||||||
let user_group_joining = match self.user_group_joining_id {
|
let user_group_joining = match self.user_group_joining_id {
|
||||||
None => None,
|
None => None,
|
||||||
Some(id) => user_group_joining::Entity::find_by_id(id).one(db).await?,
|
Some(id) => user_group_joining::Entity::find_by_id(id).one(db).await?,
|
||||||
@ -52,7 +46,7 @@ impl Repository<Antenna> for antenna::Model {
|
|||||||
notify: self.notify,
|
notify: self.notify,
|
||||||
with_replies: self.with_replies,
|
with_replies: self.with_replies,
|
||||||
with_file: self.with_file,
|
with_file: self.with_file,
|
||||||
has_unread_note,
|
has_unread_note: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,9 +105,9 @@ mod unit_test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn app_valid() {
|
fn app_valid() {
|
||||||
init_id(12, "");
|
init_id(16, "");
|
||||||
let instance = json!({
|
let instance = json!({
|
||||||
"id": create_id().unwrap(),
|
"id": create_id(0).unwrap(),
|
||||||
"name": "Test App",
|
"name": "Test App",
|
||||||
"secret": gen_string(24),
|
"secret": gen_string(24),
|
||||||
"callbackUrl": "urn:ietf:wg:oauth:2.0:oob",
|
"callbackUrl": "urn:ietf:wg:oauth:2.0:oob",
|
||||||
@ -119,9 +119,9 @@ mod unit_test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn app_invalid() {
|
fn app_invalid() {
|
||||||
init_id(12, "");
|
init_id(16, "");
|
||||||
let instance = json!({
|
let instance = json!({
|
||||||
"id": create_id().unwrap(),
|
"id": create_id(0).unwrap(),
|
||||||
// "name" is required
|
// "name" is required
|
||||||
"name": null,
|
"name": null,
|
||||||
// "permission" must be one of the app permissions
|
// "permission" must be one of the app permissions
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
//! ID generation utility based on [cuid2]
|
//! ID generation utility based on [cuid2]
|
||||||
|
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
|
use chrono::Utc;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
use radix_fmt::radix_36;
|
||||||
|
use std::cmp;
|
||||||
|
|
||||||
use crate::impl_into_napi_error;
|
use crate::impl_into_napi_error;
|
||||||
|
|
||||||
@ -14,47 +17,56 @@ impl_into_napi_error!(ErrorUninitialized);
|
|||||||
static FINGERPRINT: OnceCell<String> = OnceCell::new();
|
static FINGERPRINT: OnceCell<String> = OnceCell::new();
|
||||||
static GENERATOR: OnceCell<cuid2::CuidConstructor> = OnceCell::new();
|
static GENERATOR: OnceCell<cuid2::CuidConstructor> = OnceCell::new();
|
||||||
|
|
||||||
|
const TIME_2000: i64 = 946_684_800_000;
|
||||||
|
const TIMESTAMP_LENGTH: u16 = 8;
|
||||||
|
|
||||||
/// Initializes Cuid2 generator. Must be called before any [create_id].
|
/// Initializes Cuid2 generator. Must be called before any [create_id].
|
||||||
pub fn init_id(length: u16, fingerprint: impl Into<String>) {
|
pub fn init_id<'a>(length: u16, fingerprint: &'a str) {
|
||||||
FINGERPRINT.get_or_init(move || format!("{}{}", fingerprint.into(), cuid2::create_id()));
|
FINGERPRINT.get_or_init(move || format!("{}{}", fingerprint, cuid2::create_id()));
|
||||||
GENERATOR.get_or_init(move || {
|
GENERATOR.get_or_init(move || {
|
||||||
cuid2::CuidConstructor::new()
|
cuid2::CuidConstructor::new()
|
||||||
.with_length(length)
|
// length to pass shoule be greater than or equal to 8.
|
||||||
|
.with_length(cmp::max(length - TIMESTAMP_LENGTH, 8))
|
||||||
.with_fingerprinter(|| FINGERPRINT.get().unwrap().clone())
|
.with_fingerprinter(|| FINGERPRINT.get().unwrap().clone())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns Cuid2 with the length specified by [init_id]. Must be called after
|
/// Returns Cuid2 with the length specified by [init_id]. Must be called after
|
||||||
/// [init_id], otherwise returns [ErrorUninitialized].
|
/// [init_id], otherwise returns [ErrorUninitialized].
|
||||||
pub fn create_id() -> Result<String, ErrorUninitialized> {
|
/// The current timestamp via [chrono::Utc] is used if `date_num` is `0`.
|
||||||
|
pub fn create_id(date_num: i64) -> Result<String, ErrorUninitialized> {
|
||||||
match GENERATOR.get() {
|
match GENERATOR.get() {
|
||||||
None => Err(ErrorUninitialized),
|
None => Err(ErrorUninitialized),
|
||||||
Some(gen) => Ok(gen.create_id()),
|
Some(gen) => {
|
||||||
|
let date_num = if date_num > 0 {
|
||||||
|
date_num
|
||||||
|
} else {
|
||||||
|
Utc::now().timestamp_millis()
|
||||||
|
};
|
||||||
|
let time = cmp::max(date_num - TIME_2000, 0);
|
||||||
|
Ok(format!(
|
||||||
|
"{:0>8}{}",
|
||||||
|
radix_36(time).to_string(),
|
||||||
|
gen.create_id()
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "napi")] {
|
if #[cfg(feature = "napi")] {
|
||||||
use radix_fmt::radix_36;
|
|
||||||
use std::cmp;
|
|
||||||
use napi::bindgen_prelude::BigInt;
|
|
||||||
use napi_derive::napi;
|
use napi_derive::napi;
|
||||||
|
|
||||||
const TIME_2000: u64 = 946_684_800_000;
|
|
||||||
const TIMESTAMP_LENGTH: u16 = 8;
|
|
||||||
|
|
||||||
/// Calls [init_id] inside. Must be called before [native_create_id].
|
/// Calls [init_id] inside. Must be called before [native_create_id].
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn native_init_id_generator(length: u16, fingerprint: String) {
|
pub fn native_init_id_generator(length: u16, fingerprint: String) {
|
||||||
// length to pass init_id shoule be greater than or equal to 8.
|
init_id(length, &fingerprint);
|
||||||
init_id(cmp::max(length - TIMESTAMP_LENGTH, 8), fingerprint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates
|
/// Generates
|
||||||
#[napi]
|
#[napi]
|
||||||
pub fn native_create_id(date_num: BigInt) -> String {
|
pub fn native_create_id(date_num: i64) -> String {
|
||||||
let time = cmp::max(date_num.get_u64().1 - TIME_2000, 0);
|
create_id(date_num).unwrap()
|
||||||
format!("{:0>8}{}", radix_36(time).to_string(), create_id().unwrap())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,37 +74,17 @@ cfg_if! {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod unit_test {
|
mod unit_test {
|
||||||
use crate::util::id;
|
use crate::util::id;
|
||||||
use cfg_if::cfg_if;
|
|
||||||
use pretty_assertions::{assert_eq, assert_ne};
|
use pretty_assertions::{assert_eq, assert_ne};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(feature = "napi")] {
|
|
||||||
use chrono::Utc;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn can_generate_aid_compat_ids() {
|
|
||||||
id::native_init_id_generator(20, "".to_string());
|
|
||||||
let id1 = id::native_create_id(Utc::now().timestamp_millis().into());
|
|
||||||
assert_eq!(id1.len(), 20);
|
|
||||||
let id1 = id::native_create_id(Utc::now().timestamp_millis().into());
|
|
||||||
let id2 = id::native_create_id(Utc::now().timestamp_millis().into());
|
|
||||||
assert_ne!(id1, id2);
|
|
||||||
let id1 = thread::spawn(|| id::native_create_id(Utc::now().timestamp_millis().into()));
|
|
||||||
let id2 = thread::spawn(|| id::native_create_id(Utc::now().timestamp_millis().into()));
|
|
||||||
assert_ne!(id1.join().unwrap(), id2.join().unwrap());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_generate_unique_ids() {
|
fn can_generate_unique_ids() {
|
||||||
assert_eq!(id::create_id(), Err(id::ErrorUninitialized));
|
assert_eq!(id::create_id(0), Err(id::ErrorUninitialized));
|
||||||
id::init_id(12, "");
|
id::init_id(16, "");
|
||||||
assert_eq!(id::create_id().unwrap().len(), 12);
|
assert_eq!(id::create_id(0).unwrap().len(), 16);
|
||||||
assert_ne!(id::create_id().unwrap(), id::create_id().unwrap());
|
assert_ne!(id::create_id(0).unwrap(), id::create_id(0).unwrap());
|
||||||
let id1 = thread::spawn(|| id::create_id().unwrap());
|
let id1 = thread::spawn(|| id::create_id(0).unwrap());
|
||||||
let id2 = thread::spawn(|| id::create_id().unwrap());
|
let id2 = thread::spawn(|| id::create_id(0).unwrap());
|
||||||
assert_ne!(id1.join().unwrap(), id2.join().unwrap());
|
assert_ne!(id1.join().unwrap(), id2.join().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -139,11 +139,11 @@ async fn cleanup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn setup_model(db: &DbConn) {
|
async fn setup_model(db: &DbConn) {
|
||||||
init_id(12, "");
|
init_id(16, "");
|
||||||
|
|
||||||
db.transaction::<_, (), DbErr>(|txn| {
|
db.transaction::<_, (), DbErr>(|txn| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let user_id = create_id().unwrap();
|
let user_id = create_id(0).unwrap();
|
||||||
let name = "Alice";
|
let name = "Alice";
|
||||||
let user_model = entity::user::Model {
|
let user_model = entity::user::Model {
|
||||||
id: user_id.to_owned(),
|
id: user_id.to_owned(),
|
||||||
@ -161,7 +161,7 @@ async fn setup_model(db: &DbConn) {
|
|||||||
.insert(txn)
|
.insert(txn)
|
||||||
.await?;
|
.await?;
|
||||||
let antenna_model = entity::antenna::Model {
|
let antenna_model = entity::antenna::Model {
|
||||||
id: create_id().unwrap(),
|
id: create_id(0).unwrap(),
|
||||||
created_at: Utc::now().into(),
|
created_at: Utc::now().into(),
|
||||||
user_id: user_id.to_owned(),
|
user_id: user_id.to_owned(),
|
||||||
name: "Alice Antenna".to_string(),
|
name: "Alice Antenna".to_string(),
|
||||||
@ -186,7 +186,7 @@ async fn setup_model(db: &DbConn) {
|
|||||||
.insert(txn)
|
.insert(txn)
|
||||||
.await?;
|
.await?;
|
||||||
let note_model = entity::note::Model {
|
let note_model = entity::note::Model {
|
||||||
id: create_id().unwrap(),
|
id: create_id(0).unwrap(),
|
||||||
created_at: Utc::now().into(),
|
created_at: Utc::now().into(),
|
||||||
text: Some("Testing 123".to_string()),
|
text: Some("Testing 123".to_string()),
|
||||||
user_id: user_id.to_owned(),
|
user_id: user_id.to_owned(),
|
||||||
|
@ -93,7 +93,7 @@ mod int_test {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.expect("note not found");
|
.expect("note not found");
|
||||||
let antenna_note = antenna_note::Model {
|
let antenna_note = antenna_note::Model {
|
||||||
id: util::id::create_id().unwrap(),
|
id: util::id::create_id(0).unwrap(),
|
||||||
antenna_id: alice_antenna.id.to_owned(),
|
antenna_id: alice_antenna.id.to_owned(),
|
||||||
note_id: note_model.id.to_owned(),
|
note_id: note_model.id.to_owned(),
|
||||||
read: false,
|
read: false,
|
||||||
|
@ -59,12 +59,14 @@
|
|||||||
"color-convert": "2.0.1",
|
"color-convert": "2.0.1",
|
||||||
"content-disposition": "0.5.4",
|
"content-disposition": "0.5.4",
|
||||||
"date-fns": "2.30.0",
|
"date-fns": "2.30.0",
|
||||||
|
"decompress": "^4.2.1",
|
||||||
"deep-email-validator": "0.1.21",
|
"deep-email-validator": "0.1.21",
|
||||||
"escape-regexp": "0.0.1",
|
"escape-regexp": "0.0.1",
|
||||||
"feed": "4.2.2",
|
"feed": "4.2.2",
|
||||||
"file-type": "17.1.6",
|
"file-type": "17.1.6",
|
||||||
"fluent-ffmpeg": "2.1.2",
|
"fluent-ffmpeg": "2.1.2",
|
||||||
"got": "12.5.3",
|
"got": "12.5.3",
|
||||||
|
"gunzip-maybe": "^1.4.2",
|
||||||
"hpagent": "0.1.2",
|
"hpagent": "0.1.2",
|
||||||
"ioredis": "5.3.2",
|
"ioredis": "5.3.2",
|
||||||
"ip-cidr": "3.1.0",
|
"ip-cidr": "3.1.0",
|
||||||
@ -126,6 +128,7 @@
|
|||||||
"summaly": "2.7.0",
|
"summaly": "2.7.0",
|
||||||
"syslog-pro": "1.0.0",
|
"syslog-pro": "1.0.0",
|
||||||
"systeminformation": "5.17.17",
|
"systeminformation": "5.17.17",
|
||||||
|
"tar-stream": "^3.1.6",
|
||||||
"tesseract.js": "^3.0.3",
|
"tesseract.js": "^3.0.3",
|
||||||
"tinycolor2": "1.5.2",
|
"tinycolor2": "1.5.2",
|
||||||
"tmp": "0.2.1",
|
"tmp": "0.2.1",
|
||||||
|
@ -54,9 +54,9 @@ export default function load() {
|
|||||||
mixin.userAgent = `Calckey/${meta.version} (${config.url})`;
|
mixin.userAgent = `Calckey/${meta.version} (${config.url})`;
|
||||||
mixin.clientEntry = clientManifest["src/init.ts"];
|
mixin.clientEntry = clientManifest["src/init.ts"];
|
||||||
|
|
||||||
if (!config.redis.prefix) config.redis.prefix = mixin.host;
|
if (!config.redis.prefix) config.redis.prefix = mixin.hostname;
|
||||||
if (config.cacheServer && !config.cacheServer.prefix)
|
if (config.cacheServer && !config.cacheServer.prefix)
|
||||||
config.cacheServer.prefix = mixin.host;
|
config.cacheServer.prefix = mixin.hostname;
|
||||||
|
|
||||||
return Object.assign(config, mixin);
|
return Object.assign(config, mixin);
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,6 @@ import { AnnouncementRead } from "@/models/entities/announcement-read.js";
|
|||||||
import { Clip } from "@/models/entities/clip.js";
|
import { Clip } from "@/models/entities/clip.js";
|
||||||
import { ClipNote } from "@/models/entities/clip-note.js";
|
import { ClipNote } from "@/models/entities/clip-note.js";
|
||||||
import { Antenna } from "@/models/entities/antenna.js";
|
import { Antenna } from "@/models/entities/antenna.js";
|
||||||
import { AntennaNote } from "@/models/entities/antenna-note.js";
|
|
||||||
import { PromoNote } from "@/models/entities/promo-note.js";
|
import { PromoNote } from "@/models/entities/promo-note.js";
|
||||||
import { PromoRead } from "@/models/entities/promo-read.js";
|
import { PromoRead } from "@/models/entities/promo-read.js";
|
||||||
import { Relay } from "@/models/entities/relay.js";
|
import { Relay } from "@/models/entities/relay.js";
|
||||||
@ -168,7 +167,6 @@ export const entities = [
|
|||||||
Clip,
|
Clip,
|
||||||
ClipNote,
|
ClipNote,
|
||||||
Antenna,
|
Antenna,
|
||||||
AntennaNote,
|
|
||||||
PromoNote,
|
PromoNote,
|
||||||
PromoRead,
|
PromoRead,
|
||||||
Relay,
|
Relay,
|
||||||
|
@ -17,5 +17,5 @@ nativeInitIdGenerator(length, fingerprint);
|
|||||||
* Ref: https://github.com/paralleldrive/cuid2#parameterized-length
|
* Ref: https://github.com/paralleldrive/cuid2#parameterized-length
|
||||||
*/
|
*/
|
||||||
export function genId(date?: Date): string {
|
export function genId(date?: Date): string {
|
||||||
return nativeCreateId(BigInt((date ?? new Date()).getTime()));
|
return nativeCreateId((date ?? new Date()).getTime());
|
||||||
}
|
}
|
||||||
|
136
packages/backend/src/misc/process-masto-notes.ts
Normal file
136
packages/backend/src/misc/process-masto-notes.ts
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import * as fs from "node:fs";
|
||||||
|
import Logger from "@/services/logger.js";
|
||||||
|
import { createTemp, createTempDir } from "./create-temp.js";
|
||||||
|
import { downloadUrl } from "./download-url.js";
|
||||||
|
import { addFile } from "@/services/drive/add-file.js";
|
||||||
|
import { Users } from "@/models/index.js";
|
||||||
|
import * as tar from "tar-stream";
|
||||||
|
import gunzip from "gunzip-maybe";
|
||||||
|
import decompress from "decompress";
|
||||||
|
import * as Path from "node:path";
|
||||||
|
|
||||||
|
const logger = new Logger("process-masto-notes");
|
||||||
|
|
||||||
|
export async function processMastoNotes(
|
||||||
|
fn: string,
|
||||||
|
url: string,
|
||||||
|
uid: string,
|
||||||
|
): Promise<any> {
|
||||||
|
// Create temp file
|
||||||
|
const [path, cleanup] = await createTemp();
|
||||||
|
|
||||||
|
const [unzipPath, unzipCleanup] = await createTempDir();
|
||||||
|
|
||||||
|
logger.info(`Temp file is ${path}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// write content at URL to temp file
|
||||||
|
await downloadUrl(url, path);
|
||||||
|
return await processMastoFile(fn, path, unzipPath, uid);
|
||||||
|
} finally {
|
||||||
|
cleanup();
|
||||||
|
//unzipCleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function processMastoFile(fn: string, path: string, dir: string, uid: string) {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const user = await Users.findOneBy({ id: uid });
|
||||||
|
try {
|
||||||
|
logger.info(`Start unzip ${path}`);
|
||||||
|
fn.endsWith("tar.gz")
|
||||||
|
? await unzipTarGz(path, dir)
|
||||||
|
: await unzipZip(path, dir);
|
||||||
|
logger.info(`Unzip to ${dir}`);
|
||||||
|
const outbox = JSON.parse(fs.readFileSync(`${dir}/outbox.json`));
|
||||||
|
for (const note of outbox.orderedItems) {
|
||||||
|
for (const attachment of note.object.attachment) {
|
||||||
|
const url = attachment.url.replaceAll("..", "");
|
||||||
|
if (url.indexOf('\0') !== -1) {
|
||||||
|
logger.error(`Found Poison Null Bytes Attack: ${url}`);
|
||||||
|
reject();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const fpath = Path.resolve(`${dir}${url}`);
|
||||||
|
if (!fpath.startsWith(dir)) {
|
||||||
|
logger.error(`Found Path Attack: ${url}`);
|
||||||
|
reject();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.info(fpath);
|
||||||
|
const driveFile = await addFile({ user: user, path: fpath });
|
||||||
|
attachment.driveFile = driveFile;
|
||||||
|
} catch (e) {
|
||||||
|
logger.error(`Skipped adding file to drive: ${url}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(outbox);
|
||||||
|
} catch (e) {
|
||||||
|
logger.error(`Error on extract masto note package: ${fn}`);
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFileDir(fn: string) {
|
||||||
|
if (!fs.existsSync(fn)) {
|
||||||
|
fs.mkdirSync(fn, { recursive: true });
|
||||||
|
fs.rmdirSync(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unzipZip(fn: string, dir: string) {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
decompress(fn, dir).then((files: any) => {
|
||||||
|
resolve(files);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function unzipTarGz(fn: string, dir: string) {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const onErr = (err: any) => {
|
||||||
|
logger.error(`pipe broken: ${err}`);
|
||||||
|
reject();
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const extract = tar.extract().on("error", onErr);
|
||||||
|
dir = dir.endsWith("/") ? dir : dir + "/";
|
||||||
|
const ls: string[] = [];
|
||||||
|
extract.on("entry", function (header: any, stream: any, next: any) {
|
||||||
|
try {
|
||||||
|
ls.push(dir + header.name);
|
||||||
|
createFileDir(dir + header.name);
|
||||||
|
stream
|
||||||
|
.on("error", onErr)
|
||||||
|
.pipe(fs.createWriteStream(dir + header.name))
|
||||||
|
.on("error", onErr);
|
||||||
|
next();
|
||||||
|
} catch (e) {
|
||||||
|
logger.error(`create dir error:${e}`);
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
extract.on("finish", function () {
|
||||||
|
resolve(ls);
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.createReadStream(fn)
|
||||||
|
.on("error", onErr)
|
||||||
|
.pipe(gunzip())
|
||||||
|
.on("error", onErr)
|
||||||
|
.pipe(extract)
|
||||||
|
.on("error", onErr);
|
||||||
|
} catch (e) {
|
||||||
|
logger.error(`unzipTarGz error: ${e}`);
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -1,50 +0,0 @@
|
|||||||
import {
|
|
||||||
Entity,
|
|
||||||
Index,
|
|
||||||
JoinColumn,
|
|
||||||
Column,
|
|
||||||
ManyToOne,
|
|
||||||
PrimaryColumn,
|
|
||||||
} from "typeorm";
|
|
||||||
import { Note } from "./note.js";
|
|
||||||
import { Antenna } from "./antenna.js";
|
|
||||||
import { id } from "../id.js";
|
|
||||||
|
|
||||||
@Entity()
|
|
||||||
@Index(["noteId", "antennaId"], { unique: true })
|
|
||||||
export class AntennaNote {
|
|
||||||
@PrimaryColumn(id())
|
|
||||||
public id: string;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column({
|
|
||||||
...id(),
|
|
||||||
comment: "The note ID.",
|
|
||||||
})
|
|
||||||
public noteId: Note["id"];
|
|
||||||
|
|
||||||
@ManyToOne((type) => Note, {
|
|
||||||
onDelete: "CASCADE",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public note: Note | null;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column({
|
|
||||||
...id(),
|
|
||||||
comment: "The antenna ID.",
|
|
||||||
})
|
|
||||||
public antennaId: Antenna["id"];
|
|
||||||
|
|
||||||
@ManyToOne((type) => Antenna, {
|
|
||||||
onDelete: "CASCADE",
|
|
||||||
})
|
|
||||||
@JoinColumn()
|
|
||||||
public antenna: Antenna | null;
|
|
||||||
|
|
||||||
@Index()
|
|
||||||
@Column("boolean", {
|
|
||||||
default: false,
|
|
||||||
})
|
|
||||||
public read: boolean;
|
|
||||||
}
|
|
@ -51,7 +51,6 @@ import { UsedUsername } from "./entities/used-username.js";
|
|||||||
import { ClipRepository } from "./repositories/clip.js";
|
import { ClipRepository } from "./repositories/clip.js";
|
||||||
import { ClipNote } from "./entities/clip-note.js";
|
import { ClipNote } from "./entities/clip-note.js";
|
||||||
import { AntennaRepository } from "./repositories/antenna.js";
|
import { AntennaRepository } from "./repositories/antenna.js";
|
||||||
import { AntennaNote } from "./entities/antenna-note.js";
|
|
||||||
import { PromoNote } from "./entities/promo-note.js";
|
import { PromoNote } from "./entities/promo-note.js";
|
||||||
import { PromoRead } from "./entities/promo-read.js";
|
import { PromoRead } from "./entities/promo-read.js";
|
||||||
import { EmojiRepository } from "./repositories/emoji.js";
|
import { EmojiRepository } from "./repositories/emoji.js";
|
||||||
@ -123,7 +122,6 @@ export const ModerationLogs = ModerationLogRepository;
|
|||||||
export const Clips = ClipRepository;
|
export const Clips = ClipRepository;
|
||||||
export const ClipNotes = db.getRepository(ClipNote);
|
export const ClipNotes = db.getRepository(ClipNote);
|
||||||
export const Antennas = AntennaRepository;
|
export const Antennas = AntennaRepository;
|
||||||
export const AntennaNotes = db.getRepository(AntennaNote);
|
|
||||||
export const PromoNotes = db.getRepository(PromoNote);
|
export const PromoNotes = db.getRepository(PromoNote);
|
||||||
export const PromoReads = db.getRepository(PromoRead);
|
export const PromoReads = db.getRepository(PromoRead);
|
||||||
export const Relays = RelayRepository;
|
export const Relays = RelayRepository;
|
||||||
|
@ -18,7 +18,6 @@ import { createPerson } from "@/remote/activitypub/models/person.js";
|
|||||||
import {
|
import {
|
||||||
AnnouncementReads,
|
AnnouncementReads,
|
||||||
Announcements,
|
Announcements,
|
||||||
AntennaNotes,
|
|
||||||
Blockings,
|
Blockings,
|
||||||
ChannelFollowings,
|
ChannelFollowings,
|
||||||
DriveFiles,
|
DriveFiles,
|
||||||
@ -258,23 +257,24 @@ export const UserRepository = db.getRepository(User).extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
async getHasUnreadAntenna(userId: User["id"]): Promise<boolean> {
|
async getHasUnreadAntenna(userId: User["id"]): Promise<boolean> {
|
||||||
try {
|
// try {
|
||||||
const myAntennas = (await getAntennas()).filter(
|
// const myAntennas = (await getAntennas()).filter(
|
||||||
(a) => a.userId === userId,
|
// (a) => a.userId === userId,
|
||||||
);
|
// );
|
||||||
|
|
||||||
const unread =
|
// const unread =
|
||||||
myAntennas.length > 0
|
// myAntennas.length > 0
|
||||||
? await AntennaNotes.findOneBy({
|
// ? await AntennaNotes.findOneBy({
|
||||||
antennaId: In(myAntennas.map((x) => x.id)),
|
// antennaId: In(myAntennas.map((x) => x.id)),
|
||||||
read: false,
|
// read: false,
|
||||||
})
|
// })
|
||||||
: null;
|
// : null;
|
||||||
|
|
||||||
return unread != null;
|
// return unread != null;
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
return false; // TODO
|
||||||
},
|
},
|
||||||
|
|
||||||
async getHasUnreadChannel(userId: User["id"]): Promise<boolean> {
|
async getHasUnreadChannel(userId: User["id"]): Promise<boolean> {
|
||||||
|
@ -45,10 +45,16 @@ export async function importMastoPost(
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
job.progress(80);
|
job.progress(80);
|
||||||
|
|
||||||
|
let files: DriveFile[] = (post.object.attachment || [])
|
||||||
|
.map((x: any) => x?.driveFile)
|
||||||
|
.filter((x: any) => x);
|
||||||
|
|
||||||
|
if (files.length == 0) {
|
||||||
const urls = post.object.attachment
|
const urls = post.object.attachment
|
||||||
.map((x: any) => x.url)
|
.map((x: any) => x.url)
|
||||||
.filter((x: String) => x.startsWith("http"));
|
.filter((x: String) => x.startsWith("http"));
|
||||||
const files: DriveFile[] = [];
|
files = [];
|
||||||
for (const url of urls) {
|
for (const url of urls) {
|
||||||
try {
|
try {
|
||||||
const file = await uploadFromUrl({
|
const file = await uploadFromUrl({
|
||||||
@ -60,6 +66,7 @@ export async function importMastoPost(
|
|||||||
logger.error(`Skipped adding file to drive: ${url}`);
|
logger.error(`Skipped adding file to drive: ${url}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const note = await create(user, {
|
const note = await create(user, {
|
||||||
createdAt: new Date(post.object.published),
|
createdAt: new Date(post.object.published),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { downloadTextFile } from "@/misc/download-text-file.js";
|
import { downloadTextFile } from "@/misc/download-text-file.js";
|
||||||
|
import { processMastoNotes } from "@/misc/process-masto-notes.js";
|
||||||
import { Users, DriveFiles } from "@/models/index.js";
|
import { Users, DriveFiles } from "@/models/index.js";
|
||||||
import type { DbUserImportPostsJobData } from "@/queue/types.js";
|
import type { DbUserImportPostsJobData } from "@/queue/types.js";
|
||||||
import { queueLogger } from "../../logger.js";
|
import { queueLogger } from "../../logger.js";
|
||||||
@ -30,6 +31,26 @@ export async function importPosts(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file.name.endsWith("tar.gz") || file.name.endsWith("zip")) {
|
||||||
|
try {
|
||||||
|
logger.info("Reading Mastodon archive");
|
||||||
|
const outbox = await processMastoNotes(
|
||||||
|
file.name,
|
||||||
|
file.url,
|
||||||
|
job.data.user.id,
|
||||||
|
);
|
||||||
|
for (const post of outbox.orderedItems) {
|
||||||
|
createImportMastoPostJob(job.data.user, post, job.data.signatureCheck);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// handle error
|
||||||
|
logger.warn(`Failed reading Mastodon archive: ${e}`);
|
||||||
|
}
|
||||||
|
logger.succ("Mastodon archive imported");
|
||||||
|
done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const json = await downloadTextFile(file.url);
|
const json = await downloadTextFile(file.url);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -30,7 +30,7 @@ export const meta = {
|
|||||||
id: "c3a5a51e-04d4-11ee-be56-0242ac120002",
|
id: "c3a5a51e-04d4-11ee-be56-0242ac120002",
|
||||||
},
|
},
|
||||||
noKeywords: {
|
noKeywords: {
|
||||||
message: "No keywords",
|
message: "No keywords.",
|
||||||
code: "NO_KEYWORDS",
|
code: "NO_KEYWORDS",
|
||||||
id: "aa975b74-1ddb-11ee-be56-0242ac120002",
|
id: "aa975b74-1ddb-11ee-be56-0242ac120002",
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import { Antennas, AntennaNotes } from "@/models/index.js";
|
import { Antennas } from "@/models/index.js";
|
||||||
import { FindOptionsWhere } from "typeorm";
|
import { FindOptionsWhere } from "typeorm";
|
||||||
import { AntennaNote } from "@/models/entities/antenna-note.js";
|
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
tags: ["antennas", "account"],
|
tags: ["antennas", "account"],
|
||||||
@ -29,15 +28,15 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
await AntennaNotes.update(
|
// await AntennaNotes.update(
|
||||||
{
|
// {
|
||||||
antennaId: antenna.id,
|
// antennaId: antenna.id,
|
||||||
read: false,
|
// read: false,
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
read: true,
|
// read: true,
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import define from "../../define.js";
|
import define from "../../define.js";
|
||||||
import readNote from "@/services/note/read.js";
|
import readNote from "@/services/note/read.js";
|
||||||
import { Antennas, Notes, AntennaNotes } from "@/models/index.js";
|
import { Antennas, Notes } from "@/models/index.js";
|
||||||
|
import { redisClient } from "@/db/redis.js";
|
||||||
|
import { genId } from "@/misc/gen-id.js";
|
||||||
import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
import { makePaginationQuery } from "../../common/make-pagination-query.js";
|
||||||
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js";
|
import { generateVisibilityQuery } from "../../common/generate-visibility-query.js";
|
||||||
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js";
|
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js";
|
||||||
@ -58,6 +60,26 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||||||
throw new ApiError(meta.errors.noSuchAntenna);
|
throw new ApiError(meta.errors.noSuchAntenna);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const noteIdsRes = await redisClient.xrevrange(
|
||||||
|
`antennaTimeline:${antenna.id}`,
|
||||||
|
ps.untilDate || "+",
|
||||||
|
"-",
|
||||||
|
"COUNT",
|
||||||
|
ps.limit + 1,
|
||||||
|
); // untilIdに指定したものも含まれるため+1
|
||||||
|
|
||||||
|
if (noteIdsRes.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const noteIds = noteIdsRes
|
||||||
|
.map((x) => x[1][1])
|
||||||
|
.filter((x) => x !== ps.untilId);
|
||||||
|
|
||||||
|
if (noteIds.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const query = makePaginationQuery(
|
const query = makePaginationQuery(
|
||||||
Notes.createQueryBuilder("note"),
|
Notes.createQueryBuilder("note"),
|
||||||
ps.sinceId,
|
ps.sinceId,
|
||||||
@ -65,11 +87,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||||||
ps.sinceDate,
|
ps.sinceDate,
|
||||||
ps.untilDate,
|
ps.untilDate,
|
||||||
)
|
)
|
||||||
.innerJoin(
|
.where("note.id IN (:...noteIds)", { noteIds: noteIds })
|
||||||
AntennaNotes.metadata.targetName,
|
|
||||||
"antennaNote",
|
|
||||||
"antennaNote.noteId = note.id",
|
|
||||||
)
|
|
||||||
.innerJoinAndSelect("note.user", "user")
|
.innerJoinAndSelect("note.user", "user")
|
||||||
.leftJoinAndSelect("user.avatar", "avatar")
|
.leftJoinAndSelect("user.avatar", "avatar")
|
||||||
.leftJoinAndSelect("user.banner", "banner")
|
.leftJoinAndSelect("user.banner", "banner")
|
||||||
@ -81,7 +99,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||||||
.leftJoinAndSelect("renote.user", "renoteUser")
|
.leftJoinAndSelect("renote.user", "renoteUser")
|
||||||
.leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar")
|
.leftJoinAndSelect("renoteUser.avatar", "renoteUserAvatar")
|
||||||
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner")
|
.leftJoinAndSelect("renoteUser.banner", "renoteUserBanner")
|
||||||
.andWhere("antennaNote.antennaId = :antennaId", { antennaId: antenna.id })
|
|
||||||
.andWhere("note.visibility != 'home'");
|
.andWhere("note.visibility != 'home'");
|
||||||
|
|
||||||
generateVisibilityQuery(query, user);
|
generateVisibilityQuery(query, user);
|
||||||
|
@ -1,61 +1,24 @@
|
|||||||
import type { Antenna } from "@/models/entities/antenna.js";
|
import type { Antenna } from "@/models/entities/antenna.js";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type { Note } from "@/models/entities/note.js";
|
||||||
import { AntennaNotes, Mutings, Notes } from "@/models/index.js";
|
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import { genId } from "@/misc/gen-id.js";
|
||||||
import { isUserRelated } from "@/misc/is-user-related.js";
|
import { redisClient } from "@/db/redis.js";
|
||||||
import { publishAntennaStream, publishMainStream } from "@/services/stream.js";
|
import { publishAntennaStream } from "@/services/stream.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
|
|
||||||
export async function addNoteToAntenna(
|
export async function addNoteToAntenna(
|
||||||
antenna: Antenna,
|
antenna: Antenna,
|
||||||
note: Note,
|
note: Note,
|
||||||
noteUser: { id: User["id"] },
|
_noteUser: { id: User["id"] },
|
||||||
) {
|
) {
|
||||||
// 通知しない設定になっているか、自分自身の投稿なら既読にする
|
redisClient.xadd(
|
||||||
const read = !antenna.notify || antenna.userId === noteUser.id;
|
`antennaTimeline:${antenna.id}`,
|
||||||
|
"MAXLEN",
|
||||||
AntennaNotes.insert({
|
"~",
|
||||||
id: genId(),
|
"200",
|
||||||
antennaId: antenna.id,
|
"*",
|
||||||
noteId: note.id,
|
"note",
|
||||||
read: read,
|
note.id,
|
||||||
});
|
);
|
||||||
|
|
||||||
publishAntennaStream(antenna.id, "note", note);
|
publishAntennaStream(antenna.id, "note", note);
|
||||||
|
|
||||||
if (!read) {
|
|
||||||
const mutings = await Mutings.find({
|
|
||||||
where: {
|
|
||||||
muterId: antenna.userId,
|
|
||||||
},
|
|
||||||
select: ["muteeId"],
|
|
||||||
});
|
|
||||||
|
|
||||||
// Copy
|
|
||||||
const _note: Note = {
|
|
||||||
...note,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (note.replyId != null) {
|
|
||||||
_note.reply = await Notes.findOneByOrFail({ id: note.replyId });
|
|
||||||
}
|
|
||||||
if (note.renoteId != null) {
|
|
||||||
_note.renote = await Notes.findOneByOrFail({ id: note.renoteId });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isUserRelated(_note, new Set<string>(mutings.map((x) => x.muteeId)))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2秒経っても既読にならなかったら通知
|
|
||||||
setTimeout(async () => {
|
|
||||||
const unread = await AntennaNotes.findOneBy({
|
|
||||||
antennaId: antenna.id,
|
|
||||||
read: false,
|
|
||||||
});
|
|
||||||
if (unread) {
|
|
||||||
publishMainStream(antenna.userId, "unreadAntenna", antenna);
|
|
||||||
}
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ import type { Note } from "@/models/entities/note.js";
|
|||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
import {
|
import {
|
||||||
NoteUnreads,
|
NoteUnreads,
|
||||||
AntennaNotes,
|
|
||||||
Users,
|
Users,
|
||||||
Followings,
|
Followings,
|
||||||
ChannelFollowings,
|
ChannelFollowings,
|
||||||
@ -51,11 +50,11 @@ export default async function (
|
|||||||
).map((x) => x.followeeId),
|
).map((x) => x.followeeId),
|
||||||
);
|
);
|
||||||
|
|
||||||
const myAntennas = (await getAntennas()).filter((a) => a.userId === userId);
|
// const myAntennas = (await getAntennas()).filter((a) => a.userId === userId);
|
||||||
const readMentions: (Note | Packed<"Note">)[] = [];
|
const readMentions: (Note | Packed<"Note">)[] = [];
|
||||||
const readSpecifiedNotes: (Note | Packed<"Note">)[] = [];
|
const readSpecifiedNotes: (Note | Packed<"Note">)[] = [];
|
||||||
const readChannelNotes: (Note | Packed<"Note">)[] = [];
|
const readChannelNotes: (Note | Packed<"Note">)[] = [];
|
||||||
const readAntennaNotes: (Note | Packed<"Note">)[] = [];
|
// const readAntennaNotes: (Note | Packed<"Note">)[] = [];
|
||||||
|
|
||||||
for (const note of notes) {
|
for (const note of notes) {
|
||||||
if (note.mentions?.includes(userId)) {
|
if (note.mentions?.includes(userId)) {
|
||||||
@ -68,22 +67,22 @@ export default async function (
|
|||||||
readChannelNotes.push(note);
|
readChannelNotes.push(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note.user != null) {
|
// if (note.user != null) {
|
||||||
// たぶんnullになることは無いはずだけど一応
|
// // たぶんnullになることは無いはずだけど一応
|
||||||
for (const antenna of myAntennas) {
|
// for (const antenna of myAntennas) {
|
||||||
if (
|
// if (
|
||||||
await checkHitAntenna(
|
// await checkHitAntenna(
|
||||||
antenna,
|
// antenna,
|
||||||
note,
|
// note,
|
||||||
note.user,
|
// note.user,
|
||||||
undefined,
|
// undefined,
|
||||||
Array.from(following),
|
// Array.from(following),
|
||||||
)
|
// )
|
||||||
) {
|
// ) {
|
||||||
readAntennaNotes.push(note);
|
// readAntennaNotes.push(note);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -141,33 +140,33 @@ export default async function (
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readAntennaNotes.length > 0) {
|
// if (readAntennaNotes.length > 0) {
|
||||||
await AntennaNotes.update(
|
// await AntennaNotes.update(
|
||||||
{
|
// {
|
||||||
antennaId: In(myAntennas.map((a) => a.id)),
|
// antennaId: In(myAntennas.map((a) => a.id)),
|
||||||
noteId: In(readAntennaNotes.map((n) => n.id)),
|
// noteId: In(readAntennaNotes.map((n) => n.id)),
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
read: true,
|
// read: true,
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
|
|
||||||
// TODO: まとめてクエリしたい
|
// // TODO: まとめてクエリしたい
|
||||||
for (const antenna of myAntennas) {
|
// for (const antenna of myAntennas) {
|
||||||
const count = await AntennaNotes.countBy({
|
// const count = await AntennaNotes.countBy({
|
||||||
antennaId: antenna.id,
|
// antennaId: antenna.id,
|
||||||
read: false,
|
// read: false,
|
||||||
});
|
// });
|
||||||
|
|
||||||
if (count === 0) {
|
// if (count === 0) {
|
||||||
publishMainStream(userId, "readAntenna", antenna);
|
// publishMainStream(userId, "readAntenna", antenna);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
Users.getHasUnreadAntenna(userId).then((unread) => {
|
// Users.getHasUnreadAntenna(userId).then((unread) => {
|
||||||
if (!unread) {
|
// if (!unread) {
|
||||||
publishMainStream(userId, "readAllAntennas");
|
// publishMainStream(userId, "readAllAntennas");
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
@ -100,11 +100,11 @@ const headerActions = $computed(() =>
|
|||||||
text: i18n.ts.settings,
|
text: i18n.ts.settings,
|
||||||
handler: settings,
|
handler: settings,
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
icon: "ph-check ph-bold ph-lg",
|
// icon: "ph-check ph-bold ph-lg",
|
||||||
text: i18n.ts.markAllAsRead,
|
// text: i18n.ts.markAllAsRead,
|
||||||
handler: markRead,
|
// handler: markRead,
|
||||||
},
|
// },
|
||||||
]
|
]
|
||||||
: [],
|
: [],
|
||||||
);
|
);
|
||||||
|
@ -23,9 +23,7 @@
|
|||||||
></template>
|
></template>
|
||||||
<FormRadios v-model="importType" class="_formBlock">
|
<FormRadios v-model="importType" class="_formBlock">
|
||||||
<option value="calckey">Calckey/Misskey</option>
|
<option value="calckey">Calckey/Misskey</option>
|
||||||
<option value="mastodon">
|
<option value="mastodon">Mastodon/Akkoma/Pleroma</option>
|
||||||
Mastodon/Akkoma/Pleroma (only outbox.json)
|
|
||||||
</option>
|
|
||||||
<option :disabled="true" value="twitter">
|
<option :disabled="true" value="twitter">
|
||||||
Twitter (soon)
|
Twitter (soon)
|
||||||
</option>
|
</option>
|
||||||
|
@ -384,27 +384,6 @@ async function deleteProfile() {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: clip;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calckey_app {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: clip;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.menu-enter-active,
|
.menu-enter-active,
|
||||||
.menu-leave-active {
|
.menu-leave-active {
|
||||||
|
@ -410,27 +410,6 @@ const wallpaper = localStorage.getItem("wallpaper") != null;
|
|||||||
console.log(mainRouter.currentRoute.value.name);
|
console.log(mainRouter.currentRoute.value.name);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: clip;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calckey_app {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: clip;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.widgetsDrawer-enter-active,
|
.widgetsDrawer-enter-active,
|
||||||
.widgetsDrawer-leave-active {
|
.widgetsDrawer-leave-active {
|
||||||
|
238
pnpm-lock.yaml
238
pnpm-lock.yaml
@ -183,6 +183,9 @@ importers:
|
|||||||
date-fns:
|
date-fns:
|
||||||
specifier: 2.30.0
|
specifier: 2.30.0
|
||||||
version: 2.30.0
|
version: 2.30.0
|
||||||
|
decompress:
|
||||||
|
specifier: ^4.2.1
|
||||||
|
version: 4.2.1
|
||||||
deep-email-validator:
|
deep-email-validator:
|
||||||
specifier: 0.1.21
|
specifier: 0.1.21
|
||||||
version: 0.1.21
|
version: 0.1.21
|
||||||
@ -201,6 +204,9 @@ importers:
|
|||||||
got:
|
got:
|
||||||
specifier: 12.5.3
|
specifier: 12.5.3
|
||||||
version: 12.5.3
|
version: 12.5.3
|
||||||
|
gunzip-maybe:
|
||||||
|
specifier: ^1.4.2
|
||||||
|
version: 1.4.2
|
||||||
hpagent:
|
hpagent:
|
||||||
specifier: 0.1.2
|
specifier: 0.1.2
|
||||||
version: 0.1.2
|
version: 0.1.2
|
||||||
@ -384,6 +390,9 @@ importers:
|
|||||||
systeminformation:
|
systeminformation:
|
||||||
specifier: 5.17.17
|
specifier: 5.17.17
|
||||||
version: 5.17.17
|
version: 5.17.17
|
||||||
|
tar-stream:
|
||||||
|
specifier: ^3.1.6
|
||||||
|
version: 3.1.6
|
||||||
tesseract.js:
|
tesseract.js:
|
||||||
specifier: ^3.0.3
|
specifier: ^3.0.3
|
||||||
version: 3.0.3(eslint@8.44.0)
|
version: 3.0.3(eslint@8.44.0)
|
||||||
@ -5653,6 +5662,10 @@ packages:
|
|||||||
- debug
|
- debug
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/b4a@1.6.4:
|
||||||
|
resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/babel-eslint@10.1.0(eslint@8.44.0):
|
/babel-eslint@10.1.0(eslint@8.44.0):
|
||||||
resolution: {integrity: sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==}
|
resolution: {integrity: sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@ -5874,6 +5887,13 @@ packages:
|
|||||||
engines: {node: '>=0.8'}
|
engines: {node: '>=0.8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/bl@1.2.3:
|
||||||
|
resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==}
|
||||||
|
dependencies:
|
||||||
|
readable-stream: 2.3.8
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/bl@4.1.0:
|
/bl@4.1.0:
|
||||||
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
|
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -5959,6 +5979,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==}
|
resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/browserify-zlib@0.1.4:
|
||||||
|
resolution: {integrity: sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==}
|
||||||
|
dependencies:
|
||||||
|
pako: 0.2.9
|
||||||
|
dev: false
|
||||||
|
|
||||||
/browserslist@1.7.7:
|
/browserslist@1.7.7:
|
||||||
resolution: {integrity: sha512-qHJblDE2bXVRYzuDetv/wAeHOJyO97+9wxC1cdCtyzgNuSozOyRCiiLaCR1f71AN66lQdVVBipWm63V+a7bPOw==}
|
resolution: {integrity: sha512-qHJblDE2bXVRYzuDetv/wAeHOJyO97+9wxC1cdCtyzgNuSozOyRCiiLaCR1f71AN66lQdVVBipWm63V+a7bPOw==}
|
||||||
deprecated: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools.
|
deprecated: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools.
|
||||||
@ -5991,6 +6017,17 @@ packages:
|
|||||||
node-int64: 0.4.0
|
node-int64: 0.4.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/buffer-alloc-unsafe@1.1.0:
|
||||||
|
resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/buffer-alloc@1.2.0:
|
||||||
|
resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==}
|
||||||
|
dependencies:
|
||||||
|
buffer-alloc-unsafe: 1.1.0
|
||||||
|
buffer-fill: 1.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/buffer-crc32@0.2.13:
|
/buffer-crc32@0.2.13:
|
||||||
resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
|
resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
|
||||||
|
|
||||||
@ -6003,6 +6040,10 @@ packages:
|
|||||||
engines: {node: '>=0.4'}
|
engines: {node: '>=0.4'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/buffer-fill@1.0.0:
|
||||||
|
resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/buffer-from@1.1.2:
|
/buffer-from@1.1.2:
|
||||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
|
|
||||||
@ -7453,6 +7494,59 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mimic-response: 3.1.0
|
mimic-response: 3.1.0
|
||||||
|
|
||||||
|
/decompress-tar@4.1.1:
|
||||||
|
resolution: {integrity: sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
dependencies:
|
||||||
|
file-type: 5.2.0
|
||||||
|
is-stream: 1.1.0
|
||||||
|
tar-stream: 1.6.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/decompress-tarbz2@4.1.1:
|
||||||
|
resolution: {integrity: sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
dependencies:
|
||||||
|
decompress-tar: 4.1.1
|
||||||
|
file-type: 6.2.0
|
||||||
|
is-stream: 1.1.0
|
||||||
|
seek-bzip: 1.0.6
|
||||||
|
unbzip2-stream: 1.4.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/decompress-targz@4.1.1:
|
||||||
|
resolution: {integrity: sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
dependencies:
|
||||||
|
decompress-tar: 4.1.1
|
||||||
|
file-type: 5.2.0
|
||||||
|
is-stream: 1.1.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/decompress-unzip@4.0.1:
|
||||||
|
resolution: {integrity: sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
dependencies:
|
||||||
|
file-type: 3.9.0
|
||||||
|
get-stream: 2.3.1
|
||||||
|
pify: 2.3.0
|
||||||
|
yauzl: 2.10.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/decompress@4.2.1:
|
||||||
|
resolution: {integrity: sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
dependencies:
|
||||||
|
decompress-tar: 4.1.1
|
||||||
|
decompress-tarbz2: 4.1.1
|
||||||
|
decompress-targz: 4.1.1
|
||||||
|
decompress-unzip: 4.0.1
|
||||||
|
graceful-fs: 4.2.11
|
||||||
|
make-dir: 1.3.0
|
||||||
|
pify: 2.3.0
|
||||||
|
strip-dirs: 2.1.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/dedent@0.7.0:
|
/dedent@0.7.0:
|
||||||
resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==}
|
resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==}
|
||||||
dev: true
|
dev: true
|
||||||
@ -7737,7 +7831,6 @@ packages:
|
|||||||
inherits: 2.0.4
|
inherits: 2.0.4
|
||||||
readable-stream: 2.3.8
|
readable-stream: 2.3.8
|
||||||
stream-shift: 1.0.1
|
stream-shift: 1.0.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/each-props@1.3.2:
|
/each-props@1.3.2:
|
||||||
resolution: {integrity: sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==}
|
resolution: {integrity: sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==}
|
||||||
@ -8992,6 +9085,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
|
resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/fast-fifo@1.3.0:
|
||||||
|
resolution: {integrity: sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/fast-glob@3.3.0:
|
/fast-glob@3.3.0:
|
||||||
resolution: {integrity: sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==}
|
resolution: {integrity: sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==}
|
||||||
engines: {node: '>=8.6.0'}
|
engines: {node: '>=8.6.0'}
|
||||||
@ -9040,7 +9137,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
|
resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
pend: 1.2.0
|
pend: 1.2.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/feed@4.2.2:
|
/feed@4.2.2:
|
||||||
resolution: {integrity: sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==}
|
resolution: {integrity: sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==}
|
||||||
@ -9090,6 +9186,21 @@ packages:
|
|||||||
strtok3: 7.0.0
|
strtok3: 7.0.0
|
||||||
token-types: 5.0.1
|
token-types: 5.0.1
|
||||||
|
|
||||||
|
/file-type@3.9.0:
|
||||||
|
resolution: {integrity: sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/file-type@5.2.0:
|
||||||
|
resolution: {integrity: sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/file-type@6.2.0:
|
||||||
|
resolution: {integrity: sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/filelist@1.0.4:
|
/filelist@1.0.4:
|
||||||
resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
|
resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -9558,6 +9669,14 @@ packages:
|
|||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/get-stream@2.3.1:
|
||||||
|
resolution: {integrity: sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dependencies:
|
||||||
|
object-assign: 4.1.1
|
||||||
|
pinkie-promise: 2.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/get-stream@3.0.0:
|
/get-stream@3.0.0:
|
||||||
resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==}
|
resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@ -9933,6 +10052,18 @@ packages:
|
|||||||
glogg: 1.0.2
|
glogg: 1.0.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/gunzip-maybe@1.4.2:
|
||||||
|
resolution: {integrity: sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
browserify-zlib: 0.1.4
|
||||||
|
is-deflate: 1.0.0
|
||||||
|
is-gzip: 1.0.0
|
||||||
|
peek-stream: 1.1.3
|
||||||
|
pumpify: 1.5.1
|
||||||
|
through2: 2.0.5
|
||||||
|
dev: false
|
||||||
|
|
||||||
/hammerjs@2.0.8:
|
/hammerjs@2.0.8:
|
||||||
resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==}
|
resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==}
|
||||||
engines: {node: '>=0.8.0'}
|
engines: {node: '>=0.8.0'}
|
||||||
@ -10614,6 +10745,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==}
|
resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/is-deflate@1.0.0:
|
||||||
|
resolution: {integrity: sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/is-descriptor@0.1.6:
|
/is-descriptor@0.1.6:
|
||||||
resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==}
|
resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -10702,6 +10837,11 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-extglob: 2.1.1
|
is-extglob: 2.1.1
|
||||||
|
|
||||||
|
/is-gzip@1.0.0:
|
||||||
|
resolution: {integrity: sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/is-hexadecimal@1.0.4:
|
/is-hexadecimal@1.0.4:
|
||||||
resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==}
|
resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==}
|
||||||
dev: true
|
dev: true
|
||||||
@ -10730,6 +10870,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==}
|
resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/is-natural-number@4.0.1:
|
||||||
|
resolution: {integrity: sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/is-negated-glob@1.0.0:
|
/is-negated-glob@1.0.0:
|
||||||
resolution: {integrity: sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==}
|
resolution: {integrity: sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -10831,7 +10975,6 @@ packages:
|
|||||||
/is-stream@1.1.0:
|
/is-stream@1.1.0:
|
||||||
resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==}
|
resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/is-stream@2.0.1:
|
/is-stream@2.0.1:
|
||||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||||
@ -12947,6 +13090,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-3WjL8+ZDouZwKlyJBMp/4LeziLFXgleOdsYu87piGcMLqhBzCsy2QFdbtAwv757TFC/rtqd738fgJw1tFQCSgA==}
|
resolution: {integrity: sha512-3WjL8+ZDouZwKlyJBMp/4LeziLFXgleOdsYu87piGcMLqhBzCsy2QFdbtAwv757TFC/rtqd738fgJw1tFQCSgA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/make-dir@1.3.0:
|
||||||
|
resolution: {integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
dependencies:
|
||||||
|
pify: 3.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/make-dir@3.1.0:
|
/make-dir@3.1.0:
|
||||||
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
|
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@ -14123,6 +14273,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==}
|
resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/pako@0.2.9:
|
||||||
|
resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/paralint@1.2.1:
|
/paralint@1.2.1:
|
||||||
resolution: {integrity: sha512-HPGVDd5eUNYBhtftRypBHlUTMy5UAnHBzFO601oLEODZ0uvXUJge1y43GZQM2CnyOOUyDQlNMK/9vcjjAxbfcA==}
|
resolution: {integrity: sha512-HPGVDd5eUNYBhtftRypBHlUTMy5UAnHBzFO601oLEODZ0uvXUJge1y43GZQM2CnyOOUyDQlNMK/9vcjjAxbfcA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@ -14329,9 +14483,16 @@ packages:
|
|||||||
resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==}
|
resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==}
|
||||||
engines: {node: '>=14.16'}
|
engines: {node: '>=14.16'}
|
||||||
|
|
||||||
|
/peek-stream@1.1.3:
|
||||||
|
resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==}
|
||||||
|
dependencies:
|
||||||
|
buffer-from: 1.1.2
|
||||||
|
duplexify: 3.7.1
|
||||||
|
through2: 2.0.5
|
||||||
|
dev: false
|
||||||
|
|
||||||
/pend@1.2.0:
|
/pend@1.2.0:
|
||||||
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
|
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/performance-now@2.1.0:
|
/performance-now@2.1.0:
|
||||||
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
|
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
|
||||||
@ -14415,7 +14576,11 @@ packages:
|
|||||||
/pify@2.3.0:
|
/pify@2.3.0:
|
||||||
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
|
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
|
||||||
|
/pify@3.0.0:
|
||||||
|
resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/pify@4.0.1:
|
/pify@4.0.1:
|
||||||
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
|
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
|
||||||
@ -14426,12 +14591,10 @@ packages:
|
|||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
pinkie: 2.0.4
|
pinkie: 2.0.4
|
||||||
dev: true
|
|
||||||
|
|
||||||
/pinkie@2.0.4:
|
/pinkie@2.0.4:
|
||||||
resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==}
|
resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/pirates@4.0.6:
|
/pirates@4.0.6:
|
||||||
resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
|
resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
|
||||||
@ -15069,7 +15232,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
end-of-stream: 1.4.4
|
end-of-stream: 1.4.4
|
||||||
once: 1.4.0
|
once: 1.4.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/pump@3.0.0:
|
/pump@3.0.0:
|
||||||
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
|
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
|
||||||
@ -15083,7 +15245,6 @@ packages:
|
|||||||
duplexify: 3.7.1
|
duplexify: 3.7.1
|
||||||
inherits: 2.0.4
|
inherits: 2.0.4
|
||||||
pump: 2.0.1
|
pump: 2.0.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/punycode@1.3.2:
|
/punycode@1.3.2:
|
||||||
resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==}
|
resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==}
|
||||||
@ -15176,6 +15337,10 @@ packages:
|
|||||||
/queue-microtask@1.2.3:
|
/queue-microtask@1.2.3:
|
||||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||||
|
|
||||||
|
/queue-tick@1.0.1:
|
||||||
|
resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/quick-lru@4.0.1:
|
/quick-lru@4.0.1:
|
||||||
resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==}
|
resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@ -15852,6 +16017,13 @@ packages:
|
|||||||
/seedrandom@3.0.5:
|
/seedrandom@3.0.5:
|
||||||
resolution: {integrity: sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==}
|
resolution: {integrity: sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==}
|
||||||
|
|
||||||
|
/seek-bzip@1.0.6:
|
||||||
|
resolution: {integrity: sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
commander: 2.20.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/semver-greatest-satisfied-range@1.1.0:
|
/semver-greatest-satisfied-range@1.1.0:
|
||||||
resolution: {integrity: sha512-Ny/iyOzSSa8M5ML46IAx3iXc6tfOsYU2R4AXi2UpHk60Zrgyq6eqPj/xiOfS0rRl/iiQ/rdJkVjw/5cdUyCntQ==}
|
resolution: {integrity: sha512-Ny/iyOzSSa8M5ML46IAx3iXc6tfOsYU2R4AXi2UpHk60Zrgyq6eqPj/xiOfS0rRl/iiQ/rdJkVjw/5cdUyCntQ==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
@ -16352,13 +16524,19 @@ packages:
|
|||||||
|
|
||||||
/stream-shift@1.0.1:
|
/stream-shift@1.0.1:
|
||||||
resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==}
|
resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/streamsearch@1.1.0:
|
/streamsearch@1.1.0:
|
||||||
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/streamx@2.15.0:
|
||||||
|
resolution: {integrity: sha512-HcxY6ncGjjklGs1xsP1aR71INYcsXFJet5CU1CHqihQ2J5nOsbd4OjgjHO42w/4QNv9gZb3BueV+Vxok5pLEXg==}
|
||||||
|
dependencies:
|
||||||
|
fast-fifo: 1.3.0
|
||||||
|
queue-tick: 1.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/strict-event-emitter-types@2.0.0:
|
/strict-event-emitter-types@2.0.0:
|
||||||
resolution: {integrity: sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==}
|
resolution: {integrity: sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==}
|
||||||
dev: true
|
dev: true
|
||||||
@ -16486,6 +16664,12 @@ packages:
|
|||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/strip-dirs@2.1.0:
|
||||||
|
resolution: {integrity: sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==}
|
||||||
|
dependencies:
|
||||||
|
is-natural-number: 4.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/strip-eof@1.0.0:
|
/strip-eof@1.0.0:
|
||||||
resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==}
|
resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -16693,6 +16877,19 @@ packages:
|
|||||||
tar-stream: 2.2.0
|
tar-stream: 2.2.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/tar-stream@1.6.2:
|
||||||
|
resolution: {integrity: sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==}
|
||||||
|
engines: {node: '>= 0.8.0'}
|
||||||
|
dependencies:
|
||||||
|
bl: 1.2.3
|
||||||
|
buffer-alloc: 1.2.0
|
||||||
|
end-of-stream: 1.4.4
|
||||||
|
fs-constants: 1.0.0
|
||||||
|
readable-stream: 2.3.8
|
||||||
|
to-buffer: 1.1.1
|
||||||
|
xtend: 4.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tar-stream@2.2.0:
|
/tar-stream@2.2.0:
|
||||||
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
|
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@ -16704,6 +16901,14 @@ packages:
|
|||||||
readable-stream: 3.6.2
|
readable-stream: 3.6.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/tar-stream@3.1.6:
|
||||||
|
resolution: {integrity: sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==}
|
||||||
|
dependencies:
|
||||||
|
b4a: 1.6.4
|
||||||
|
fast-fifo: 1.3.0
|
||||||
|
streamx: 2.15.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tar@4.4.19:
|
/tar@4.4.19:
|
||||||
resolution: {integrity: sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==}
|
resolution: {integrity: sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==}
|
||||||
engines: {node: '>=4.5'}
|
engines: {node: '>=4.5'}
|
||||||
@ -16867,7 +17072,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
readable-stream: 2.3.8
|
readable-stream: 2.3.8
|
||||||
xtend: 4.0.2
|
xtend: 4.0.2
|
||||||
dev: true
|
|
||||||
|
|
||||||
/through2@4.0.2:
|
/through2@4.0.2:
|
||||||
resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==}
|
resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==}
|
||||||
@ -16918,6 +17122,10 @@ packages:
|
|||||||
is-negated-glob: 1.0.0
|
is-negated-glob: 1.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/to-buffer@1.1.1:
|
||||||
|
resolution: {integrity: sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/to-fast-properties@2.0.0:
|
/to-fast-properties@2.0.0:
|
||||||
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@ -17466,6 +17674,13 @@ packages:
|
|||||||
which-boxed-primitive: 1.0.2
|
which-boxed-primitive: 1.0.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/unbzip2-stream@1.4.3:
|
||||||
|
resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==}
|
||||||
|
dependencies:
|
||||||
|
buffer: 5.7.1
|
||||||
|
through: 2.3.8
|
||||||
|
dev: false
|
||||||
|
|
||||||
/unc-path-regex@0.1.2:
|
/unc-path-regex@0.1.2:
|
||||||
resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==}
|
resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -18528,7 +18743,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
buffer-crc32: 0.2.13
|
buffer-crc32: 0.2.13
|
||||||
fd-slicer: 1.1.0
|
fd-slicer: 1.1.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ylru@1.3.2:
|
/ylru@1.3.2:
|
||||||
resolution: {integrity: sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==}
|
resolution: {integrity: sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==}
|
||||||
|
Loading…
Reference in New Issue
Block a user