diff --git a/.config/example.yml b/.config/example.yml index 7d8ba32be..16fa67142 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -2,32 +2,31 @@ # Calckey configuration #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# After starting your server, please don't change the URL! Doing so will break federation. + # ┌─────┐ #───┘ URL └───────────────────────────────────────────────────── # Final accessible URL seen by a user. -url: https://example.tld/ - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# URL SETTINGS AFTER THAT! +url: https://example.com/ # ┌───────────────────────┐ #───┘ Port and TLS settings └─────────────────────────────────── # -# Misskey requires a reverse proxy to support HTTPS connections. +# Calckey requires a reverse proxy to support HTTPS connections. # -# +----- https://example.tld/ ------------+ +# +----- https://example.com/ ------------+ # +------+ |+-------------+ +----------------+| -# | User | ---> || Proxy (443) | ---> | Misskey (3000) || +# | User | ---> || Proxy (443) | ---> | Calckey (3000) || # +------+ |+-------------+ +----------------+| # +---------------------------------------+ # -# You need to set up a reverse proxy. (e.g. nginx) +# You need to set up a reverse proxy. (e.g. nginx, caddy) # An encrypted connection with HTTPS is highly recommended # because tokens may be transferred in GET requests. -# The port that your Misskey server should listen on. +# The port that your Calckey server should listen on. port: 3000 # ┌──────────────────────────┐ @@ -62,6 +61,17 @@ redis: #prefix: example-prefix #db: 1 +# Please configure either MeiliSearch *or* Sonic. +# If both MeiliSearch and Sonic configurations are present, MeiliSearch will take precedence. + +# ┌───────────────────────────┐ +#───┘ MeiliSearch configuration └───────────────────────────────────── +#meilisearch: +# host: meilisearch +# port: 7700 +# ssl: false +# apiKey: + # ┌─────────────────────┐ #───┘ Sonic configuration └───────────────────────────────────── @@ -72,41 +82,29 @@ redis: # collection: notes # bucket: default -# ┌─────────────────────────────┐ -#───┘ Elasticsearch configuration └───────────────────────────── - -#elasticsearch: -# host: localhost -# port: 9200 -# ssl: false -# user: -# pass: # ┌───────────────┐ #───┘ ID generation └─────────────────────────────────────────── -# You can select the ID generation method. -# You don't usually need to change this setting, but you can -# change it according to your preferences. +# No need to uncomment in most cases, but you may want to change +# these settings if you plan to run a large and/or distributed server. -# Available methods: -# aid ... Short, Millisecond accuracy -# meid ... Similar to ObjectID, Millisecond accuracy -# ulid ... Millisecond accuracy -# objectid ... This is left for backward compatibility +# cuid: +# # Min 16, Max 24 +# length: 16 +# +# # Set this to a unique string across workers (e.g., machine's hostname) +# # if your workers are running in multiple hosts. +# fingerprint: my-fingerprint -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# ID SETTINGS AFTER THAT! - -id: 'aid' # ┌─────────────────────┐ #───┘ Other configuration └───────────────────────────────────── -# Max note length, should be < 8000. +# Maximum length of a post (default 3000, max 8192) #maxNoteLength: 3000 -# Maximum lenght of an image caption or file comment (default 1500, max 8192) +# Maximum length of an image caption (default 1500, max 8192) #maxCaptionLength: 1500 # Reserved usernames that only the administrator can register with @@ -180,13 +178,21 @@ reservedUsernames: [ # Upload or download file size limits (bytes) #maxFileSize: 262144000 +#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# Congrats, you've reached the end of the config file needed for most deployments! +# Enjoy your Calckey server! +#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + + + +#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # Managed hosting settings -# !!!!!!!!!! -# >>>>>> NORMAL SELF-HOSTERS, STAY AWAY! <<<<<< -# >>>>>> YOU DON'T NEED THIS! <<<<<< -# !!!!!!!!!! +# >>> NORMAL SELF-HOSTERS, STAY AWAY! <<< +# >>> YOU DON'T NEED THIS! <<< # Each category is optional, but if each item in each category is mandatory! # If you mess this up, that's on you, you've been warned... +#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ #maxUserSignups: 100 #isManagedHosting: true diff --git a/.envrc b/.envrc index 0dcc9e739..3ce7171a3 100644 --- a/.envrc +++ b/.envrc @@ -1,4 +1,4 @@ -if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs=" +if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8=" fi use flake . --impure diff --git a/.node-version b/.node-version index 7fd023741..8ddbc0c64 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -v16.15.0 +v18.16.0 diff --git a/CALCKEY.md b/CALCKEY.md index 55d37a56e..d1585adc3 100644 --- a/CALCKEY.md +++ b/CALCKEY.md @@ -11,7 +11,7 @@ - Federate with note edits - User "choices" (recommended users) like Mastodon and Soapbox - Join Reason system like Mastodon/Pleroma - - Option to publicize instance blocks + - Option to publicize server blocks - Build flag to remove NSFW/AI stuff - Filter notifications by user - Exclude self from antenna @@ -19,7 +19,7 @@ - MFM button - Personal notes for all accounts - Fully revamp non-logged-in screen - - Lookup/details for post/file/instance + - Lookup/details for post/file/server - [Rat mode?](https://stop.voring.me/notes/933fx97bmd) ## Work in progress @@ -43,7 +43,7 @@ - Upgrade packages with security vunrabilities - Saner defaults - Fediverse account migration -- Recommended instances timeline +- Recommended servers timeline - OCR image captioning - Improve mobile UX - Swipe through pages on mobile @@ -71,7 +71,7 @@ - Better welcome screen (not logged in) - vue-plyr as video/audio player - Ability to turn off "Connection lost" message -- Raw instance info only for moderators +- Raw server info only for moderators - New spinner animation - Spinner instead of "Loading..." - SearchX instead of Google @@ -98,7 +98,7 @@ - Obliteration of Ai-chan - Switch to [Calckey.js](https://codeberg.org/calckey/calckey.js) - Woozy mode 🥴 -- Improve blocking instances +- Improve blocking servers - Release notes - New post style - Admins set default reaction emoji @@ -117,7 +117,7 @@ - Sonic search - Popular color schemes, including Nord, Gruvbox, and Catppuccin - Non-nyaify cat mode -- Post imports from other Calckey/Misskey/Mastodon/Pleroma/Akkoma instances +- Post imports from other Calckey/Misskey/Mastodon/Pleroma/Akkoma servers - Improve Classic mode - Proper Helm/Kubernetes config - Multiple boost visibilities diff --git a/Dockerfile b/Dockerfile index c378444f7..0aa13aefe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,7 @@ FROM node:19-alpine as build WORKDIR /calckey # Install compilation dependencies +RUN apk update RUN apk add --no-cache --no-progress git alpine-sdk python3 rust cargo vips # Copy only the dependency-related files first, to cache efficiently diff --git a/README.md b/README.md index a72a171bb..f4d7c4150 100644 --- a/README.md +++ b/README.md @@ -23,15 +23,15 @@ # ✨ About Calckey - Calckey is based off of Misskey, a powerful microblogging server on ActivityPub with features such as emoji reactions, a customizable web UI, rich chatting, and much more! -- Calckey adds many quality of life changes and bug fixes for users and instance admins alike. +- Calckey adds many quality of life changes and bug fixes for users and server admins alike. - Read **[this document](./CALCKEY.md)** all for current and future differences. - Notable differences: - Improved UI/UX (especially on mobile) - Improved notifications - - Improved instance security + - Improved server security - Improved accessibility - Improved threads - - Recommended Instances timeline + - Recommended Servers timeline - OCR image captioning - New and improved Groups - Better intro tutorial @@ -50,10 +50,10 @@ - 💸 OpenCollective: - 💸 Liberapay: - Donate publicly to get your name on the Patron list! -- 🚢 Flagship instance: +- 🚢 Flagship server: - 📣 Official account: - 💁 Matrix support room: -- 📜 Instance list: +- 📜 Server list: - 📖 JoinFediverse Wiki: - 🐋 Docker Hub: - ✍️ Weblate: @@ -76,10 +76,10 @@ If you have access to a server that supports one of the sources below, I recomme ## 🧑‍💻 Dependencies -- 🐢 At least [NodeJS](https://nodejs.org/en/) v18.12.1 (v19 recommended) +- 🐢 At least [NodeJS](https://nodejs.org/en/) v18.16.0 (v20 recommended) - Install with [nvm](https://github.com/nvm-sh/nvm) -- 🐘 At least [PostgreSQL](https://www.postgresql.org/) v12 -- 🍱 At least [Redis](https://redis.io/) v6 (v7 recommend) +- 🐘 At least [PostgreSQL](https://www.postgresql.org/) v12 (v14 recommended) +- 🍱 At least [Redis](https://redis.io/) v6 (v7 recommended) - Web Proxy (one of the following) - 🍀 Nginx (recommended) - 🦦 Caddy @@ -89,7 +89,8 @@ If you have access to a server that supports one of the sources below, I recomme - [FFmpeg](https://ffmpeg.org/) for video transcoding - Full text search (one of the following) - - 🦔 [Sonic](https://crates.io/crates/sonic-server) (recommended) + - 🦔 [Sonic](https://crates.io/crates/sonic-server) + - [MeiliSearch](https://www.meilisearch.com/) - [ElasticSearch](https://www.elastic.co/elasticsearch/) ### 🏗️ Build dependencies @@ -103,7 +104,7 @@ If you have access to a server that supports one of the sources below, I recomme ## 👀 Get folder ready ```sh -git clone --depth 1 https://codeberg.org/calckey/calckey.git +git clone https://codeberg.org/calckey/calckey.git cd calckey/ ``` @@ -148,7 +149,11 @@ psql postgres -c "create database calckey with encoding = 'UTF8';" In Calckey's directory, fill out the `db` section of `.config/default.yml` with the correct information, where the `db` key is `calckey`. -## 🦔 Set up search +## 🔎 Set up search + +### 🦔 Sonic + +Sonic is better suited for self hosters with smaller deployments. It's easier to use, uses almost no resources, and takes barely any any disk space. Follow sonic's [installation guide](https://github.com/valeriansaliou/sonic#installation) @@ -157,17 +162,28 @@ Follow sonic's [installation guide](https://github.com/valeriansaliou/sonic#inst In Calckey's directory, fill out the `sonic` section of `.config/default.yml` with the correct information. +### Meilisearch + +Meilisearch is better suited for larger deployments. It's faster but uses far more resources and disk space. + +Follow Meilisearch's [quick start guide](https://www.meilisearch.com/docs/learn/getting_started/quick_start) + +In Calckey's directory, fill out the `meilisearch` section of `.config/default.yml` with the correct information. + +### ElasticSearch + +Please don't use ElasticSearch unless you already have an ElasticSearch setup and want to continue using it for Calckey. ElasticSearch is slow, heavy, and offers very few benefits over Sonic/Meilisearch. ## 💅 Customize - To add custom CSS for all users, edit `./custom/assets/instance.css`. -- To add static assets (such as images for the splash screen), place them in the `./custom/assets/` directory. They'll then be available on `https://yourinstance.tld/static-assets/filename.ext`. +- To add static assets (such as images for the splash screen), place them in the `./custom/assets/` directory. They'll then be available on `https://yourserver.tld/static-assets/filename.ext`. - To add custom locales, place them in the `./custom/locales/` directory. If you name your custom locale the same as an existing locale, it will overwrite it. If you give it a unique name, it will be added to the list. Also make sure that the first part of the filename matches the locale you're basing it on. (Example: `en-FOO.yml`) - To add custom error images, place them in the `./custom/assets/badges` directory, replacing the files already there. - To add custom sounds, place only mp3 files in the `./custom/assets/sounds` directory. - To update custom assets without rebuilding, just run `pnpm run gulp`. -## 🧑‍🔬 Configuring a new instance +## 🧑‍🔬 Configuring a new server - Run `cp .config/example.yml .config/default.yml` - Edit `.config/default.yml`, making sure to fill out required fields. @@ -182,7 +198,7 @@ For migrating from Misskey v13, Misskey v12, and Foundkey, read [this document]( ### 🍀 Nginx (recommended) - Run `sudo cp ./calckey.nginx.conf /etc/nginx/sites-available/ && cd /etc/nginx/sites-available/` -- Edit `calckey.nginx.conf` to reflect your instance properly +- Edit `calckey.nginx.conf` to reflect your server properly - Run `sudo ln -s ./calckey.nginx.conf ../sites-enabled/calckey.nginx.conf` - Run `sudo nginx -t` to validate that the config is valid, then restart the NGINX service. @@ -202,7 +218,7 @@ example.tld { > Apache has some known problems with Calckey. Only use it if you have to. - Run `sudo cp ./calckey.apache.conf /etc/apache2/sites-available/ && cd /etc/apache2/sites-available/` -- Edit `calckey.apache.conf` to reflect your instance properly +- Edit `calckey.apache.conf` to reflect your server properly - Run `sudo a2ensite calckey.apache` to enable the site - Run `sudo service apache2 restart` to reload apache2 configuration ## 🚀 Build and launch! diff --git a/docker-compose.yml b/docker-compose.yml index 5de14d0c8..bf4e4fb8d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,7 @@ services: depends_on: - db - redis - - sonic + - meilisearch ports: - "3000:3000" networks: @@ -40,17 +40,33 @@ services: volumes: - ./db:/var/lib/postgresql/data - sonic: - restart: unless-stopped - image: docker.io/valeriansaliou/sonic:v1.4.0 - networks: - - calcnet - volumes: - - ./sonic:/var/lib/sonic/store - - ./sonic/config.cfg:/etc/sonic.cfg +### Only one of the below should be used. +### Meilisearch is better overall, but resource-intensive. Sonic is a very light full text search engine. + +# meilisearch: +# container_name: meilisearch +# image: getmeili/meilisearch:v1.1.1 +# environment: +# - MEILI_ENV=${MEILI_ENV:-development} +# ports: +# - "7700:7700" +# networks: +# - calcnet +# volumes: +# - ./meili_data:/meili_data +# restart: unless-stopped + +# sonic: +# restart: unless-stopped +# image: docker.io/valeriansaliou/sonic:v1.4.0 +# networks: +# - calcnet +# volumes: +# - ./sonic:/var/lib/sonic/store +# - ./sonic/config.cfg:/etc/sonic.cfg networks: calcnet: - # web: - # external: - # name: web + # web: + # external: + # name: web diff --git a/docs/development.md b/docs/development.md index 41d1b3469..6d6c0ea8d 100644 --- a/docs/development.md +++ b/docs/development.md @@ -7,8 +7,8 @@ Please note, however, that this environment will not work on Windows outside of ### Prerequisites -- Installed the [Nix Package Manager](https://nixos.org/download.html) -- Installed [direnv](https://direnv.net/docs/installation.html) and added its hook to your shell. +- Installed the [Nix Package Manager](https://nixos.org/download.html) (use the comman on their website) +- Installed [direnv](https://direnv.net/docs/installation.html) and added its hook to your shell. (package manager) Once the repo is cloned to your computer, follow these next few steps inside the Calckey folder: @@ -20,3 +20,89 @@ Once the repo is cloned to your computer, follow these next few steps inside the - You should now see the admin user creation screen! Note: When you want to restart a dev server, all you need to do is run `devenv up`, no other steps are necessary. + +# Possible Troubles with the dev enviroment +(this doesn't have to be done under normal conditions, this is for future reference) + +### direnv +If you have any trouble with `direnv allow` +Check that the contents of `.envrc` have the same version of nix-direnv that is specified here: +> nix-direnv under -> installation -> using direnv source url +> https://github.com/nix-community/nix-direnv#direnv-source_url + +there should be no errors during `direnv allow` + +### outdated nix packages +if `install-deps` or any subsequent command doesn't run due to versioning problems +`flake.nix` and `flake.lock` may be outdated + +delete `flake.lock`, or better, run `nix flake update --extra-experimental-features flakes --extra-experimental-features nix-command` +after that, run `direnv rebuild` + +if there are any errors, you might have to change `flake.nix` +(because the available options can change between versions - consider getting support in [the matrix channel](https://matrix.to/#/#calckey:matrix.fedibird.com)) + +### after changing a node version +in my case, i had to change the node version from 19, to 18 + +! before proceeding, make sure to delete all build artifacts! +remove `node_modules` and `built` folders, and maybe `.devenv` and `.direnv` as well +manually, or run `npm cache clean --force` and `pnpm cleanall` + +### Windows Subsystem for Linux +if `devenv up` terminates because of wrong folder permissions, + +create the file `/etc/wsl.conf` in your distro and add +```shell +[automount] +options = "metadata" +``` + +this allows `chmod` calls to actually have an effect. +the build scripts DO actually set the permissions, it just needs to work in wsl. + +### devenv up +devenv up may take a looong time. (some say this is fake news, maybe it was bad luck in my case) + +do not get spooked by this error: +``` +> calckey@14.0.0-dev32 start /mnt/.../calckey +> pnpm --filter backend run start + + +> backend@ start /mnt/.../calckey/packages/backend +> pnpm node ./built/index.js + +node:internal/modules/cjs/loader:1078 + throw err; + ^ + +Error: Cannot find module '/mnt/.../calckey/packages/backend/built/index.js' + at Module._resolveFilename (node:internal/modules/cjs/loader:1075:15) + at Module._load (node:internal/modules/cjs/loader:920:27) + at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) + at node:internal/main/run_main_module:23:47 { + code: 'MODULE_NOT_FOUND', + requireStack: [] +} + +Node.js v18.16.0 +undefined +/mnt/.../calckey/packages/backend: + ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  backend@ start: `pnpm node ./built/index.js` +Exit status 1 + ELIFECYCLE  Command failed with exit code 1. +``` + +the script is designed to constantly try to start the server, while the build is still running. +this just means that the build isn't finished yet. + +at some point you should see a banner that says "Calckey" in big letters - +then you're good to go and can run `migrate` (in another terminal)! + +if you don't see the banner, +and it's for some reason stuck on `Finished 'build' after 917 ms` for a view minutes, + +just leave devenv running and open another terminal in the folder +run `migrate` and then `pnpm --filter backend run start` by yourself +the server should start diff --git a/docs/docker.md b/docs/docker.md index 8c42ee54d..0c625a4b3 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -1,4 +1,4 @@ -# 🐳 Running a Calckey instance with Docker +# 🐳 Running a Calckey server with Docker ## Pre-built docker container [thatonecalculator/calckey](https://hub.docker.com/r/thatonecalculator/calckey) @@ -8,7 +8,7 @@ There is a `docker-compose.yml` in the root of the project that you can use to build the container from source - .config/docker.env (**db config settings**) -- .config/default.yml (**calckey instance settings**) +- .config/default.yml (**calckey server settings**) ## Configuring @@ -20,7 +20,7 @@ Rename the files: then edit them according to your environment. You can configure `docker.env` with anything you like, but you will have to pay attention to the `default.yml` file: -- `url` should be set to the URL you will be hosting the web interface for the instance at. +- `url` should be set to the URL you will be hosting the web interface for the server at. - `host`, `db`, `user`, `pass` will have to be configured in the `PostgreSQL configuration` section - `host` is the name of the postgres container (eg: *calckey_db_1*), and the others should match your `docker.env`. - `host`will need to be configured in the *Redis configuration* section - it is the name of the redis container (eg: *calckey_redis_1*) - `auth` will need to be configured in the *Sonic* section - cannot be the default `SecretPassword` @@ -36,7 +36,7 @@ Copy `docker-compose.yml` and the `config/` to a directory, then run the **docke NOTE: This will take some time to come fully online, even after download and extracting the container images, and it may emit some error messages before completing successfully. Specifically, the `db` container needs to initialize and so isn't available to the `web` container right away. Only once the `db` container comes online does the `web` container start building and initializing the calckey tables. -Once the instance is up you can use a web browser to access the web interface at `http://serverip:3000` (where `serverip` is the IP of the server you are running the calckey instance on). +Once the server is up you can use a web browser to access the web interface at `http://serverip:3000` (where `serverip` is the IP of the server you are running the calckey server on). ## Docker for development diff --git a/docs/kubernetes.md b/docs/kubernetes.md index 710d0dee0..5cb6e5d83 100644 --- a/docs/kubernetes.md +++ b/docs/kubernetes.md @@ -1,4 +1,4 @@ -# Running a Calckey instance with Kubernetes and Helm +# Running a Calckey server with Kubernetes and Helm This is a [Helm](https://helm.sh/) chart directory in the root of the project that you can use to deploy calckey to a Kubernetes cluster @@ -27,7 +27,7 @@ helm upgrade \ -f .config/helm_values.yml ``` -4. Watch your calckey instance spin up: +4. Watch your calckey server spin up: ```shell kubectl -n calckey get po -w ``` diff --git a/flake.lock b/flake.lock index c07493140..f1ff69041 100644 --- a/flake.lock +++ b/flake.lock @@ -8,11 +8,11 @@ "pre-commit-hooks": "pre-commit-hooks" }, "locked": { - "lastModified": 1682953188, - "narHash": "sha256-MFH6yK7QnEV6+T96Pt++lH8ozDn4YqzaOXAS6u5h3mM=", + "lastModified": 1685521914, + "narHash": "sha256-0fdFP5IASLwJ0PSXrErW8PZon9TVYmi8VRF8OtjGkV4=", "owner": "cachix", "repo": "devenv", - "rev": "c388b8c57116a71174d26b09c0c38b4b6b5bac3a", + "rev": "e206d8f2e3e8d6aa943656052f15bdfea8146b8d", "type": "github" }, "original": { @@ -29,11 +29,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1682922129, - "narHash": "sha256-qnhkfksuuSLbN5UJM+KSCMSRC13bXosr6Ed3NwerRno=", + "lastModified": 1685514167, + "narHash": "sha256-urRxF0ZGSNeZjM4kALNg3wTh7fBscbqQmS6S/HU7Wms=", "owner": "nix-community", "repo": "fenix", - "rev": "c1f90f80ba4d60bea60685dd4515fb22d53279cc", + "rev": "3abfea51663583186f687c49a157eab1639349ca", "type": "github" }, "original": { @@ -63,11 +63,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1680392223, - "narHash": "sha256-n3g7QFr85lDODKt250rkZj2IFS3i4/8HBU2yKHO3tqw=", + "lastModified": 1685457039, + "narHash": "sha256-bEFtQm+YyLxQjKQAaBHJyPN1z2wbhBnr2g1NJWSYjwM=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "dcc36e45d054d7bb554c9cdab69093debd91a0b5", + "rev": "80717d11615b6f42d1ad2e18ead51193fc15de69", "type": "github" }, "original": { @@ -155,11 +155,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1677534593, - "narHash": "sha256-PuZSAHeq4/9pP/uYH1FcagQ3nLm/DrDrvKi/xC9glvw=", + "lastModified": 1678875422, + "narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3ad64d9e2d5bf80c877286102355b1625891ae9a", + "rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459", "type": "github" }, "original": { @@ -172,11 +172,11 @@ "nixpkgs-lib": { "locked": { "dir": "lib", - "lastModified": 1680213900, - "narHash": "sha256-cIDr5WZIj3EkKyCgj/6j3HBH4Jj1W296z7HTcWj1aMA=", + "lastModified": 1682879489, + "narHash": "sha256-sASwo8gBt7JDnOOstnps90K1wxmVfyhsTPPNTGBPjjg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e3652e0735fbec227f342712f180f4f21f0594f2", + "rev": "da45bf6ec7bbcc5d1e14d3795c025199f28e0de0", "type": "github" }, "original": { @@ -205,11 +205,11 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1673800717, - "narHash": "sha256-SFHraUqLSu5cC6IxTprex/nTsI81ZQAtDvlBvGDWfnA=", + "lastModified": 1678872516, + "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2f9fd351ec37f5d479556cd48be4ca340da59b8f", + "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8", "type": "github" }, "original": { @@ -221,11 +221,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1682929865, - "narHash": "sha256-jxVrgnf5QNjO+XoxDxUWtN2G5xyJSGZ5SWDQFxMuHxc=", + "lastModified": 1685399834, + "narHash": "sha256-Lt7//5snriXSdJo5hlVcDkpERL1piiih0UXIz1RUcC4=", "owner": "nixos", "repo": "nixpkgs", - "rev": "f2e9a130461950270f87630b11132323706b4d91", + "rev": "58c85835512b0db938600b6fe13cc3e3dc4b364e", "type": "github" }, "original": { @@ -250,11 +250,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1677160285, - "narHash": "sha256-tBzpCjMP+P3Y3nKLYvdBkXBg3KvTMo3gvi8tLQaqXVY=", + "lastModified": 1682596858, + "narHash": "sha256-Hf9XVpqaGqe/4oDGr30W8HlsWvJXtMsEPHDqHZA6dDg=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "2bd861ab81469428d9c823ef72c4bb08372dd2c4", + "rev": "fb58866e20af98779017134319b5663b8215d912", "type": "github" }, "original": { @@ -274,11 +274,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1682886915, - "narHash": "sha256-FPQKPvlHIU2DsDF6GMoRtrZhil0vHi6MFd8vpKEx/n8=", + "lastModified": 1685465261, + "narHash": "sha256-aJ2nUinUrNcFi+pb47bS5IIAeSiUEEPLJY8W4Q8Pcjk=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "3a27518fee5a723005299cf49e2d58a842a261ca", + "rev": "d2b3caa5b5694125fad04a9699e919444439f6a2", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 73d8fe02f..8553456ea 100644 --- a/flake.nix +++ b/flake.nix @@ -41,7 +41,7 @@ languages.typescript.enable = true; # Enable javascript for NPM and PNPM languages.javascript.enable = true; - languages.javascript.package = pkgs.nodejs_19; + languages.javascript.package = pkgs.nodejs_18; # Enable stable Rust for the backend languages.rust.enable = true; languages.rust.version = "stable"; diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml index 148cd32a0..3ce83ebcc 100644 --- a/locales/ar-SA.yml +++ b/locales/ar-SA.yml @@ -176,7 +176,6 @@ operations: "الإجراءات" software: "البرمجية" version: "الإصدار" metadata: "البيانات الوصفية" -withNFiles: "{n} ملف (ملفات)" monitor: "شاشة التحكم" jobQueue: "قائمة الانتظار" cpuAndMemory: "وحدة المعالجة المركزية والذاكرة" diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml index cde425d7f..f08e4bfc2 100644 --- a/locales/bn-BD.yml +++ b/locales/bn-BD.yml @@ -177,7 +177,6 @@ operations: "ক্রিয়াকলাপ" software: "সফটওয়্যার" version: "সংস্করণ" metadata: "মেটাডাটা" -withNFiles: "{n} টি ফাইল" monitor: "মনিটর" jobQueue: "জব কিউ" cpuAndMemory: "সিপিউ এবং মেমরি" diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index f64f70583..857caac1f 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -791,7 +791,6 @@ selectUser: Selecciona un usuari latestStatus: Últim estat storageUsage: Ús del emmagatzematge metadata: Metadades -withNFiles: '{n} fitxer(s)' monitor: Seguiment software: Programari version: Versió @@ -1802,8 +1801,8 @@ pushNotificationNotSupported: El vostre navegador o servidor no admet notificaci push license: Llicència indexPosts: Índex de notes -indexFrom: Índex a partir de l'ID de Publicacions (deixeu en blanc per indexar cada - publicació) +indexFrom: Índex a partir de l'ID de Publicacions +indexFromDescription: Deixeu en blanc per indexar cada publicació indexNotice: Ara indexant. Això probablement trigarà una estona, si us plau, no reinicieu el servidor durant almenys una hora. _instanceTicker: diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml index 1d12e69ab..8b502762f 100644 --- a/locales/cs-CZ.yml +++ b/locales/cs-CZ.yml @@ -189,7 +189,6 @@ operations: "Operace" software: "Software" version: "Verze" metadata: "Metadata" -withNFiles: "{n} soubor(ů)" monitor: "Monitorovat" jobQueue: "Fronta úloh" cpuAndMemory: "CPU a paměť" diff --git a/locales/da-DK.yml b/locales/da-DK.yml index c6d339a2e..878273c65 100644 --- a/locales/da-DK.yml +++ b/locales/da-DK.yml @@ -117,7 +117,6 @@ operations: Operationer software: Software metadata: Metadata version: Version -withNFiles: '{n} fil(er)' monitor: Vagt jobQueue: Jobkø statistics: Statistik diff --git a/locales/de-DE.yml b/locales/de-DE.yml index 2a039af4c..45edbe045 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -200,7 +200,6 @@ operations: "Tätigkeiten" software: "Software" version: "Version" metadata: "Metadaten" -withNFiles: "{n} Datei(en)" monitor: "Überwachung" jobQueue: "Auftragswarteschlange" cpuAndMemory: "CPU und Speicher" diff --git a/locales/el-GR.yml b/locales/el-GR.yml index 57270f7aa..d444882b4 100644 --- a/locales/el-GR.yml +++ b/locales/el-GR.yml @@ -435,7 +435,6 @@ nothing: Δεν υπάρχει τίποτα να δείτε εδώ newNoteRecived: Υπάρχουν νέες δημοσιεύσεις passwordMatched: Ταιριάζει unmarkAsSensitive: Αναίρεση επισήμανσης ως Ευαίσθητο Περιεχόμενο (NSFW) -withNFiles: '{n} αρχείο(-α)' blockedUsers: Μπλοκαρισμένα μέλη noteDeleteConfirm: Θέλετε σίγουρα να διαγράψετε αυτή τη δημοσίευση; preview: Προεπισκόπηση diff --git a/locales/en-US.yml b/locales/en-US.yml index 84e68ea6b..127b2d0fe 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -5,6 +5,7 @@ introMisskey: "Welcome! Calckey is an open source, decentralized social media pl \ that's free forever! \U0001F680" monthAndDay: "{month}/{day}" search: "Search" +searchPlaceholder: "Search Calckey" notifications: "Notifications" username: "Username" password: "Password" @@ -82,6 +83,7 @@ exportRequested: "You've requested an export. This may take a while. It will be \ to your Drive once completed." importRequested: "You've requested an import. This may take a while." lists: "Lists" +listsDesc: "Lists let you create timelines with specified users. They can be accessed from the timelines page." noLists: "You don't have any lists" note: "Post" notes: "Posts" @@ -209,7 +211,6 @@ operations: "Operations" software: "Software" version: "Version" metadata: "Metadata" -withNFiles: "{n} file(s)" monitor: "Monitor" jobQueue: "Job Queue" cpuAndMemory: "CPU and Memory" @@ -404,6 +405,7 @@ avoidMultiCaptchaConfirm: "Using multiple Captcha systems may cause interference \ them. Would you like to disable the other Captcha systems currently active? If\ \ you would like them to stay enabled, press cancel." antennas: "Antennas" +antennasDesc: "Antennas display new posts matching the criteria you set!\n They can be accessed from the timelines page." manageAntennas: "Manage Antennas" name: "Name" antennaSource: "Antenna source" @@ -595,6 +597,8 @@ scratchpadDescription: "The scratchpad provides an environment for AiScript expe output: "Output" script: "Script" disablePagesScript: "Disable AiScript on Pages" +expandOnNoteClick: "Open post on click" +expandOnNoteClickDesc: "If disabled, you can still open posts in the right-click menu or by clicking the timestamp." updateRemoteUser: "Update remote user information" deleteAllFiles: "Delete all files" deleteAllFilesConfirm: "Are you sure that you want to delete all files?" @@ -685,6 +689,7 @@ logs: "Logs" delayed: "Delayed" database: "Database" channel: "Channels" +channelFederationWarn: "Channels do not yet federate to other servers" create: "Create" notificationSetting: "Notification settings" notificationSettingDesc: "Select the types of notification to display." @@ -770,6 +775,7 @@ pageLikedCount: "Number of received Page likes" contact: "Contact" useSystemFont: "Use the system's default font" clips: "Clips" +clipsDesc: "Clips are like share-able categorized bookmarks. You can create clips from the menu of individual posts." experimentalFeatures: "Experimental features" developer: "Developer" makeExplorable: "Make account visible in \"Explore\"" @@ -1064,7 +1070,8 @@ migrationConfirm: "Are you absolutely sure you want to migrate your account to { defaultReaction: "Default emoji reaction for outgoing and incoming posts" license: "License" indexPosts: "Index Posts" -indexFrom: "Index from Post ID onwards (leave blank to index every post)" +indexFrom: "Index from Post ID onwards" +indexFromDescription: "Leave blank to index every post" indexNotice: "Now indexing. This will probably take a while, please don't restart\ \ your server for at least an hour." customKaTeXMacro: "Custom KaTeX macros" @@ -1445,7 +1452,7 @@ _tutorial: \ you follow." step5_4: "The Local {icon} timeline is where you can see posts from everyone else on this server." step5_5: "The Social {icon} timeline is a combination of the Home and Local timelines." - step5_6: "The Recommended {icon} timeline is where you can see posts from server\ + step5_6: "The Recommended {icon} timeline is where you can see posts from servers\ \ the admins recommend." step5_7: "The Global {icon} timeline is where you can see posts from every other\ \ connected server." @@ -1526,30 +1533,35 @@ _weekday: friday: "Friday" saturday: "Saturday" _widgets: - memo: "Sticky notes" + memo: "Sticky Notes" notifications: "Notifications" timeline: "Timeline" calendar: "Calendar" trends: "Trending" clock: "Clock" - rss: "RSS reader" - rssTicker: "RSS-Ticker" + rss: "RSS Reader" + rssTicker: "RSS Ticker" activity: "Activity" photos: "Photos" - digitalClock: "Digital clock" - unixClock: "UNIX clock" + digitalClock: "Digital Clock" + unixClock: "UNIX Clock" federation: "Federation" - instanceCloud: "Server cloud" - postForm: "Posting form" + instanceCloud: "Server Cloud" + postForm: "Posting Form" slideshow: "Slideshow" button: "Button" - onlineUsers: "Online users" + onlineUsers: "Online Users" jobQueue: "Job Queue" - serverMetric: "Server metrics" - aiscript: "AiScript console" - userList: "User list" + serverMetric: "Server Metrics" + aiscript: "AiScript Console" + userList: "User List" + serverInfo: "Server Info" _userList: chooseList: "Select a list" + meiliStatus: "Server Status" + meiliSize: "Index size" + meiliIndexCount: "Indexed posts" + _cw: hide: "Hide" show: "Show content" @@ -2020,6 +2032,6 @@ _experiments: postEditingCaption: "Shows the option for users to edit their existing posts via\ \ the post options menu." enablePostImports: "Enable post imports" - postImportsDescription: "Allows users to import their posts from past Calckey,\ + postImportsCaption: "Allows users to import their posts from past Calckey,\ \ Misskey, Mastodon, Akkoma, and Pleroma accounts. It may cause slowdowns during\ \ load if your queue is bottlenecked." diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 49f51bff6..2dc40f359 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -195,7 +195,6 @@ operations: "Operaciones" software: "Software" version: "Versión" metadata: "Metadatos" -withNFiles: "{n} archivos" monitor: "Monitor" jobQueue: "Cola de trabajos" cpuAndMemory: "CPU y Memoria" diff --git a/locales/fi.yml b/locales/fi.yml index ec7438096..aa9699cca 100644 --- a/locales/fi.yml +++ b/locales/fi.yml @@ -182,7 +182,6 @@ followsYou: Seuraa sinua pageLoadErrorDescription: Tämä yleensä johtuu verkkovirheistä tai selaimen välimuistista. Kokeile tyhjentämällä välimuisti ja yritä sitten hetken kuluttua uudelleen. enterListName: Anna listalle nimi -withNFiles: '{n} tiedosto(t)' instanceInfo: Instanssin tiedot clearQueue: Tyhjennä jono suspendConfirm: Oletko varma, että haluat keskeyttää tämän tilin? diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index e7416f577..dad095688 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -201,7 +201,6 @@ operations: "Opérations" software: "Logiciel" version: "Version" metadata: "Métadonnées" -withNFiles: "{n} fichier(s)" monitor: "Contrôle" jobQueue: "File d’attente" cpuAndMemory: "Processeur et mémoire" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index 4caca4439..f9859c2c7 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -197,7 +197,6 @@ operations: "Tindakan" software: "Perangkat lunak" version: "Versi" metadata: "Metadata" -withNFiles: "{n} berkas" monitor: "Pantau" jobQueue: "Antrian kerja" cpuAndMemory: "CPU dan Memori" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 6dc4b68b5..ed3632ec6 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -175,7 +175,6 @@ operations: "Operazioni" software: "Software" version: "Versione" metadata: "Metadato" -withNFiles: "{n} file in allegato" monitor: "Monitorare" jobQueue: "Coda di lavoro" cpuAndMemory: "CPU e Memoria" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 84c894c7a..1bbc38c49 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -188,7 +188,6 @@ operations: "操作" software: "ソフトウェア" version: "バージョン" metadata: "メタデータ" -withNFiles: "{n}つのファイル" monitor: "モニター" jobQueue: "ジョブキュー" cpuAndMemory: "CPUとメモリ" @@ -966,7 +965,8 @@ migrationConfirm: "本当にこのアカウントを {account} に引っ越し defaultReaction: "リモートとローカルの投稿に対するデフォルトの絵文字リアクション" license: "ライセンス" indexPosts: "投稿をインデックス" -indexFrom: "この投稿ID以降をインデックスする(空白で全ての投稿を指定します)" +indexFrom: "この投稿ID以降をインデックスする" +indexFromDescription: "空白で全ての投稿を指定します" indexNotice: "インデックスを開始しました。完了まで時間がかかる場合があるため、少なくとも1時間はサーバーを再起動しないでください。" customKaTeXMacro: "カスタムKaTeXマクロ" customKaTeXMacroDescription: "数式入力を楽にするためのマクロを設定しましょう!記法はLaTeXにおけるコマンドの定義と同様に \\newcommand{\\\ diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index d5c48276f..8a9b91486 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -177,7 +177,6 @@ operations: "操作" software: "ソフトウェア" version: "バージョン" metadata: "メタデータ" -withNFiles: "{n}個のファイル" monitor: "モニター" jobQueue: "ジョブキュー" cpuAndMemory: "CPUとメモリ" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 15e776faf..7143cf2f9 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -177,7 +177,6 @@ operations: "작업" software: "소프트웨어" version: "버전" metadata: "메타데이터" -withNFiles: "{n}개의 파일" monitor: "모니터" jobQueue: "작업 대기열" cpuAndMemory: "CPU와 메모리" diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml index 49b737e91..115c003e3 100644 --- a/locales/nl-NL.yml +++ b/locales/nl-NL.yml @@ -179,7 +179,6 @@ operations: "Verwerkingen" software: "Software" version: "Versie" metadata: "Metadata" -withNFiles: "{n} bestand(en)" monitor: "Monitor" jobQueue: "Job Queue" cpuAndMemory: "CPU en geheugen" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index c127c5a52..a1b0f0c15 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -187,7 +187,6 @@ operations: "Działania" software: "Oprogramowanie" version: "Wersja" metadata: "Metadane" -withNFiles: "{n} plik(i/ów)" monitor: "Monitor" jobQueue: "Kolejka zadań" cpuAndMemory: "CPU i pamięć" @@ -1898,7 +1897,8 @@ sendPushNotificationReadMessageCaption: Powiadomienie zawierające tekst "{empty defaultReaction: Domyślna reakcja emoji dla wychodzących i przychodzących wpisów license: Licencja indexPosts: Indeksuj wpisy -indexFrom: Indeksuj wpisy od ID (zostaw puste dla indeksowania wszystkich wpisów) +indexFrom: Indeksuj wpisy od ID +indexFromDescription: Zostaw puste dla indeksowania wszystkich wpisów indexNotice: Indeksuję. Zapewne zajmie to chwilę, nie restartuj serwera przez co najmniej godzinę. customKaTeXMacro: Niestandardowe makra KaTeX diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml index 2803df928..3e15beebb 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -177,7 +177,6 @@ operations: "operar" software: "Programas" version: "versão" metadata: "Metadados" -withNFiles: "{n} Um arquivo" monitor: "monitor" jobQueue: "Fila de trabalhos" cpuAndMemory: "CPU e memória" diff --git a/locales/ro-RO.yml b/locales/ro-RO.yml index 92a35ffa8..ba51950e3 100644 --- a/locales/ro-RO.yml +++ b/locales/ro-RO.yml @@ -177,7 +177,6 @@ operations: "Operațiuni" software: "Software" version: "Versiune" metadata: "Metadata" -withNFiles: "{n} fișier(e)" monitor: "Monitor" jobQueue: "coada de job-uri" cpuAndMemory: "CPU și memorie" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index 4d94ab287..01b21b0fc 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -192,7 +192,6 @@ operations: "Операции" software: "Программы" version: "Версия" metadata: "Метаданные" -withNFiles: "Файлы, {n} шт" monitor: "Монитор" jobQueue: "Очередь заданий" cpuAndMemory: "Процессор и память" @@ -1909,8 +1908,8 @@ recommendedInstances: Рекомендованные инстансы defaultReaction: Эмодзи реакция по умолчанию для выходящих и исходящих постов license: Лицензия indexPosts: Индексировать посты -indexFrom: Индексировать начиная с идентификатора поста и далее (оставьте пустым для - индексации каждого поста) +indexFrom: Индексировать начиная с идентификатора поста и далее +indexFromDescription: оставьте пустым для индексации каждого поста indexNotice: Теперь индексирование. Вероятно, это займет некоторое время, пожалуйста, не перезагружайте свой сервер по крайней мере в течение часа. customKaTeXMacro: Кастомные KaTex макросы diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml index a36caf1fd..462f34ed2 100644 --- a/locales/sk-SK.yml +++ b/locales/sk-SK.yml @@ -177,7 +177,6 @@ operations: "Operácie" software: "Softvér" version: "Verzia" metadata: "Metadáta" -withNFiles: "{n} súbor(ov)" monitor: "Monitor" jobQueue: "Fronta úloh" cpuAndMemory: "CPU a pamäť" diff --git a/locales/sv-SE.yml b/locales/sv-SE.yml index 993af2a23..6523ce068 100644 --- a/locales/sv-SE.yml +++ b/locales/sv-SE.yml @@ -176,7 +176,6 @@ operations: "Operationer" software: "Mjukvara" version: "Version" metadata: "Metadata" -withNFiles: "{n} fil(er)" monitor: "Övervakning" jobQueue: "Jobbkö" cpuAndMemory: "CPU och minne" diff --git a/locales/th-TH.yml b/locales/th-TH.yml index b6d81d8f5..9666737ee 100644 --- a/locales/th-TH.yml +++ b/locales/th-TH.yml @@ -177,7 +177,6 @@ operations: "ดำเนินการ" software: "ซอฟต์แวร์" version: "เวอร์ชั่น" metadata: "ข้อมูลเมตา" -withNFiles: "{n} ไฟล์(s)" monitor: "มอนิเตอร์" jobQueue: "คิวงาน" cpuAndMemory: "ซีพียู และ หน่วยความจำ" diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index 0368a0897..549dce666 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -177,7 +177,6 @@ operations: "Операції" software: "Програмне забезпечення" version: "Версія" metadata: "Метадані" -withNFiles: "файли: {n}" monitor: "Монітор" jobQueue: "Черга завдань" cpuAndMemory: "ЦП та пам'ять" diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index 7662af409..4b254fe94 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -177,7 +177,6 @@ operations: "Vận hành" software: "Phần mềm" version: "Phiên bản" metadata: "Metadata" -withNFiles: "{n} tập tin" monitor: "Giám sát" jobQueue: "Công việc chờ xử lý" cpuAndMemory: "CPU và Dung lượng" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 8ca19e596..5359cb6ef 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -181,7 +181,6 @@ operations: "操作" software: "软件" version: "版本" metadata: "元数据" -withNFiles: "{n}个文件" monitor: "服务器状态" jobQueue: "作业队列" cpuAndMemory: "CPU和内存" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index fd5117f48..61b5afbe6 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -180,7 +180,6 @@ operations: "操作" software: "軟體" version: "版本" metadata: "元資料" -withNFiles: "{n}個檔案" monitor: "監視器" jobQueue: "佇列" cpuAndMemory: "CPU及記憶體用量" diff --git a/package.json b/package.json index 2899adf7e..6b6531fc6 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "calckey", - "version": "14.0.0-dev26", + "version": "14.0.0-dev40", "codename": "aqua", "repository": { "type": "git", "url": "https://codeberg.org/calckey/calckey.git" }, - "packageManager": "pnpm@8.5.1", + "packageManager": "pnpm@8.6.0", "private": true, "scripts": { "rebuild": "pnpm run clean && pnpm -r run build && pnpm run gulp", @@ -27,7 +27,7 @@ "e2e": "start-server-and-test start:test http://localhost:61812 cy:run", "mocha": "pnpm --filter backend run mocha", "test": "pnpm run mocha", - "format": "pnpm rome format packages/**/* --write && pnpm --filter client run format", + "format": "pnpm rome format packages/**/* --write && pnpm -r run format", "clean": "pnpm node ./scripts/clean.js", "clean-all": "pnpm node ./scripts/clean-all.js", "cleanall": "pnpm run clean-all" @@ -36,9 +36,9 @@ "chokidar": "^3.3.1" }, "dependencies": { - "@bull-board/api": "^4.10.2", - "@bull-board/ui": "^4.10.2", - "@napi-rs/cli": "^2.15.0", + "@bull-board/api": "5.2.0", + "@bull-board/ui": "5.2.0", + "@napi-rs/cli": "^2.16.1", "@tensorflow/tfjs": "^3.21.0", "focus-trap": "^7.2.0", "focus-trap-vue": "^4.0.1", diff --git a/packages/backend/jsconfig.json b/packages/backend/jsconfig.json index 1230aadd1..f3f4f9c77 100644 --- a/packages/backend/jsconfig.json +++ b/packages/backend/jsconfig.json @@ -4,10 +4,5 @@ "module": "commonjs", "allowSyntheticDefaultImports": true }, - "exclude": [ - "node_modules", - "jspm_packages", - "tmp", - "temp" - ] + "exclude": ["node_modules", "jspm_packages", "tmp", "temp"] } diff --git a/packages/backend/migration/1000000000000-Init.js b/packages/backend/migration/1000000000000-Init.js index c07500e35..d32a6e0d2 100644 --- a/packages/backend/migration/1000000000000-Init.js +++ b/packages/backend/migration/1000000000000-Init.js @@ -220,7 +220,7 @@ export class Init1000000000000 { `CREATE INDEX "IDX_3c601b70a1066d2c8b517094cb" ON "notification" ("notifieeId") `, ); await queryRunner.query( - `CREATE TABLE "meta" ("id" character varying(32) NOT NULL, "name" character varying(128), "description" character varying(1024), "maintainerName" character varying(128), "maintainerEmail" character varying(128), "announcements" jsonb NOT NULL DEFAULT '[]', "disableRegistration" boolean NOT NULL DEFAULT false, "disableLocalTimeline" boolean NOT NULL DEFAULT false, "disableGlobalTimeline" boolean NOT NULL DEFAULT false, "enableEmojiReaction" boolean NOT NULL DEFAULT true, "useStarForReactionFallback" boolean NOT NULL DEFAULT false, "langs" character varying(64) array NOT NULL DEFAULT '{}'::varchar[], "hiddenTags" character varying(256) array NOT NULL DEFAULT '{}'::varchar[], "blockedHosts" character varying(256) array NOT NULL DEFAULT '{}'::varchar[], "mascotImageUrl" character varying(512) DEFAULT '/assets/ai.png', "bannerUrl" character varying(512), "errorImageUrl" character varying(512) DEFAULT 'https://xn--931a.moe/aiart/yubitun.png', "iconUrl" character varying(512), "cacheRemoteFiles" boolean NOT NULL DEFAULT true, "proxyAccount" character varying(128), "enableRecaptcha" boolean NOT NULL DEFAULT false, "recaptchaSiteKey" character varying(64), "recaptchaSecretKey" character varying(64), "localDriveCapacityMb" integer NOT NULL DEFAULT 1024, "remoteDriveCapacityMb" integer NOT NULL DEFAULT 32, "maxNoteTextLength" integer NOT NULL DEFAULT 500, "summalyProxy" character varying(128), "enableEmail" boolean NOT NULL DEFAULT false, "email" character varying(128), "smtpSecure" boolean NOT NULL DEFAULT false, "smtpHost" character varying(128), "smtpPort" integer, "smtpUser" character varying(128), "smtpPass" character varying(128), "enableServiceWorker" boolean NOT NULL DEFAULT false, "swPublicKey" character varying(128), "swPrivateKey" character varying(128), "enableTwitterIntegration" boolean NOT NULL DEFAULT false, "twitterConsumerKey" character varying(128), "twitterConsumerSecret" character varying(128), "enableGithubIntegration" boolean NOT NULL DEFAULT false, "githubClientId" character varying(128), "githubClientSecret" character varying(128), "enableDiscordIntegration" boolean NOT NULL DEFAULT false, "discordClientId" character varying(128), "discordClientSecret" character varying(128), CONSTRAINT "PK_c4c17a6c2bd7651338b60fc590b" PRIMARY KEY ("id"))`, + `CREATE TABLE "meta" ("id" character varying(32) NOT NULL, "name" character varying(128), "description" character varying(1024), "maintainerName" character varying(128), "maintainerEmail" character varying(128), "announcements" jsonb NOT NULL DEFAULT '[]', "disableRegistration" boolean NOT NULL DEFAULT false, "disableLocalTimeline" boolean NOT NULL DEFAULT false, "disableGlobalTimeline" boolean NOT NULL DEFAULT false, "enableEmojiReaction" boolean NOT NULL DEFAULT true, "useStarForReactionFallback" boolean NOT NULL DEFAULT false, "langs" character varying(64) array NOT NULL DEFAULT '{}'::varchar[], "hiddenTags" character varying(256) array NOT NULL DEFAULT '{}'::varchar[], "blockedHosts" character varying(256) array NOT NULL DEFAULT '{}'::varchar[], "mascotImageUrl" character varying(512) DEFAULT '/static-assets/badges/info.png', "bannerUrl" character varying(512), "errorImageUrl" character varying(512) DEFAULT '/static-assets/badges/error.png', "iconUrl" character varying(512), "cacheRemoteFiles" boolean NOT NULL DEFAULT true, "proxyAccount" character varying(128), "enableRecaptcha" boolean NOT NULL DEFAULT false, "recaptchaSiteKey" character varying(64), "recaptchaSecretKey" character varying(64), "localDriveCapacityMb" integer NOT NULL DEFAULT 1024, "remoteDriveCapacityMb" integer NOT NULL DEFAULT 32, "maxNoteTextLength" integer NOT NULL DEFAULT 500, "summalyProxy" character varying(128), "enableEmail" boolean NOT NULL DEFAULT false, "email" character varying(128), "smtpSecure" boolean NOT NULL DEFAULT false, "smtpHost" character varying(128), "smtpPort" integer, "smtpUser" character varying(128), "smtpPass" character varying(128), "enableServiceWorker" boolean NOT NULL DEFAULT false, "swPublicKey" character varying(128), "swPrivateKey" character varying(128), "enableTwitterIntegration" boolean NOT NULL DEFAULT false, "twitterConsumerKey" character varying(128), "twitterConsumerSecret" character varying(128), "enableGithubIntegration" boolean NOT NULL DEFAULT false, "githubClientId" character varying(128), "githubClientSecret" character varying(128), "enableDiscordIntegration" boolean NOT NULL DEFAULT false, "discordClientId" character varying(128), "discordClientSecret" character varying(128), CONSTRAINT "PK_c4c17a6c2bd7651338b60fc590b" PRIMARY KEY ("id"))`, ); await queryRunner.query( `CREATE TABLE "following" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "followeeId" character varying(32) NOT NULL, "followerId" character varying(32) NOT NULL, "followerHost" character varying(128), "followerInbox" character varying(512), "followerSharedInbox" character varying(512), "followeeHost" character varying(128), "followeeInbox" character varying(512), "followeeSharedInbox" character varying(512), CONSTRAINT "PK_c76c6e044bdf76ecf8bfb82a645" PRIMARY KEY ("id"))`, diff --git a/packages/backend/native-utils/.editorconfig b/packages/backend/native-utils/.editorconfig new file mode 100644 index 000000000..889b72e11 --- /dev/null +++ b/packages/backend/native-utils/.editorconfig @@ -0,0 +1,3 @@ +[*.rs] +indent_style = space +indent_size = 4 diff --git a/packages/backend/native-utils/Cargo.toml b/packages/backend/native-utils/Cargo.toml index 4f7fb4c39..f93180fe4 100644 --- a/packages/backend/native-utils/Cargo.toml +++ b/packages/backend/native-utils/Cargo.toml @@ -3,13 +3,42 @@ edition = "2021" name = "native-utils" version = "0.0.0" +[workspace] +members = ["migration"] + +[features] +default = [] +noarray = [] +napi = ["dep:napi", "dep:napi-derive", "dep:radix_fmt"] + [lib] -crate-type = ["cdylib"] +crate-type = ["cdylib", "lib"] [dependencies] +async-trait = "0.1.68" +cfg-if = "1.0.0" +chrono = "0.4.24" +cuid2 = "0.1.0" +derive_more = "0.99.17" +jsonschema = "0.17.0" +once_cell = "1.17.1" +parse-display = "0.8.0" +rand = "0.8.5" +schemars = { version = "0.8.12", features = ["chrono"] } +sea-orm = { version = "0.11.3", features = ["sqlx-postgres", "postgres-array", "sqlx-sqlite", "runtime-tokio-rustls"] } +serde = { version = "1.0.163", features = ["derive"] } +serde_json = "1.0.96" +thiserror = "1.0.40" +tokio = { version = "1.28.1", features = ["full"] } +utoipa = "3.3.0" + # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix -napi = { version = "2.12.0", default-features = false, features = ["napi4"] } -napi-derive = "2.12.0" +napi = { version = "2.13.1", default-features = false, features = ["napi6", "tokio_rt"], optional = true } +napi-derive = { version = "2.12.0", optional = true } +radix_fmt = { version = "1.0.0", optional = true } + +[dev-dependencies] +pretty_assertions = "1.3.0" [build-dependencies] napi-build = "2.0.1" diff --git a/packages/backend/native-utils/__test__/index.spec.mjs b/packages/backend/native-utils/__test__/index.spec.mjs index 0d41e012d..6e6a91858 100644 --- a/packages/backend/native-utils/__test__/index.spec.mjs +++ b/packages/backend/native-utils/__test__/index.spec.mjs @@ -1,7 +1,32 @@ import test from "ava"; -import { sum } from "../index.js"; +import { + convertId, + IdConvertType, + nativeInitIdGenerator, + nativeCreateId, + nativeRandomStr, +} from "../built/index.js"; -test("sum from native", (t) => { - t.is(sum(1, 2), 3); +test("convert to mastodon id", (t) => { + t.is(convertId("9gf61ehcxv", IdConvertType.MastodonId), "960365976481219"); + t.is( + convertId("9fbr9z0wbrjqyd3u", IdConvertType.MastodonId), + "3954607381600562394", + ); + t.is( + convertId("9fbs680oyviiqrol9md73p8g", IdConvertType.MastodonId), + "3494513243013053824", + ); +}); + +test("create cuid2 with timestamp prefix", (t) => { + nativeInitIdGenerator(16, ""); + t.not(nativeCreateId(BigInt(Date.now())), nativeCreateId(BigInt(Date.now()))); + t.is(nativeCreateId(BigInt(Date.now())).length, 16); +}); + +test("create random string", (t) => { + t.not(nativeRandomStr(16), nativeRandomStr(16)); + t.is(nativeRandomStr(24).length, 24); }); diff --git a/packages/backend/native-utils/build.rs b/packages/backend/native-utils/build.rs index 1f866b6a3..9fc236788 100644 --- a/packages/backend/native-utils/build.rs +++ b/packages/backend/native-utils/build.rs @@ -1,5 +1,5 @@ extern crate napi_build; fn main() { - napi_build::setup(); + napi_build::setup(); } diff --git a/packages/backend/native-utils/migration/Cargo.toml b/packages/backend/native-utils/migration/Cargo.toml new file mode 100644 index 000000000..3813eccd8 --- /dev/null +++ b/packages/backend/native-utils/migration/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "migration" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "migration" +path = "src/lib.rs" + +[features] +default = [] +convert = ["dep:native-utils"] + +[dependencies] +async-std = { version = "1", features = ["attributes", "tokio1"] } +serde_json = "1.0.96" +native-utils = { path = "../", optional = true } +indicatif = { version = "0.17.4", features = ["tokio"] } +tokio = { version = "1.28.2", features = ["full"] } +futures = "0.3.28" +serde_yaml = "0.9.21" +serde = { version = "1.0.163", features = ["derive"] } + +[dependencies.sea-orm-migration] +version = "0.11.0" +features = [ + # Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI. + # View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime. + # e.g. + "runtime-tokio-rustls", # `ASYNC_RUNTIME` feature + "sqlx-postgres", # `DATABASE_DRIVER` feature + "sqlx-sqlite", +] diff --git a/packages/backend/native-utils/migration/README.md b/packages/backend/native-utils/migration/README.md new file mode 100644 index 000000000..b3ea53eb4 --- /dev/null +++ b/packages/backend/native-utils/migration/README.md @@ -0,0 +1,41 @@ +# Running Migrator CLI + +- Generate a new migration file + ```sh + cargo run -- migrate generate MIGRATION_NAME + ``` +- Apply all pending migrations + ```sh + cargo run + ``` + ```sh + cargo run -- up + ``` +- Apply first 10 pending migrations + ```sh + cargo run -- up -n 10 + ``` +- Rollback last applied migrations + ```sh + cargo run -- down + ``` +- Rollback last 10 applied migrations + ```sh + cargo run -- down -n 10 + ``` +- Drop all tables from the database, then reapply all migrations + ```sh + cargo run -- fresh + ``` +- Rollback all applied migrations, then reapply all migrations + ```sh + cargo run -- refresh + ``` +- Rollback all applied migrations + ```sh + cargo run -- reset + ``` +- Check the status of all migrations + ```sh + cargo run -- status + ``` diff --git a/packages/backend/native-utils/migration/src/lib.rs b/packages/backend/native-utils/migration/src/lib.rs new file mode 100644 index 000000000..4835c2d3d --- /dev/null +++ b/packages/backend/native-utils/migration/src/lib.rs @@ -0,0 +1,12 @@ +pub use sea_orm_migration::prelude::*; + +mod m20230531_180824_drop_reversi; + +pub struct Migrator; + +#[async_trait::async_trait] +impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + vec![Box::new(m20230531_180824_drop_reversi::Migration)] + } +} diff --git a/packages/backend/native-utils/migration/src/m20230531_180824_drop_reversi.rs b/packages/backend/native-utils/migration/src/m20230531_180824_drop_reversi.rs new file mode 100644 index 000000000..32b8dae22 --- /dev/null +++ b/packages/backend/native-utils/migration/src/m20230531_180824_drop_reversi.rs @@ -0,0 +1,51 @@ +use sea_orm_migration::{ + prelude::*, + sea_orm::{DbBackend, Statement}, +}; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + if manager.get_database_backend() == DbBackend::Sqlite { + return Ok(()); + } + + let db = manager.get_connection(); + db.query_one(Statement::from_string( + DbBackend::Postgres, + Table::drop() + .table(ReversiGame::Table) + .if_exists() + .to_string(PostgresQueryBuilder), + )) + .await?; + db.query_one(Statement::from_string( + DbBackend::Postgres, + Table::drop() + .table(ReversiMatching::Table) + .if_exists() + .to_string(PostgresQueryBuilder), + )) + .await?; + + Ok(()) + } + + async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> { + // Replace the sample below with your own migration scripts + Ok(()) + } +} + +/// Learn more at https://docs.rs/sea-query#iden +#[derive(Iden)] +enum ReversiGame { + Table, +} +#[derive(Iden)] +enum ReversiMatching { + Table, +} diff --git a/packages/backend/native-utils/migration/src/main.rs b/packages/backend/native-utils/migration/src/main.rs new file mode 100644 index 000000000..a845a41ff --- /dev/null +++ b/packages/backend/native-utils/migration/src/main.rs @@ -0,0 +1,45 @@ +use serde::Deserialize; +use std::env; +use std::fs; + +use sea_orm_migration::prelude::*; + +#[cfg(feature = "convert")] +mod vec_to_json; + +#[async_std::main] +async fn main() { + let cwd = env::current_dir().unwrap(); + let yml = fs::File::open(cwd.join("../../.config/default.yml")) + .expect("Unable to read '.config/default.yml'"); + let config: Config = serde_yaml::from_reader(yml).expect("Unable to parse"); + + env::set_var( + "DATABASE_URL", + format!( + "postgres://{}:{}@{}:{}/{}", + config.db.user, config.db.pass, config.db.host, config.db.port, config.db.db + ), + ); + + cli::run_cli(migration::Migrator).await; + + #[cfg(feature = "convert")] + vec_to_json::convert().await; +} + +#[derive(Debug, PartialEq, Deserialize)] +#[serde(rename = "camelCase")] +pub struct Config { + pub db: DbConfig, +} + +#[derive(Debug, PartialEq, Deserialize)] +#[serde(rename = "camelCase")] +pub struct DbConfig { + pub host: String, + pub port: u32, + pub db: String, + pub user: String, + pub pass: String, +} diff --git a/packages/backend/native-utils/migration/src/vec_to_json.rs b/packages/backend/native-utils/migration/src/vec_to_json.rs new file mode 100644 index 000000000..104357a49 --- /dev/null +++ b/packages/backend/native-utils/migration/src/vec_to_json.rs @@ -0,0 +1,498 @@ +use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; +use native_utils::model::entity::newtype::{I32Vec, StringVec}; +use sea_orm_migration::{ + prelude::*, + sea_orm::{Database, DbBackend, DbConn, Statement, TryGetable}, +}; +use serde_json::json; +use std::env; +use std::time::Duration; + +pub async fn convert() { + let uri = env::var("DATABASE_URL").expect("Environment variable 'DATABASE_URL' not set"); + + let db = Database::connect(uri).await.expect("Unable to connect"); + let mp = MultiProgress::new(); + + let handlers = vec![ + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + AccessToken::Table, + AccessToken::Id, + AccessToken::Permission, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Antenna::Table, + Antenna::Id, + Antenna::Users, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + App::Table, + App::Id, + App::Permission, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Emoji::Table, + Emoji::Id, + Emoji::Aliases, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + GalleryPost::Table, + GalleryPost::Id, + GalleryPost::FileIds, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + GalleryPost::Table, + GalleryPost::Id, + GalleryPost::Tags, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Hashtag::Table, + Hashtag::Id, + Hashtag::MentionedUserIds, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Hashtag::Table, + Hashtag::Id, + Hashtag::MentionedLocalUserIds, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Hashtag::Table, + Hashtag::Id, + Hashtag::MentionedRemoteUserIds, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Hashtag::Table, + Hashtag::Id, + Hashtag::AttachedUserIds, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Hashtag::Table, + Hashtag::Id, + Hashtag::AttachedLocalUserIds, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Hashtag::Table, + Hashtag::Id, + Hashtag::AttachedRemoteUserIds, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + MessagingMessage::Table, + MessagingMessage::Id, + MessagingMessage::Reads, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Meta::Table, + Meta::Id, + Meta::Langs, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Meta::Table, + Meta::Id, + Meta::BlockedHosts, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Meta::Table, + Meta::Id, + Meta::HiddenTags, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Meta::Table, + Meta::Id, + Meta::PinnedUsers, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Meta::Table, + Meta::Id, + Meta::PinnedPages, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Meta::Table, + Meta::Id, + Meta::RecommendedInstances, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Meta::Table, + Meta::Id, + Meta::SilencedHosts, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Note::Table, + Note::Id, + Note::FileIds, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Note::Table, + Note::Id, + Note::AttachedFileTypes, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Note::Table, + Note::Id, + Note::VisibleUserIds, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Note::Table, + Note::Id, + Note::Mentions, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Note::Table, + Note::Id, + Note::Emojis, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Note::Table, + Note::Id, + Note::Tags, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + NoteEdit::Table, + NoteEdit::Id, + NoteEdit::FileIds, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Page::Table, + Page::Id, + Page::VisibleUserIds, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + RegistryItem::Table, + RegistryItem::Id, + RegistryItem::Scope, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + User::Table, + User::Id, + User::Tags, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + User::Table, + User::Id, + User::Emojis, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Webhook::Table, + Webhook::Id, + Webhook::On, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + Poll::Table, + Poll::NoteId, + Poll::Choices, + )), + tokio::spawn(to_json::, I32Vec>( + db.clone(), + mp.clone(), + Poll::Table, + Poll::NoteId, + Poll::Votes, + )), + tokio::spawn(to_json::, StringVec>( + db.clone(), + mp.clone(), + UserProfile::Table, + UserProfile::UserId, + UserProfile::MutingNotificationTypes, + )), + ]; + + futures::future::join_all(handlers).await; +} + +fn select_query(table: T, id: T, col: T) -> String { + Query::select() + .column(id) + .column(col) + .from(table) + .to_string(PostgresQueryBuilder) +} + +async fn get_vec(db: &DbConn, query: String) -> Result, DbErr> { + let res: Vec<(String, T)> = db + .query_all(Statement::from_string(DbBackend::Postgres, query)) + .await? + .iter() + .filter_map(|r| r.try_get_many_by_index().ok()) + .collect(); + Ok(res) +} + +async fn convert_col( + db: &DbConn, + table: T, + col: T, +) -> Result<(), DbErr> { + let stmt = Table::alter() + .table(table) + .drop_column(col.to_owned()) + .add_column( + ColumnDef::new(col.to_owned()) + .json_binary() + .not_null() + .default(json!([])), + ) + .to_string(PostgresQueryBuilder); + db.query_one(Statement::from_string(DbBackend::Postgres, stmt)) + .await?; + Ok(()) +} + +async fn to_json( + db: DbConn, + mp: MultiProgress, + table: T, + id: T, + col: T, +) -> Result<(), DbErr> +where + T: Iden + Clone + 'static, + U: TryGetable + IntoIterator + Clone, + V: From + Into, +{ + let query = select_query(table.clone(), id.clone(), col.clone()); + let loading = ProgressBar::new_spinner() + .with_style(ProgressStyle::with_template("{prefix} {msg} {spinner}").unwrap()) + .with_prefix("[-]") + .with_message(format!( + "Loading data from {}.{}", + table.to_string(), + col.to_string() + )); + let loading = mp.add(loading); + loading.enable_steady_tick(Duration::from_millis(100)); + let res = get_vec::(&db, query).await?; + let models: Vec<(String, V)> = res + .iter() + .filter(|(_, r)| r.clone().into_iter().count() > 0) + .map(|(id, r)| (id.clone(), ::from(r.clone()))) + .collect(); + loading.finish_and_clear(); + convert_col(&db, table.clone(), col.clone()).await?; + + let progress = ProgressBar::new(models.len() as u64) + .with_style( + ProgressStyle::with_template("{prefix} {msg} {wide_bar} {pos}/{len}") + .unwrap() + .progress_chars("##-"), + ) + .with_prefix("[*]") + .with_message(format!("Copying {}.{}", table.to_string(), col.to_string())); + let progress = mp.add(progress); + + for model in models { + progress.inc(1); + let q = Query::update() + .table(table.clone()) + .values([(col.clone(), model.1.into())]) + .and_where(Expr::col(id.clone()).eq(model.0)) + .to_string(PostgresQueryBuilder); + db.query_one(Statement::from_string(DbBackend::Postgres, q)) + .await?; + } + progress.finish_with_message(format!("Done {}.{}", table.to_string(), col.to_string())); + + Ok(()) +} + +#[derive(Iden, Clone)] +enum AccessToken { + Table, + Id, + Permission, +} +#[derive(Iden, Clone)] +enum Antenna { + Table, + Id, + Users, +} +#[derive(Iden, Clone)] +enum App { + Table, + Id, + Permission, +} +#[derive(Iden, Clone)] +enum Emoji { + Table, + Id, + Aliases, +} +#[derive(Iden, Clone)] +enum GalleryPost { + Table, + Id, + #[iden = "fileIds"] + FileIds, + Tags, +} +#[derive(Iden, Clone)] +enum Hashtag { + Table, + Id, + #[iden = "mentionedUserIds"] + MentionedUserIds, + #[iden = "mentionedLocalUserIds"] + MentionedLocalUserIds, + #[iden = "mentionedRemoteUserIds"] + MentionedRemoteUserIds, + #[iden = "attachedUserIds"] + AttachedUserIds, + #[iden = "attachedLocalUserIds"] + AttachedLocalUserIds, + #[iden = "attachedRemoteUserIds"] + AttachedRemoteUserIds, +} +#[derive(Iden, Clone)] +enum MessagingMessage { + Table, + Id, + Reads, +} +#[derive(Iden, Clone)] +enum Meta { + Table, + Id, + Langs, + #[iden = "hiddenTags"] + HiddenTags, + #[iden = "blockedHosts"] + BlockedHosts, + #[iden = "pinnedUsers"] + PinnedUsers, + #[iden = "pinnedPages"] + PinnedPages, + #[iden = "recommendedInstances"] + RecommendedInstances, + #[iden = "silencedHosts"] + SilencedHosts, +} +#[derive(Iden, Clone)] +enum Note { + Table, + Id, + #[iden = "fileIds"] + FileIds, + #[iden = "attachedFileTypes"] + AttachedFileTypes, + #[iden = "visibleUserIds"] + VisibleUserIds, + Mentions, + Emojis, + Tags, +} +#[derive(Iden, Clone)] +enum NoteEdit { + Table, + Id, + #[iden = "fileIds"] + FileIds, +} +#[derive(Iden, Clone)] +enum Page { + Table, + Id, + #[iden = "visibleUserIds"] + VisibleUserIds, +} +#[derive(Iden, Clone)] +enum Poll { + Table, + #[iden = "noteId"] + NoteId, + Choices, + Votes, // I32Vec +} +#[derive(Iden, Clone)] +enum RegistryItem { + Table, + Id, + Scope, +} +#[derive(Iden, Clone)] +enum User { + Table, + Id, + Tags, + Emojis, +} +#[derive(Iden, Clone)] +enum UserProfile { + Table, + #[iden = "userId"] + UserId, + #[iden = "mutingNotificationTypes"] + MutingNotificationTypes, +} +#[derive(Iden, Clone)] +enum Webhook { + Table, + Id, + On, +} diff --git a/packages/backend/native-utils/package.json b/packages/backend/native-utils/package.json index 787d1bd89..2e6a721f4 100644 --- a/packages/backend/native-utils/package.json +++ b/packages/backend/native-utils/package.json @@ -23,8 +23,8 @@ }, "license": "MIT", "devDependencies": { - "@napi-rs/cli": "^2.15.0", - "ava": "^5.1.1" + "@napi-rs/cli": "2.16.1", + "ava": "5.1.1" }, "ava": { "timeout": "3m" @@ -34,11 +34,15 @@ }, "scripts": { "artifacts": "napi artifacts", - "build": "napi build --platform --release ./built/", + "build": "napi build --features napi --platform --release ./built/", "build:debug": "napi build --platform", "prepublishOnly": "napi prepublish -t npm", - "test": "ava", + "test": "pnpm run cargo:test && pnpm run build && ava", "universal": "napi universal", - "version": "napi version" + "version": "napi version", + "format": "cargo fmt --all", + "cargo:test": "pnpm run cargo:unit && pnpm run cargo:integration", + "cargo:unit": "cargo test unit_test && cargo test -F napi unit_test", + "cargo:integration": "cargo test -F noarray int_test -- --test-threads=1" } } diff --git a/packages/backend/native-utils/rustfmt.toml b/packages/backend/native-utils/rustfmt.toml deleted file mode 100644 index cab5731ed..000000000 --- a/packages/backend/native-utils/rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -tab_spaces = 2 -edition = "2021" diff --git a/packages/backend/native-utils/src/database/error.rs b/packages/backend/native-utils/src/database/error.rs new file mode 100644 index 000000000..68e959e0a --- /dev/null +++ b/packages/backend/native-utils/src/database/error.rs @@ -0,0 +1,13 @@ +use sea_orm::error::DbErr; + +use crate::impl_into_napi_error; + +#[derive(thiserror::Error, Debug, PartialEq, Eq)] +pub enum Error { + #[error("The database connections have not been initialized yet")] + Uninitialized, + #[error("ORM error: {0}")] + OrmError(#[from] DbErr), +} + +impl_into_napi_error!(Error); diff --git a/packages/backend/native-utils/src/database/mod.rs b/packages/backend/native-utils/src/database/mod.rs new file mode 100644 index 000000000..80189a813 --- /dev/null +++ b/packages/backend/native-utils/src/database/mod.rs @@ -0,0 +1,38 @@ +pub mod error; + +use cfg_if::cfg_if; +use error::Error; +use sea_orm::{Database, DbConn}; + +static DB_CONN: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); + +pub async fn init_database(conn_uri: impl Into) -> Result<(), Error> { + let conn = Database::connect(conn_uri.into()).await?; + DB_CONN.get_or_init(move || conn); + Ok(()) +} + +pub fn get_database() -> Result<&'static DbConn, Error> { + DB_CONN.get().ok_or(Error::Uninitialized) +} + +cfg_if! { + if #[cfg(feature = "napi")] { + use napi_derive::napi; + + #[napi] + pub async fn native_init_database(conn_uri: String) -> napi::Result<()> { + init_database(conn_uri).await.map_err(Into::into) + } + } +} + +#[cfg(test)] +mod unit_test { + use super::{error::Error, get_database}; + + #[test] + fn error_uninitialized() { + assert_eq!(get_database().unwrap_err(), Error::Uninitialized); + } +} diff --git a/packages/backend/native-utils/src/lib.rs b/packages/backend/native-utils/src/lib.rs index bc5b9fc7c..f18e69a48 100644 --- a/packages/backend/native-utils/src/lib.rs +++ b/packages/backend/native-utils/src/lib.rs @@ -1,2 +1,7 @@ +pub mod database; +pub mod macros; +pub mod model; +pub mod util; +#[cfg(feature = "napi")] pub mod mastodon_api; diff --git a/packages/backend/native-utils/src/macros.rs b/packages/backend/native-utils/src/macros.rs new file mode 100644 index 000000000..49ab82632 --- /dev/null +++ b/packages/backend/native-utils/src/macros.rs @@ -0,0 +1,11 @@ +#[macro_export] +macro_rules! impl_into_napi_error { + ($a:ty) => { + #[cfg(feature = "napi")] + impl Into for $a { + fn into(self) -> napi::Error { + napi::Error::from_reason(self.to_string()) + } + } + }; +} diff --git a/packages/backend/native-utils/src/mastodon_api.rs b/packages/backend/native-utils/src/mastodon_api.rs index 36b4eb984..7a3ea455a 100644 --- a/packages/backend/native-utils/src/mastodon_api.rs +++ b/packages/backend/native-utils/src/mastodon_api.rs @@ -7,64 +7,64 @@ static CHAR_COLLECTION: &str = "0123456789abcdefghijklmnopqrstuvwxyz"; #[napi] pub enum IdConvertType { - MastodonId, - CalckeyId, + MastodonId, + CalckeyId, } #[napi] pub fn convert_id(in_id: String, id_convert_type: IdConvertType) -> napi::Result { - use IdConvertType::*; - match id_convert_type { - MastodonId => { - let mut out: i64 = 0; - for (i, c) in in_id.to_lowercase().chars().rev().enumerate() { - out += num_from_char(c)? as i64 * 36_i64.pow(i as u32); - } + use IdConvertType::*; + match id_convert_type { + MastodonId => { + let mut out: i64 = 0; + for (i, c) in in_id.to_lowercase().chars().rev().enumerate() { + out += num_from_char(c)? as i64 * 36_i64.pow(i as u32); + } - Ok(out.to_string()) - } - CalckeyId => { - let mut input: i64 = match in_id.parse() { - Ok(s) => s, - Err(_) => { - return Err(Error::new( - Status::InvalidArg, - "Unable to parse ID as MasstodonId", - )) + Ok(out.to_string()) } - }; - let mut out = String::new(); + CalckeyId => { + let mut input: i64 = match in_id.parse() { + Ok(s) => s, + Err(_) => { + return Err(Error::new( + Status::InvalidArg, + "Unable to parse ID as MasstodonId", + )) + } + }; + let mut out = String::new(); - while input != 0 { - out.insert(0, char_from_num((input % 36) as u8)?); - input /= 36; - } + while input != 0 { + out.insert(0, char_from_num((input % 36) as u8)?); + input /= 36; + } - Ok(out) + Ok(out) + } } - } } // -- end -- #[inline(always)] fn num_from_char(character: char) -> napi::Result { - for (i, c) in CHAR_COLLECTION.chars().enumerate() { - if c == character { - return Ok(i as u8); + for (i, c) in CHAR_COLLECTION.chars().enumerate() { + if c == character { + return Ok(i as u8); + } } - } - Err(Error::new( - Status::InvalidArg, - "Invalid character in parsed base36 id", - )) + Err(Error::new( + Status::InvalidArg, + "Invalid character in parsed base36 id", + )) } #[inline(always)] fn char_from_num(number: u8) -> napi::Result { - CHAR_COLLECTION - .chars() - .nth(number as usize) - .ok_or(Error::from_status(Status::Unknown)) + CHAR_COLLECTION + .chars() + .nth(number as usize) + .ok_or(Error::from_status(Status::Unknown)) } diff --git a/packages/backend/native-utils/src/model/entity.rs b/packages/backend/native-utils/src/model/entity.rs new file mode 100644 index 000000000..d71057fde --- /dev/null +++ b/packages/backend/native-utils/src/model/entity.rs @@ -0,0 +1,74 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +pub mod prelude; + +pub mod abuse_user_report; +pub mod access_token; +pub mod ad; +pub mod announcement; +pub mod announcement_read; +pub mod antenna; +pub mod antenna_note; +pub mod app; +pub mod attestation_challenge; +pub mod auth_session; +pub mod blocking; +pub mod channel; +pub mod channel_following; +pub mod channel_note_pining; +pub mod clip; +pub mod clip_note; +pub mod drive_file; +pub mod drive_folder; +pub mod emoji; +pub mod follow_request; +pub mod following; +pub mod gallery_like; +pub mod gallery_post; +pub mod hashtag; +pub mod instance; +pub mod messaging_message; +pub mod meta; +pub mod migrations; +pub mod moderation_log; +pub mod muted_note; +pub mod muting; +pub mod newtype; +pub mod note; +pub mod note_edit; +pub mod note_favorite; +pub mod note_reaction; +pub mod note_thread_muting; +pub mod note_unread; +pub mod note_watching; +pub mod notification; +pub mod page; +pub mod page_like; +pub mod password_reset_request; +pub mod poll; +pub mod poll_vote; +pub mod promo_note; +pub mod promo_read; +pub mod registration_ticket; +pub mod registry_item; +pub mod relay; +pub mod renote_muting; +pub mod sea_orm_active_enums; +pub mod signin; +pub mod sw_subscription; +pub mod used_username; +pub mod user; +pub mod user_group; +pub mod user_group_invitation; +pub mod user_group_invite; +pub mod user_group_joining; +pub mod user_ip; +pub mod user_keypair; +pub mod user_list; +pub mod user_list_joining; +pub mod user_note_pining; +pub mod user_pending; +pub mod user_profile; +pub mod user_publickey; +pub mod user_security_key; +pub mod webhook; diff --git a/packages/backend/native-utils/src/model/entity/abuse_user_report.rs b/packages/backend/native-utils/src/model/entity/abuse_user_report.rs new file mode 100644 index 000000000..24230b394 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/abuse_user_report.rs @@ -0,0 +1,55 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "abuse_user_report")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "targetUserId")] + pub target_user_id: String, + #[sea_orm(column_name = "reporterId")] + pub reporter_id: String, + #[sea_orm(column_name = "assigneeId")] + pub assignee_id: Option, + pub resolved: bool, + pub comment: String, + #[sea_orm(column_name = "targetUserHost")] + pub target_user_host: Option, + #[sea_orm(column_name = "reporterHost")] + pub reporter_host: Option, + pub forwarded: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::ReporterId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User3, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::AssigneeId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "SetNull" + )] + User2, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::TargetUserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User1, +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/access_token.rs b/packages/backend/native-utils/src/model/entity/access_token.rs new file mode 100644 index 000000000..dd9289224 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/access_token.rs @@ -0,0 +1,71 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "access_token")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + pub token: String, + pub hash: String, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "appId")] + pub app_id: Option, + #[sea_orm(column_name = "lastUsedAt")] + pub last_used_at: Option, + pub session: Option, + pub name: Option, + pub description: Option, + #[sea_orm(column_name = "iconUrl")] + pub icon_url: Option, + pub permission: StringVec, + pub fetched: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::app::Entity", + from = "Column::AppId", + to = "super::app::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + App, + #[sea_orm(has_many = "super::notification::Entity")] + Notification, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::App.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Notification.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/ad.rs b/packages/backend/native-utils/src/model/entity/ad.rs new file mode 100644 index 000000000..2cf7a6fc8 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/ad.rs @@ -0,0 +1,26 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "ad")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "expiresAt")] + pub expires_at: DateTimeWithTimeZone, + pub place: String, + pub priority: String, + pub url: String, + #[sea_orm(column_name = "imageUrl")] + pub image_url: String, + pub memo: String, + pub ratio: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/announcement.rs b/packages/backend/native-utils/src/model/entity/announcement.rs new file mode 100644 index 000000000..e8a2a28aa --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/announcement.rs @@ -0,0 +1,32 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "announcement")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + pub text: String, + pub title: String, + #[sea_orm(column_name = "imageUrl")] + pub image_url: Option, + #[sea_orm(column_name = "updatedAt")] + pub updated_at: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::announcement_read::Entity")] + AnnouncementRead, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::AnnouncementRead.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/announcement_read.rs b/packages/backend/native-utils/src/model/entity/announcement_read.rs new file mode 100644 index 000000000..53ff8d6ce --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/announcement_read.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "announcement_read")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "announcementId")] + pub announcement_id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::announcement::Entity", + from = "Column::AnnouncementId", + to = "super::announcement::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Announcement, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Announcement.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/antenna.rs b/packages/backend/native-utils/src/model/entity/antenna.rs new file mode 100644 index 000000000..85bdfbfea --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/antenna.rs @@ -0,0 +1,92 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use super::{newtype, sea_orm_active_enums::AntennaSrcEnum}; +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "antenna")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + pub name: String, + pub src: AntennaSrcEnum, + #[sea_orm(column_name = "userListId")] + pub user_list_id: Option, + #[sea_orm(column_type = "JsonBinary")] + pub keywords: newtype::JsonKeyword, + #[sea_orm(column_name = "withFile")] + pub with_file: bool, + pub expression: Option, + pub notify: bool, + #[sea_orm(column_name = "caseSensitive")] + pub case_sensitive: bool, + #[sea_orm(column_name = "withReplies")] + pub with_replies: bool, + #[sea_orm(column_name = "userGroupJoiningId")] + pub user_group_joining_id: Option, + pub users: newtype::StringVec, + #[sea_orm(column_name = "excludeKeywords", column_type = "JsonBinary")] + pub exclude_keywords: newtype::JsonKeyword, + #[sea_orm(column_type = "JsonBinary")] + pub instances: newtype::JsonStringVec, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::antenna_note::Entity")] + AntennaNote, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, + #[sea_orm( + belongs_to = "super::user_group_joining::Entity", + from = "Column::UserGroupJoiningId", + to = "super::user_group_joining::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + UserGroupJoining, + #[sea_orm( + belongs_to = "super::user_list::Entity", + from = "Column::UserListId", + to = "super::user_list::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + UserList, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::AntennaNote.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroupJoining.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserList.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/antenna_note.rs b/packages/backend/native-utils/src/model/entity/antenna_note.rs new file mode 100644 index 000000000..c86fb349d --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/antenna_note.rs @@ -0,0 +1,49 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "antenna_note")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, + #[sea_orm(column_name = "antennaId")] + pub antenna_id: String, + pub read: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::antenna::Entity", + from = "Column::AntennaId", + to = "super::antenna::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Antenna, + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Antenna.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/app.rs b/packages/backend/native-utils/src/model/entity/app.rs new file mode 100644 index 000000000..6400d0b24 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/app.rs @@ -0,0 +1,58 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "app")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: Option, + pub secret: String, + pub name: String, + pub description: String, + pub permission: StringVec, + #[sea_orm(column_name = "callbackUrl")] + pub callback_url: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::access_token::Entity")] + AccessToken, + #[sea_orm(has_many = "super::auth_session::Entity")] + AuthSession, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "SetNull" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::AccessToken.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::AuthSession.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/attestation_challenge.rs b/packages/backend/native-utils/src/model/entity/attestation_challenge.rs new file mode 100644 index 000000000..5217b2796 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/attestation_challenge.rs @@ -0,0 +1,37 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "attestation_challenge")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "userId", primary_key, auto_increment = false)] + pub user_id: String, + pub challenge: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "registrationChallenge")] + pub registration_challenge: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/auth_session.rs b/packages/backend/native-utils/src/model/entity/auth_session.rs new file mode 100644 index 000000000..8ced191c3 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/auth_session.rs @@ -0,0 +1,51 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "auth_session")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + pub token: String, + #[sea_orm(column_name = "userId")] + pub user_id: Option, + #[sea_orm(column_name = "appId")] + pub app_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::app::Entity", + from = "Column::AppId", + to = "super::app::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + App, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::App.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/blocking.rs b/packages/backend/native-utils/src/model/entity/blocking.rs new file mode 100644 index 000000000..4f326f6fa --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/blocking.rs @@ -0,0 +1,38 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "blocking")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "blockeeId")] + pub blockee_id: String, + #[sea_orm(column_name = "blockerId")] + pub blocker_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::BlockerId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User2, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::BlockeeId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User1, +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/channel.rs b/packages/backend/native-utils/src/model/entity/channel.rs new file mode 100644 index 000000000..abc79b4f5 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/channel.rs @@ -0,0 +1,82 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "channel")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "lastNotedAt")] + pub last_noted_at: Option, + #[sea_orm(column_name = "userId")] + pub user_id: Option, + pub name: String, + pub description: Option, + #[sea_orm(column_name = "bannerId")] + pub banner_id: Option, + #[sea_orm(column_name = "notesCount")] + pub notes_count: i32, + #[sea_orm(column_name = "usersCount")] + pub users_count: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::channel_following::Entity")] + ChannelFollowing, + #[sea_orm(has_many = "super::channel_note_pining::Entity")] + ChannelNotePining, + #[sea_orm( + belongs_to = "super::drive_file::Entity", + from = "Column::BannerId", + to = "super::drive_file::Column::Id", + on_update = "NoAction", + on_delete = "SetNull" + )] + DriveFile, + #[sea_orm(has_many = "super::note::Entity")] + Note, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "SetNull" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ChannelFollowing.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ChannelNotePining.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::DriveFile.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/channel_following.rs b/packages/backend/native-utils/src/model/entity/channel_following.rs new file mode 100644 index 000000000..93739459a --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/channel_following.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "channel_following")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "followeeId")] + pub followee_id: String, + #[sea_orm(column_name = "followerId")] + pub follower_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::channel::Entity", + from = "Column::FolloweeId", + to = "super::channel::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Channel, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::FollowerId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Channel.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/channel_note_pining.rs b/packages/backend/native-utils/src/model/entity/channel_note_pining.rs new file mode 100644 index 000000000..50ec1ecef --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/channel_note_pining.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "channel_note_pining")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "channelId")] + pub channel_id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::channel::Entity", + from = "Column::ChannelId", + to = "super::channel::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Channel, + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Channel.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/clip.rs b/packages/backend/native-utils/src/model/entity/clip.rs new file mode 100644 index 000000000..a51ef720e --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/clip.rs @@ -0,0 +1,46 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "clip")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + pub name: String, + #[sea_orm(column_name = "isPublic")] + pub is_public: bool, + pub description: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::clip_note::Entity")] + ClipNote, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ClipNote.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/clip_note.rs b/packages/backend/native-utils/src/model/entity/clip_note.rs new file mode 100644 index 000000000..a8bfd4564 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/clip_note.rs @@ -0,0 +1,48 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "clip_note")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, + #[sea_orm(column_name = "clipId")] + pub clip_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::clip::Entity", + from = "Column::ClipId", + to = "super::clip::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Clip, + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Clip.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/drive_file.rs b/packages/backend/native-utils/src/model/entity/drive_file.rs new file mode 100644 index 000000000..7c42b9881 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/drive_file.rs @@ -0,0 +1,113 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "drive_file")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: Option, + #[sea_orm(column_name = "userHost")] + pub user_host: Option, + pub md5: String, + pub name: String, + pub r#type: String, + pub size: i32, + pub comment: Option, + #[sea_orm(column_type = "JsonBinary")] + pub properties: Json, + #[sea_orm(column_name = "storedInternal")] + pub stored_internal: bool, + pub url: String, + #[sea_orm(column_name = "thumbnailUrl")] + pub thumbnail_url: Option, + #[sea_orm(column_name = "webpublicUrl")] + pub webpublic_url: Option, + #[sea_orm(column_name = "accessKey")] + pub access_key: Option, + #[sea_orm(column_name = "thumbnailAccessKey")] + pub thumbnail_access_key: Option, + #[sea_orm(column_name = "webpublicAccessKey")] + pub webpublic_access_key: Option, + pub uri: Option, + pub src: Option, + #[sea_orm(column_name = "folderId")] + pub folder_id: Option, + #[sea_orm(column_name = "isSensitive")] + pub is_sensitive: bool, + #[sea_orm(column_name = "isLink")] + pub is_link: bool, + pub blurhash: Option, + #[sea_orm(column_name = "webpublicType")] + pub webpublic_type: Option, + #[sea_orm(column_name = "requestHeaders", column_type = "JsonBinary", nullable)] + pub request_headers: Option, + #[sea_orm(column_name = "requestIp")] + pub request_ip: Option, + #[sea_orm(column_name = "maybeSensitive")] + pub maybe_sensitive: bool, + #[sea_orm(column_name = "maybePorn")] + pub maybe_porn: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::channel::Entity")] + Channel, + #[sea_orm( + belongs_to = "super::drive_folder::Entity", + from = "Column::FolderId", + to = "super::drive_folder::Column::Id", + on_update = "NoAction", + on_delete = "SetNull" + )] + DriveFolder, + #[sea_orm(has_many = "super::messaging_message::Entity")] + MessagingMessage, + #[sea_orm(has_many = "super::page::Entity")] + Page, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "SetNull" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Channel.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::DriveFolder.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::MessagingMessage.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Page.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/drive_folder.rs b/packages/backend/native-utils/src/model/entity/drive_folder.rs new file mode 100644 index 000000000..98a9f8901 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/drive_folder.rs @@ -0,0 +1,53 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "drive_folder")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + pub name: String, + #[sea_orm(column_name = "userId")] + pub user_id: Option, + #[sea_orm(column_name = "parentId")] + pub parent_id: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::drive_file::Entity")] + DriveFile, + #[sea_orm( + belongs_to = "Entity", + from = "Column::ParentId", + to = "Column::Id", + on_update = "NoAction", + on_delete = "SetNull" + )] + SelfRef, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::DriveFile.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/emoji.rs b/packages/backend/native-utils/src/model/entity/emoji.rs new file mode 100644 index 000000000..00fc6184a --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/emoji.rs @@ -0,0 +1,32 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "emoji")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "updatedAt")] + pub updated_at: Option, + pub name: String, + pub host: Option, + #[sea_orm(column_name = "originalUrl")] + pub original_url: String, + pub uri: Option, + pub r#type: Option, + pub aliases: StringVec, + pub category: Option, + #[sea_orm(column_name = "publicUrl")] + pub public_url: String, + pub license: Option, + pub width: Option, + pub height: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/follow_request.rs b/packages/backend/native-utils/src/model/entity/follow_request.rs new file mode 100644 index 000000000..6f8b00b79 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/follow_request.rs @@ -0,0 +1,60 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "follow_request")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "followeeId")] + pub followee_id: String, + #[sea_orm(column_name = "followerId")] + pub follower_id: String, + #[sea_orm(column_name = "requestId")] + pub request_id: Option, + #[sea_orm(column_name = "followerHost")] + pub follower_host: Option, + #[sea_orm(column_name = "followerInbox")] + pub follower_inbox: Option, + #[sea_orm(column_name = "followerSharedInbox")] + pub follower_shared_inbox: Option, + #[sea_orm(column_name = "followeeHost")] + pub followee_host: Option, + #[sea_orm(column_name = "followeeInbox")] + pub followee_inbox: Option, + #[sea_orm(column_name = "followeeSharedInbox")] + pub followee_shared_inbox: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::notification::Entity")] + Notification, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::FolloweeId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User2, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::FollowerId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User1, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Notification.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/following.rs b/packages/backend/native-utils/src/model/entity/following.rs new file mode 100644 index 000000000..641e41530 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/following.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "following")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "followeeId")] + pub followee_id: String, + #[sea_orm(column_name = "followerId")] + pub follower_id: String, + #[sea_orm(column_name = "followerHost")] + pub follower_host: Option, + #[sea_orm(column_name = "followerInbox")] + pub follower_inbox: Option, + #[sea_orm(column_name = "followerSharedInbox")] + pub follower_shared_inbox: Option, + #[sea_orm(column_name = "followeeHost")] + pub followee_host: Option, + #[sea_orm(column_name = "followeeInbox")] + pub followee_inbox: Option, + #[sea_orm(column_name = "followeeSharedInbox")] + pub followee_shared_inbox: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::FolloweeId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User2, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::FollowerId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User1, +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/gallery_like.rs b/packages/backend/native-utils/src/model/entity/gallery_like.rs new file mode 100644 index 000000000..e90dfedb3 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/gallery_like.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "gallery_like")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "postId")] + pub post_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::gallery_post::Entity", + from = "Column::PostId", + to = "super::gallery_post::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + GalleryPost, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::GalleryPost.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/gallery_post.rs b/packages/backend/native-utils/src/model/entity/gallery_post.rs new file mode 100644 index 000000000..7e53e6bf3 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/gallery_post.rs @@ -0,0 +1,55 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "gallery_post")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "updatedAt")] + pub updated_at: DateTimeWithTimeZone, + pub title: String, + pub description: Option, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "fileIds")] + pub file_ids: StringVec, + #[sea_orm(column_name = "isSensitive")] + pub is_sensitive: bool, + #[sea_orm(column_name = "likedCount")] + pub liked_count: i32, + pub tags: StringVec, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::gallery_like::Entity")] + GalleryLike, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::GalleryLike.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/hashtag.rs b/packages/backend/native-utils/src/model/entity/hashtag.rs new file mode 100644 index 000000000..7a8722a5f --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/hashtag.rs @@ -0,0 +1,42 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "hashtag")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub name: String, + #[sea_orm(column_name = "mentionedUserIds")] + pub mentioned_user_ids: StringVec, + #[sea_orm(column_name = "mentionedUsersCount")] + pub mentioned_users_count: i32, + #[sea_orm(column_name = "mentionedLocalUserIds")] + pub mentioned_local_user_ids: StringVec, + #[sea_orm(column_name = "mentionedLocalUsersCount")] + pub mentioned_local_users_count: i32, + #[sea_orm(column_name = "mentionedRemoteUserIds")] + pub mentioned_remote_user_ids: StringVec, + #[sea_orm(column_name = "mentionedRemoteUsersCount")] + pub mentioned_remote_users_count: i32, + #[sea_orm(column_name = "attachedUserIds")] + pub attached_user_ids: StringVec, + #[sea_orm(column_name = "attachedUsersCount")] + pub attached_users_count: i32, + #[sea_orm(column_name = "attachedLocalUserIds")] + pub attached_local_user_ids: StringVec, + #[sea_orm(column_name = "attachedLocalUsersCount")] + pub attached_local_users_count: i32, + #[sea_orm(column_name = "attachedRemoteUserIds")] + pub attached_remote_user_ids: StringVec, + #[sea_orm(column_name = "attachedRemoteUsersCount")] + pub attached_remote_users_count: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/instance.rs b/packages/backend/native-utils/src/model/entity/instance.rs new file mode 100644 index 000000000..fc9c5bf8b --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/instance.rs @@ -0,0 +1,58 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "instance")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "caughtAt")] + pub caught_at: DateTimeWithTimeZone, + pub host: String, + #[sea_orm(column_name = "usersCount")] + pub users_count: i32, + #[sea_orm(column_name = "notesCount")] + pub notes_count: i32, + #[sea_orm(column_name = "followingCount")] + pub following_count: i32, + #[sea_orm(column_name = "followersCount")] + pub followers_count: i32, + #[sea_orm(column_name = "latestRequestSentAt")] + pub latest_request_sent_at: Option, + #[sea_orm(column_name = "latestStatus")] + pub latest_status: Option, + #[sea_orm(column_name = "latestRequestReceivedAt")] + pub latest_request_received_at: Option, + #[sea_orm(column_name = "lastCommunicatedAt")] + pub last_communicated_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "isNotResponding")] + pub is_not_responding: bool, + #[sea_orm(column_name = "softwareName")] + pub software_name: Option, + #[sea_orm(column_name = "softwareVersion")] + pub software_version: Option, + #[sea_orm(column_name = "openRegistrations")] + pub open_registrations: Option, + pub name: Option, + pub description: Option, + #[sea_orm(column_name = "maintainerName")] + pub maintainer_name: Option, + #[sea_orm(column_name = "maintainerEmail")] + pub maintainer_email: Option, + #[sea_orm(column_name = "infoUpdatedAt")] + pub info_updated_at: Option, + #[sea_orm(column_name = "isSuspended")] + pub is_suspended: bool, + #[sea_orm(column_name = "iconUrl")] + pub icon_url: Option, + #[sea_orm(column_name = "themeColor")] + pub theme_color: Option, + #[sea_orm(column_name = "faviconUrl")] + pub favicon_url: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/messaging_message.rs b/packages/backend/native-utils/src/model/entity/messaging_message.rs new file mode 100644 index 000000000..8d7c7b8cc --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/messaging_message.rs @@ -0,0 +1,77 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "messaging_message")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "recipientId")] + pub recipient_id: Option, + pub text: Option, + #[sea_orm(column_name = "isRead")] + pub is_read: bool, + #[sea_orm(column_name = "fileId")] + pub file_id: Option, + #[sea_orm(column_name = "groupId")] + pub group_id: Option, + pub reads: StringVec, + pub uri: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::drive_file::Entity", + from = "Column::FileId", + to = "super::drive_file::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + DriveFile, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User2, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::RecipientId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User1, + #[sea_orm( + belongs_to = "super::user_group::Entity", + from = "Column::GroupId", + to = "super::user_group::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + UserGroup, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::DriveFile.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroup.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/meta.rs b/packages/backend/native-utils/src/model/entity/meta.rs new file mode 100644 index 000000000..2c0dc315c --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/meta.rs @@ -0,0 +1,212 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use super::sea_orm_active_enums::MetaSensitivemediadetectionEnum; +use super::sea_orm_active_enums::MetaSensitivemediadetectionsensitivityEnum; +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "meta")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub name: Option, + pub description: Option, + #[sea_orm(column_name = "maintainerName")] + pub maintainer_name: Option, + #[sea_orm(column_name = "maintainerEmail")] + pub maintainer_email: Option, + #[sea_orm(column_name = "disableRegistration")] + pub disable_registration: bool, + #[sea_orm(column_name = "disableLocalTimeline")] + pub disable_local_timeline: bool, + #[sea_orm(column_name = "disableGlobalTimeline")] + pub disable_global_timeline: bool, + #[sea_orm(column_name = "useStarForReactionFallback")] + pub use_star_for_reaction_fallback: bool, + pub langs: StringVec, + #[sea_orm(column_name = "hiddenTags")] + pub hidden_tags: StringVec, + #[sea_orm(column_name = "blockedHosts")] + pub blocked_hosts: StringVec, + #[sea_orm(column_name = "mascotImageUrl")] + pub mascot_image_url: Option, + #[sea_orm(column_name = "bannerUrl")] + pub banner_url: Option, + #[sea_orm(column_name = "errorImageUrl")] + pub error_image_url: Option, + #[sea_orm(column_name = "iconUrl")] + pub icon_url: Option, + #[sea_orm(column_name = "cacheRemoteFiles")] + pub cache_remote_files: bool, + #[sea_orm(column_name = "enableRecaptcha")] + pub enable_recaptcha: bool, + #[sea_orm(column_name = "recaptchaSiteKey")] + pub recaptcha_site_key: Option, + #[sea_orm(column_name = "recaptchaSecretKey")] + pub recaptcha_secret_key: Option, + #[sea_orm(column_name = "localDriveCapacityMb")] + pub local_drive_capacity_mb: i32, + #[sea_orm(column_name = "remoteDriveCapacityMb")] + pub remote_drive_capacity_mb: i32, + #[sea_orm(column_name = "summalyProxy")] + pub summaly_proxy: Option, + #[sea_orm(column_name = "enableEmail")] + pub enable_email: bool, + pub email: Option, + #[sea_orm(column_name = "smtpSecure")] + pub smtp_secure: bool, + #[sea_orm(column_name = "smtpHost")] + pub smtp_host: Option, + #[sea_orm(column_name = "smtpPort")] + pub smtp_port: Option, + #[sea_orm(column_name = "smtpUser")] + pub smtp_user: Option, + #[sea_orm(column_name = "smtpPass")] + pub smtp_pass: Option, + #[sea_orm(column_name = "enableServiceWorker")] + pub enable_service_worker: bool, + #[sea_orm(column_name = "swPublicKey")] + pub sw_public_key: Option, + #[sea_orm(column_name = "swPrivateKey")] + pub sw_private_key: Option, + #[sea_orm(column_name = "enableTwitterIntegration")] + pub enable_twitter_integration: bool, + #[sea_orm(column_name = "twitterConsumerKey")] + pub twitter_consumer_key: Option, + #[sea_orm(column_name = "twitterConsumerSecret")] + pub twitter_consumer_secret: Option, + #[sea_orm(column_name = "enableGithubIntegration")] + pub enable_github_integration: bool, + #[sea_orm(column_name = "githubClientId")] + pub github_client_id: Option, + #[sea_orm(column_name = "githubClientSecret")] + pub github_client_secret: Option, + #[sea_orm(column_name = "enableDiscordIntegration")] + pub enable_discord_integration: bool, + #[sea_orm(column_name = "discordClientId")] + pub discord_client_id: Option, + #[sea_orm(column_name = "discordClientSecret")] + pub discord_client_secret: Option, + #[sea_orm(column_name = "pinnedUsers")] + pub pinned_users: StringVec, + #[sea_orm(column_name = "ToSUrl")] + pub to_s_url: Option, + #[sea_orm(column_name = "repositoryUrl")] + pub repository_url: String, + #[sea_orm(column_name = "feedbackUrl")] + pub feedback_url: Option, + #[sea_orm(column_name = "useObjectStorage")] + pub use_object_storage: bool, + #[sea_orm(column_name = "objectStorageBucket")] + pub object_storage_bucket: Option, + #[sea_orm(column_name = "objectStoragePrefix")] + pub object_storage_prefix: Option, + #[sea_orm(column_name = "objectStorageBaseUrl")] + pub object_storage_base_url: Option, + #[sea_orm(column_name = "objectStorageEndpoint")] + pub object_storage_endpoint: Option, + #[sea_orm(column_name = "objectStorageRegion")] + pub object_storage_region: Option, + #[sea_orm(column_name = "objectStorageAccessKey")] + pub object_storage_access_key: Option, + #[sea_orm(column_name = "objectStorageSecretKey")] + pub object_storage_secret_key: Option, + #[sea_orm(column_name = "objectStoragePort")] + pub object_storage_port: Option, + #[sea_orm(column_name = "objectStorageUseSSL")] + pub object_storage_use_ssl: bool, + #[sea_orm(column_name = "proxyAccountId")] + pub proxy_account_id: Option, + #[sea_orm(column_name = "objectStorageUseProxy")] + pub object_storage_use_proxy: bool, + #[sea_orm(column_name = "enableHcaptcha")] + pub enable_hcaptcha: bool, + #[sea_orm(column_name = "hcaptchaSiteKey")] + pub hcaptcha_site_key: Option, + #[sea_orm(column_name = "hcaptchaSecretKey")] + pub hcaptcha_secret_key: Option, + #[sea_orm(column_name = "objectStorageSetPublicRead")] + pub object_storage_set_public_read: bool, + #[sea_orm(column_name = "pinnedPages")] + pub pinned_pages: StringVec, + #[sea_orm(column_name = "backgroundImageUrl")] + pub background_image_url: Option, + #[sea_orm(column_name = "logoImageUrl")] + pub logo_image_url: Option, + #[sea_orm(column_name = "pinnedClipId")] + pub pinned_clip_id: Option, + #[sea_orm(column_name = "objectStorageS3ForcePathStyle")] + pub object_storage_s3_force_path_style: bool, + #[sea_orm(column_name = "allowedHosts")] + pub allowed_hosts: Option, + #[sea_orm(column_name = "secureMode")] + pub secure_mode: Option, + #[sea_orm(column_name = "privateMode")] + pub private_mode: Option, + #[sea_orm(column_name = "deeplAuthKey")] + pub deepl_auth_key: Option, + #[sea_orm(column_name = "deeplIsPro")] + pub deepl_is_pro: bool, + #[sea_orm(column_name = "emailRequiredForSignup")] + pub email_required_for_signup: bool, + #[sea_orm(column_name = "themeColor")] + pub theme_color: Option, + #[sea_orm(column_name = "defaultLightTheme")] + pub default_light_theme: Option, + #[sea_orm(column_name = "defaultDarkTheme")] + pub default_dark_theme: Option, + #[sea_orm(column_name = "sensitiveMediaDetection")] + pub sensitive_media_detection: MetaSensitivemediadetectionEnum, + #[sea_orm(column_name = "sensitiveMediaDetectionSensitivity")] + pub sensitive_media_detection_sensitivity: MetaSensitivemediadetectionsensitivityEnum, + #[sea_orm(column_name = "setSensitiveFlagAutomatically")] + pub set_sensitive_flag_automatically: bool, + #[sea_orm(column_name = "enableIpLogging")] + pub enable_ip_logging: bool, + #[sea_orm(column_name = "enableSensitiveMediaDetectionForVideos")] + pub enable_sensitive_media_detection_for_videos: bool, + #[sea_orm(column_name = "enableActiveEmailValidation")] + pub enable_active_email_validation: bool, + #[sea_orm(column_name = "customMOTD")] + pub custom_motd: StringVec, + #[sea_orm(column_name = "customSplashIcons")] + pub custom_splash_icons: StringVec, + #[sea_orm(column_name = "disableRecommendedTimeline")] + pub disable_recommended_timeline: bool, + #[sea_orm(column_name = "recommendedInstances")] + pub recommended_instances: StringVec, + #[sea_orm(column_name = "enableGuestTimeline")] + pub enable_guest_timeline: bool, + #[sea_orm(column_name = "defaultReaction")] + pub default_reaction: String, + #[sea_orm(column_name = "libreTranslateApiUrl")] + pub libre_translate_api_url: Option, + #[sea_orm(column_name = "libreTranslateApiKey")] + pub libre_translate_api_key: Option, + #[sea_orm(column_name = "silencedHosts")] + pub silenced_hosts: StringVec, + #[sea_orm(column_name = "experimentalFeatures", column_type = "JsonBinary")] + pub experimental_features: Json, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::ProxyAccountId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "SetNull" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/migrations.rs b/packages/backend/native-utils/src/model/entity/migrations.rs new file mode 100644 index 000000000..54e44f2fd --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/migrations.rs @@ -0,0 +1,17 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "migrations")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub timestamp: i64, + pub name: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/moderation_log.rs b/packages/backend/native-utils/src/model/entity/moderation_log.rs new file mode 100644 index 000000000..eb882b896 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/moderation_log.rs @@ -0,0 +1,37 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "moderation_log")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + pub r#type: String, + #[sea_orm(column_type = "JsonBinary")] + pub info: Json, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/muted_note.rs b/packages/backend/native-utils/src/model/entity/muted_note.rs new file mode 100644 index 000000000..238898549 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/muted_note.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use super::sea_orm_active_enums::MutedNoteReasonEnum; +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "muted_note")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, + #[sea_orm(column_name = "userId")] + pub user_id: String, + pub reason: MutedNoteReasonEnum, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/muting.rs b/packages/backend/native-utils/src/model/entity/muting.rs new file mode 100644 index 000000000..7b46a0b24 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/muting.rs @@ -0,0 +1,40 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "muting")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "muteeId")] + pub mutee_id: String, + #[sea_orm(column_name = "muterId")] + pub muter_id: String, + #[sea_orm(column_name = "expiresAt")] + pub expires_at: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::MuterId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User2, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::MuteeId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User1, +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/newtype/macros.rs b/packages/backend/native-utils/src/model/entity/newtype/macros.rs new file mode 100644 index 000000000..4b05c2c99 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/newtype/macros.rs @@ -0,0 +1,51 @@ +#[macro_export] +macro_rules! impl_json_newtype { + ($a:tt) => { + impl From<$a> for Value { + fn from(source: $a) -> Self { + Value::Json(serde_json::to_value(source).ok().map(Box::new)) + } + } + + impl TryGetable for $a { + fn try_get_by( + res: &QueryResult, + idx: I, + ) -> Result { + let json_value: serde_json::Value = + res.try_get_by(idx).map_err(TryGetError::DbErr)?; + serde_json::from_value(json_value) + .map_err(|e| TryGetError::DbErr(DbErr::Json(e.to_string()))) + } + } + + impl sea_query::ValueType for $a { + fn try_from(v: Value) -> Result { + match v { + Value::Json(Some(x)) => Ok($a( + serde_json::from_value(*x).map_err(|_| sea_query::ValueTypeErr)? + )), + _ => Err(sea_query::ValueTypeErr), + } + } + + fn type_name() -> String { + stringify!($a).to_owned() + } + + fn array_type() -> sea_query::ArrayType { + sea_query::ArrayType::Json + } + + fn column_type() -> sea_query::ColumnType { + sea_query::ColumnType::JsonBinary + } + } + + impl sea_query::Nullable for $a { + fn null() -> Value { + Value::Json(None) + } + } + }; +} diff --git a/packages/backend/native-utils/src/model/entity/newtype/mod.rs b/packages/backend/native-utils/src/model/entity/newtype/mod.rs new file mode 100644 index 000000000..3dc2d7553 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/newtype/mod.rs @@ -0,0 +1,30 @@ +mod macros; + +use cfg_if::cfg_if; +use derive_more::{From, Into}; +use sea_orm::{sea_query, DbErr, QueryResult, TryGetError, TryGetable, Value}; +use serde::{Deserialize, Serialize}; + +use crate::impl_json_newtype; + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, From, Into, Default)] +pub struct JsonKeyword(pub Vec>); +impl_json_newtype!(JsonKeyword); + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, From, Into, Default)] +pub struct JsonStringVec(pub Vec); +impl_json_newtype!(JsonStringVec); + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, From, Into, Default)] +pub struct JsonI32Vec(pub Vec); +impl_json_newtype!(JsonI32Vec); + +cfg_if! { + if #[cfg(feature = "noarray")] { + pub type StringVec = JsonStringVec; + pub type I32Vec = JsonI32Vec; + } else { + pub type StringVec = Vec; + pub type I32Vec = Vec; + } +} diff --git a/packages/backend/native-utils/src/model/entity/note.rs b/packages/backend/native-utils/src/model/entity/note.rs new file mode 100644 index 000000000..077841e48 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/note.rs @@ -0,0 +1,236 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use super::sea_orm_active_enums::NoteVisibilityEnum; +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "note")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "replyId")] + pub reply_id: Option, + #[sea_orm(column_name = "renoteId")] + pub renote_id: Option, + #[sea_orm(column_type = "Text", nullable)] + pub text: Option, + pub name: Option, + pub cw: Option, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "localOnly")] + pub local_only: bool, + #[sea_orm(column_name = "renoteCount")] + pub renote_count: i16, + #[sea_orm(column_name = "repliesCount")] + pub replies_count: i16, + #[sea_orm(column_type = "JsonBinary")] + pub reactions: Json, + pub visibility: NoteVisibilityEnum, + pub uri: Option, + pub score: i32, + #[sea_orm(column_name = "fileIds")] + pub file_ids: StringVec, + #[sea_orm(column_name = "attachedFileTypes")] + pub attached_file_types: StringVec, + #[sea_orm(column_name = "visibleUserIds")] + pub visible_user_ids: StringVec, + pub mentions: StringVec, + #[sea_orm(column_name = "mentionedRemoteUsers", column_type = "Text")] + pub mentioned_remote_users: String, + pub emojis: StringVec, + pub tags: StringVec, + #[sea_orm(column_name = "hasPoll")] + pub has_poll: bool, + #[sea_orm(column_name = "userHost")] + pub user_host: Option, + #[sea_orm(column_name = "replyUserId")] + pub reply_user_id: Option, + #[sea_orm(column_name = "replyUserHost")] + pub reply_user_host: Option, + #[sea_orm(column_name = "renoteUserId")] + pub renote_user_id: Option, + #[sea_orm(column_name = "renoteUserHost")] + pub renote_user_host: Option, + pub url: Option, + #[sea_orm(column_name = "channelId")] + pub channel_id: Option, + #[sea_orm(column_name = "threadId")] + pub thread_id: Option, + #[sea_orm(column_name = "updatedAt")] + pub updated_at: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::antenna_note::Entity")] + AntennaNote, + #[sea_orm( + belongs_to = "super::channel::Entity", + from = "Column::ChannelId", + to = "super::channel::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Channel, + #[sea_orm(has_many = "super::channel_note_pining::Entity")] + ChannelNotePining, + #[sea_orm(has_many = "super::clip_note::Entity")] + ClipNote, + #[sea_orm(has_many = "super::muted_note::Entity")] + MutedNote, + #[sea_orm( + belongs_to = "Entity", + from = "Column::ReplyId", + to = "Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + SelfRef2, + #[sea_orm( + belongs_to = "Entity", + from = "Column::RenoteId", + to = "Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + SelfRef1, + #[sea_orm(has_many = "super::note_edit::Entity")] + NoteEdit, + #[sea_orm(has_many = "super::note_favorite::Entity")] + NoteFavorite, + #[sea_orm(has_many = "super::note_reaction::Entity")] + NoteReaction, + #[sea_orm(has_many = "super::note_unread::Entity")] + NoteUnread, + #[sea_orm(has_many = "super::note_watching::Entity")] + NoteWatching, + #[sea_orm(has_many = "super::notification::Entity")] + Notification, + #[sea_orm(has_one = "super::poll::Entity")] + Poll, + #[sea_orm(has_many = "super::poll_vote::Entity")] + PollVote, + #[sea_orm(has_one = "super::promo_note::Entity")] + PromoNote, + #[sea_orm(has_many = "super::promo_read::Entity")] + PromoRead, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, + #[sea_orm(has_many = "super::user_note_pining::Entity")] + UserNotePining, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::AntennaNote.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Channel.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ChannelNotePining.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ClipNote.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::MutedNote.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteEdit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteFavorite.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteReaction.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteUnread.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteWatching.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Notification.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Poll.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::PollVote.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::PromoNote.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::PromoRead.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserNotePining.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/note_edit.rs b/packages/backend/native-utils/src/model/entity/note_edit.rs new file mode 100644 index 000000000..ea9b9eabd --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/note_edit.rs @@ -0,0 +1,41 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "note_edit")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, + #[sea_orm(column_type = "Text", nullable)] + pub text: Option, + pub cw: Option, + #[sea_orm(column_name = "fileIds")] + pub file_ids: StringVec, + #[sea_orm(column_name = "updatedAt")] + pub updated_at: DateTimeWithTimeZone, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/note_favorite.rs b/packages/backend/native-utils/src/model/entity/note_favorite.rs new file mode 100644 index 000000000..470ad55d2 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/note_favorite.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "note_favorite")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/note_reaction.rs b/packages/backend/native-utils/src/model/entity/note_reaction.rs new file mode 100644 index 000000000..a4e9f490d --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/note_reaction.rs @@ -0,0 +1,51 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "note_reaction")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, + pub reaction: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/note_thread_muting.rs b/packages/backend/native-utils/src/model/entity/note_thread_muting.rs new file mode 100644 index 000000000..51688a088 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/note_thread_muting.rs @@ -0,0 +1,36 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "note_thread_muting")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "threadId")] + pub thread_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/note_unread.rs b/packages/backend/native-utils/src/model/entity/note_unread.rs new file mode 100644 index 000000000..a444eb35d --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/note_unread.rs @@ -0,0 +1,56 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "note_unread")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, + #[sea_orm(column_name = "noteUserId")] + pub note_user_id: String, + #[sea_orm(column_name = "isSpecified")] + pub is_specified: bool, + #[sea_orm(column_name = "isMentioned")] + pub is_mentioned: bool, + #[sea_orm(column_name = "noteChannelId")] + pub note_channel_id: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/note_watching.rs b/packages/backend/native-utils/src/model/entity/note_watching.rs new file mode 100644 index 000000000..962ef081e --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/note_watching.rs @@ -0,0 +1,52 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "note_watching")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, + #[sea_orm(column_name = "noteUserId")] + pub note_user_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/notification.rs b/packages/backend/native-utils/src/model/entity/notification.rs new file mode 100644 index 000000000..896b6c2da --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/notification.rs @@ -0,0 +1,114 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use super::sea_orm_active_enums::NotificationTypeEnum; +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "notification")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "notifieeId")] + pub notifiee_id: String, + #[sea_orm(column_name = "notifierId")] + pub notifier_id: Option, + #[sea_orm(column_name = "isRead")] + pub is_read: bool, + #[sea_orm(column_name = "noteId")] + pub note_id: Option, + pub reaction: Option, + pub choice: Option, + #[sea_orm(column_name = "followRequestId")] + pub follow_request_id: Option, + pub r#type: NotificationTypeEnum, + #[sea_orm(column_name = "userGroupInvitationId")] + pub user_group_invitation_id: Option, + #[sea_orm(column_name = "customBody")] + pub custom_body: Option, + #[sea_orm(column_name = "customHeader")] + pub custom_header: Option, + #[sea_orm(column_name = "customIcon")] + pub custom_icon: Option, + #[sea_orm(column_name = "appAccessTokenId")] + pub app_access_token_id: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::access_token::Entity", + from = "Column::AppAccessTokenId", + to = "super::access_token::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + AccessToken, + #[sea_orm( + belongs_to = "super::follow_request::Entity", + from = "Column::FollowRequestId", + to = "super::follow_request::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + FollowRequest, + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::NotifierId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User2, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::NotifieeId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User1, + #[sea_orm( + belongs_to = "super::user_group_invitation::Entity", + from = "Column::UserGroupInvitationId", + to = "super::user_group_invitation::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + UserGroupInvitation, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::AccessToken.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FollowRequest.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroupInvitation.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/page.rs b/packages/backend/native-utils/src/model/entity/page.rs new file mode 100644 index 000000000..dabb5c9f0 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/page.rs @@ -0,0 +1,91 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use super::sea_orm_active_enums::PageVisibilityEnum; +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "page")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "updatedAt")] + pub updated_at: DateTimeWithTimeZone, + pub title: String, + pub name: String, + pub summary: Option, + #[sea_orm(column_name = "alignCenter")] + pub align_center: bool, + pub font: String, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "eyeCatchingImageId")] + pub eye_catching_image_id: Option, + #[sea_orm(column_type = "JsonBinary")] + pub content: Json, + #[sea_orm(column_type = "JsonBinary")] + pub variables: Json, + pub visibility: PageVisibilityEnum, + #[sea_orm(column_name = "visibleUserIds")] + pub visible_user_ids: StringVec, + #[sea_orm(column_name = "likedCount")] + pub liked_count: i32, + #[sea_orm(column_name = "hideTitleWhenPinned")] + pub hide_title_when_pinned: bool, + pub script: String, + #[sea_orm(column_name = "isPublic")] + pub is_public: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::drive_file::Entity", + from = "Column::EyeCatchingImageId", + to = "super::drive_file::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + DriveFile, + #[sea_orm(has_many = "super::page_like::Entity")] + PageLike, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, + #[sea_orm(has_one = "super::user_profile::Entity")] + UserProfile, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::DriveFile.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::PageLike.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserProfile.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/page_like.rs b/packages/backend/native-utils/src/model/entity/page_like.rs new file mode 100644 index 000000000..108b6b929 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/page_like.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "page_like")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "pageId")] + pub page_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::page::Entity", + from = "Column::PageId", + to = "super::page::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Page, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Page.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/password_reset_request.rs b/packages/backend/native-utils/src/model/entity/password_reset_request.rs new file mode 100644 index 000000000..45cc3de10 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/password_reset_request.rs @@ -0,0 +1,35 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "password_reset_request")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + pub token: String, + #[sea_orm(column_name = "userId")] + pub user_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/poll.rs b/packages/backend/native-utils/src/model/entity/poll.rs new file mode 100644 index 000000000..4d64594c7 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/poll.rs @@ -0,0 +1,44 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use super::sea_orm_active_enums::PollNotevisibilityEnum; +use sea_orm::entity::prelude::*; + +use super::newtype::{I32Vec, StringVec}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "poll")] +pub struct Model { + #[sea_orm(column_name = "noteId", primary_key, auto_increment = false, unique)] + pub note_id: String, + #[sea_orm(column_name = "expiresAt")] + pub expires_at: Option, + pub multiple: bool, + pub choices: StringVec, + pub votes: I32Vec, + #[sea_orm(column_name = "noteVisibility")] + pub note_visibility: PollNotevisibilityEnum, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "userHost")] + pub user_host: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/poll_vote.rs b/packages/backend/native-utils/src/model/entity/poll_vote.rs new file mode 100644 index 000000000..bf26bf5dd --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/poll_vote.rs @@ -0,0 +1,51 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "poll_vote")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, + pub choice: i32, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/prelude.rs b/packages/backend/native-utils/src/model/entity/prelude.rs new file mode 100644 index 000000000..8be696cb4 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/prelude.rs @@ -0,0 +1,70 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +pub use super::abuse_user_report::Entity as AbuseUserReport; +pub use super::access_token::Entity as AccessToken; +pub use super::ad::Entity as Ad; +pub use super::announcement::Entity as Announcement; +pub use super::announcement_read::Entity as AnnouncementRead; +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::attestation_challenge::Entity as AttestationChallenge; +pub use super::auth_session::Entity as AuthSession; +pub use super::blocking::Entity as Blocking; +pub use super::channel::Entity as Channel; +pub use super::channel_following::Entity as ChannelFollowing; +pub use super::channel_note_pining::Entity as ChannelNotePining; +pub use super::clip::Entity as Clip; +pub use super::clip_note::Entity as ClipNote; +pub use super::drive_file::Entity as DriveFile; +pub use super::drive_folder::Entity as DriveFolder; +pub use super::emoji::Entity as Emoji; +pub use super::follow_request::Entity as FollowRequest; +pub use super::following::Entity as Following; +pub use super::gallery_like::Entity as GalleryLike; +pub use super::gallery_post::Entity as GalleryPost; +pub use super::hashtag::Entity as Hashtag; +pub use super::instance::Entity as Instance; +pub use super::messaging_message::Entity as MessagingMessage; +pub use super::meta::Entity as Meta; +pub use super::migrations::Entity as Migrations; +pub use super::moderation_log::Entity as ModerationLog; +pub use super::muted_note::Entity as MutedNote; +pub use super::muting::Entity as Muting; +pub use super::note::Entity as Note; +pub use super::note_edit::Entity as NoteEdit; +pub use super::note_favorite::Entity as NoteFavorite; +pub use super::note_reaction::Entity as NoteReaction; +pub use super::note_thread_muting::Entity as NoteThreadMuting; +pub use super::note_unread::Entity as NoteUnread; +pub use super::note_watching::Entity as NoteWatching; +pub use super::notification::Entity as Notification; +pub use super::page::Entity as Page; +pub use super::page_like::Entity as PageLike; +pub use super::password_reset_request::Entity as PasswordResetRequest; +pub use super::poll::Entity as Poll; +pub use super::poll_vote::Entity as PollVote; +pub use super::promo_note::Entity as PromoNote; +pub use super::promo_read::Entity as PromoRead; +pub use super::registration_ticket::Entity as RegistrationTicket; +pub use super::registry_item::Entity as RegistryItem; +pub use super::relay::Entity as Relay; +pub use super::renote_muting::Entity as RenoteMuting; +pub use super::signin::Entity as Signin; +pub use super::sw_subscription::Entity as SwSubscription; +pub use super::used_username::Entity as UsedUsername; +pub use super::user::Entity as User; +pub use super::user_group::Entity as UserGroup; +pub use super::user_group_invitation::Entity as UserGroupInvitation; +pub use super::user_group_invite::Entity as UserGroupInvite; +pub use super::user_group_joining::Entity as UserGroupJoining; +pub use super::user_ip::Entity as UserIp; +pub use super::user_keypair::Entity as UserKeypair; +pub use super::user_list::Entity as UserList; +pub use super::user_list_joining::Entity as UserListJoining; +pub use super::user_note_pining::Entity as UserNotePining; +pub use super::user_pending::Entity as UserPending; +pub use super::user_profile::Entity as UserProfile; +pub use super::user_publickey::Entity as UserPublickey; +pub use super::user_security_key::Entity as UserSecurityKey; +pub use super::webhook::Entity as Webhook; diff --git a/packages/backend/native-utils/src/model/entity/promo_note.rs b/packages/backend/native-utils/src/model/entity/promo_note.rs new file mode 100644 index 000000000..288a0ea81 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/promo_note.rs @@ -0,0 +1,34 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "promo_note")] +pub struct Model { + #[sea_orm(column_name = "noteId", primary_key, auto_increment = false, unique)] + pub note_id: String, + #[sea_orm(column_name = "expiresAt")] + pub expires_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/promo_read.rs b/packages/backend/native-utils/src/model/entity/promo_read.rs new file mode 100644 index 000000000..4e6224cf2 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/promo_read.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "promo_read")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/registration_ticket.rs b/packages/backend/native-utils/src/model/entity/registration_ticket.rs new file mode 100644 index 000000000..798f19586 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/registration_ticket.rs @@ -0,0 +1,18 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "registration_ticket")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + pub code: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/registry_item.rs b/packages/backend/native-utils/src/model/entity/registry_item.rs new file mode 100644 index 000000000..904c43abf --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/registry_item.rs @@ -0,0 +1,43 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "registry_item")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "updatedAt")] + pub updated_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + pub key: String, + pub scope: StringVec, + pub domain: Option, + #[sea_orm(column_type = "JsonBinary", nullable)] + pub value: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/relay.rs b/packages/backend/native-utils/src/model/entity/relay.rs new file mode 100644 index 000000000..bed89c849 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/relay.rs @@ -0,0 +1,18 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use super::sea_orm_active_enums::RelayStatusEnum; +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "relay")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + pub inbox: String, + pub status: RelayStatusEnum, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/renote_muting.rs b/packages/backend/native-utils/src/model/entity/renote_muting.rs new file mode 100644 index 000000000..44751c14c --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/renote_muting.rs @@ -0,0 +1,21 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "renote_muting")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "muteeId")] + pub mutee_id: String, + #[sea_orm(column_name = "muterId")] + pub muter_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/sea_orm_active_enums.rs b/packages/backend/native-utils/src/model/entity/sea_orm_active_enums.rs new file mode 100644 index 000000000..f26995224 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/sea_orm_active_enums.rs @@ -0,0 +1,184 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Default)] +#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "antenna_src_enum")] +pub enum AntennaSrcEnum { + #[default] + #[sea_orm(string_value = "all")] + All, + #[sea_orm(string_value = "group")] + Group, + #[sea_orm(string_value = "home")] + Home, + #[sea_orm(string_value = "instances")] + Instances, + #[sea_orm(string_value = "list")] + List, + #[sea_orm(string_value = "users")] + Users, +} +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Default)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "meta_sensitivemediadetection_enum" +)] +pub enum MetaSensitivemediadetectionEnum { + #[default] + #[sea_orm(string_value = "all")] + All, + #[sea_orm(string_value = "local")] + Local, + #[sea_orm(string_value = "none")] + None, + #[sea_orm(string_value = "remote")] + Remote, +} +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Default)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "meta_sensitivemediadetectionsensitivity_enum" +)] +pub enum MetaSensitivemediadetectionsensitivityEnum { + #[sea_orm(string_value = "high")] + High, + #[sea_orm(string_value = "low")] + Low, + #[default] + #[sea_orm(string_value = "medium")] + Medium, + #[sea_orm(string_value = "veryHigh")] + VeryHigh, + #[sea_orm(string_value = "veryLow")] + VeryLow, +} +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Default)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "muted_note_reason_enum" +)] +pub enum MutedNoteReasonEnum { + #[default] + #[sea_orm(string_value = "manual")] + Manual, + #[sea_orm(string_value = "other")] + Other, + #[sea_orm(string_value = "spam")] + Spam, + #[sea_orm(string_value = "word")] + Word, +} +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Default)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "note_visibility_enum" +)] +pub enum NoteVisibilityEnum { + #[sea_orm(string_value = "followers")] + Followers, + #[sea_orm(string_value = "hidden")] + Hidden, + #[sea_orm(string_value = "home")] + Home, + #[default] + #[sea_orm(string_value = "public")] + Public, + #[sea_orm(string_value = "specified")] + Specified, +} +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Default)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "notification_type_enum" +)] +pub enum NotificationTypeEnum { + #[sea_orm(string_value = "app")] + App, + #[sea_orm(string_value = "follow")] + Follow, + #[sea_orm(string_value = "followRequestAccepted")] + FollowRequestAccepted, + #[sea_orm(string_value = "groupInvited")] + GroupInvited, + #[sea_orm(string_value = "mention")] + Mention, + #[sea_orm(string_value = "pollEnded")] + PollEnded, + #[sea_orm(string_value = "pollVote")] + PollVote, + #[sea_orm(string_value = "quote")] + Quote, + #[sea_orm(string_value = "reaction")] + Reaction, + #[sea_orm(string_value = "receiveFollowRequest")] + ReceiveFollowRequest, + #[sea_orm(string_value = "renote")] + Renote, + #[default] + #[sea_orm(string_value = "reply")] + Reply, +} +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Default)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "page_visibility_enum" +)] +pub enum PageVisibilityEnum { + #[sea_orm(string_value = "followers")] + Followers, + #[default] + #[sea_orm(string_value = "public")] + Public, + #[sea_orm(string_value = "specified")] + Specified, +} +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Default)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "poll_notevisibility_enum" +)] +pub enum PollNotevisibilityEnum { + #[sea_orm(string_value = "followers")] + Followers, + #[sea_orm(string_value = "home")] + Home, + #[default] + #[sea_orm(string_value = "public")] + Public, + #[sea_orm(string_value = "specified")] + Specified, +} +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Default)] +#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "relay_status_enum")] +pub enum RelayStatusEnum { + #[sea_orm(string_value = "accepted")] + Accepted, + #[sea_orm(string_value = "rejected")] + Rejected, + #[default] + #[sea_orm(string_value = "requesting")] + Requesting, +} +#[derive(Debug, Clone, PartialEq, Eq, EnumIter, DeriveActiveEnum, Default)] +#[sea_orm( + rs_type = "String", + db_type = "Enum", + enum_name = "user_profile_ffvisibility_enum" +)] +pub enum UserProfileFfvisibilityEnum { + #[sea_orm(string_value = "followers")] + Followers, + #[sea_orm(string_value = "private")] + Private, + #[default] + #[sea_orm(string_value = "public")] + Public, +} diff --git a/packages/backend/native-utils/src/model/entity/signin.rs b/packages/backend/native-utils/src/model/entity/signin.rs new file mode 100644 index 000000000..60bbc33d2 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/signin.rs @@ -0,0 +1,38 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "signin")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + pub ip: String, + #[sea_orm(column_type = "JsonBinary")] + pub headers: Json, + pub success: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/sw_subscription.rs b/packages/backend/native-utils/src/model/entity/sw_subscription.rs new file mode 100644 index 000000000..1be9e046a --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/sw_subscription.rs @@ -0,0 +1,39 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "sw_subscription")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + pub endpoint: String, + pub auth: String, + pub publickey: String, + #[sea_orm(column_name = "sendReadMessage")] + pub send_read_message: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/used_username.rs b/packages/backend/native-utils/src/model/entity/used_username.rs new file mode 100644 index 000000000..620950b64 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/used_username.rs @@ -0,0 +1,17 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "used_username")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub username: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user.rs b/packages/backend/native-utils/src/model/entity/user.rs new file mode 100644 index 000000000..f30fd8ace --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user.rs @@ -0,0 +1,426 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "updatedAt")] + pub updated_at: Option, + #[sea_orm(column_name = "lastFetchedAt")] + pub last_fetched_at: Option, + pub username: String, + #[sea_orm(column_name = "usernameLower")] + pub username_lower: String, + pub name: Option, + #[sea_orm(column_name = "followersCount")] + pub followers_count: i32, + #[sea_orm(column_name = "followingCount")] + pub following_count: i32, + #[sea_orm(column_name = "notesCount")] + pub notes_count: i32, + #[sea_orm(column_name = "avatarId", unique)] + pub avatar_id: Option, + #[sea_orm(column_name = "bannerId", unique)] + pub banner_id: Option, + pub tags: StringVec, + #[sea_orm(column_name = "isSuspended")] + pub is_suspended: bool, + #[sea_orm(column_name = "isSilenced")] + pub is_silenced: bool, + #[sea_orm(column_name = "isLocked")] + pub is_locked: bool, + #[sea_orm(column_name = "isBot")] + pub is_bot: bool, + #[sea_orm(column_name = "isCat")] + pub is_cat: bool, + #[sea_orm(column_name = "isAdmin")] + pub is_admin: bool, + #[sea_orm(column_name = "isModerator")] + pub is_moderator: bool, + pub emojis: StringVec, + pub host: Option, + pub inbox: Option, + #[sea_orm(column_name = "sharedInbox")] + pub shared_inbox: Option, + pub featured: Option, + pub uri: Option, + #[sea_orm(unique)] + pub token: Option, + #[sea_orm(column_name = "isExplorable")] + pub is_explorable: bool, + #[sea_orm(column_name = "followersUri")] + pub followers_uri: Option, + #[sea_orm(column_name = "lastActiveDate")] + pub last_active_date: Option, + #[sea_orm(column_name = "hideOnlineStatus")] + pub hide_online_status: bool, + #[sea_orm(column_name = "isDeleted")] + pub is_deleted: bool, + #[sea_orm(column_name = "showTimelineReplies")] + pub show_timeline_replies: bool, + #[sea_orm(column_name = "driveCapacityOverrideMb")] + pub drive_capacity_override_mb: Option, + #[sea_orm(column_name = "movedToUri")] + pub moved_to_uri: Option, + #[sea_orm(column_name = "alsoKnownAs", column_type = "Text", nullable)] + pub also_known_as: Option, + #[sea_orm(column_name = "speakAsCat")] + pub speak_as_cat: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::access_token::Entity")] + AccessToken, + #[sea_orm(has_many = "super::announcement_read::Entity")] + AnnouncementRead, + #[sea_orm(has_many = "super::antenna::Entity")] + Antenna, + #[sea_orm(has_many = "super::app::Entity")] + App, + #[sea_orm(has_many = "super::attestation_challenge::Entity")] + AttestationChallenge, + #[sea_orm(has_many = "super::auth_session::Entity")] + AuthSession, + #[sea_orm(has_many = "super::channel::Entity")] + Channel, + #[sea_orm(has_many = "super::channel_following::Entity")] + ChannelFollowing, + #[sea_orm(has_many = "super::clip::Entity")] + Clip, + #[sea_orm( + belongs_to = "super::drive_file::Entity", + from = "Column::AvatarId", + to = "super::drive_file::Column::Id", + on_update = "NoAction", + on_delete = "SetNull" + )] + DriveFile2, + #[sea_orm( + belongs_to = "super::drive_file::Entity", + from = "Column::BannerId", + to = "super::drive_file::Column::Id", + on_update = "NoAction", + on_delete = "SetNull" + )] + DriveFile1, + #[sea_orm(has_many = "super::drive_folder::Entity")] + DriveFolder, + #[sea_orm(has_many = "super::gallery_like::Entity")] + GalleryLike, + #[sea_orm(has_many = "super::gallery_post::Entity")] + GalleryPost, + #[sea_orm(has_many = "super::meta::Entity")] + Meta, + #[sea_orm(has_many = "super::moderation_log::Entity")] + ModerationLog, + #[sea_orm(has_many = "super::muted_note::Entity")] + MutedNote, + #[sea_orm(has_many = "super::note::Entity")] + Note, + #[sea_orm(has_many = "super::note_favorite::Entity")] + NoteFavorite, + #[sea_orm(has_many = "super::note_reaction::Entity")] + NoteReaction, + #[sea_orm(has_many = "super::note_thread_muting::Entity")] + NoteThreadMuting, + #[sea_orm(has_many = "super::note_unread::Entity")] + NoteUnread, + #[sea_orm(has_many = "super::note_watching::Entity")] + NoteWatching, + #[sea_orm(has_many = "super::page::Entity")] + Page, + #[sea_orm(has_many = "super::page_like::Entity")] + PageLike, + #[sea_orm(has_many = "super::password_reset_request::Entity")] + PasswordResetRequest, + #[sea_orm(has_many = "super::poll_vote::Entity")] + PollVote, + #[sea_orm(has_many = "super::promo_read::Entity")] + PromoRead, + #[sea_orm(has_many = "super::registry_item::Entity")] + RegistryItem, + #[sea_orm(has_many = "super::signin::Entity")] + Signin, + #[sea_orm(has_many = "super::sw_subscription::Entity")] + SwSubscription, + #[sea_orm(has_many = "super::user_group::Entity")] + UserGroup, + #[sea_orm(has_many = "super::user_group_invitation::Entity")] + UserGroupInvitation, + #[sea_orm(has_many = "super::user_group_invite::Entity")] + UserGroupInvite, + #[sea_orm(has_many = "super::user_group_joining::Entity")] + UserGroupJoining, + #[sea_orm(has_one = "super::user_keypair::Entity")] + UserKeypair, + #[sea_orm(has_many = "super::user_list::Entity")] + UserList, + #[sea_orm(has_many = "super::user_list_joining::Entity")] + UserListJoining, + #[sea_orm(has_many = "super::user_note_pining::Entity")] + UserNotePining, + #[sea_orm(has_one = "super::user_profile::Entity")] + UserProfile, + #[sea_orm(has_one = "super::user_publickey::Entity")] + UserPublickey, + #[sea_orm(has_many = "super::user_security_key::Entity")] + UserSecurityKey, + #[sea_orm(has_many = "super::webhook::Entity")] + Webhook, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::AccessToken.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::AnnouncementRead.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Antenna.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::App.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::AttestationChallenge.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::AuthSession.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Channel.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ChannelFollowing.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Clip.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::DriveFolder.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::GalleryLike.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::GalleryPost.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Meta.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ModerationLog.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::MutedNote.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteFavorite.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteReaction.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteThreadMuting.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteUnread.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::NoteWatching.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Page.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::PageLike.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::PasswordResetRequest.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::PollVote.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::PromoRead.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::RegistryItem.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Signin.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::SwSubscription.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroup.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroupInvitation.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroupInvite.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroupJoining.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserKeypair.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserList.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserListJoining.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserNotePining.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserProfile.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserPublickey.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserSecurityKey.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Webhook.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_group.rs b/packages/backend/native-utils/src/model/entity/user_group.rs new file mode 100644 index 000000000..74ee4f22f --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_group.rs @@ -0,0 +1,69 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_group")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + pub name: String, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "isPrivate")] + pub is_private: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::messaging_message::Entity")] + MessagingMessage, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, + #[sea_orm(has_many = "super::user_group_invitation::Entity")] + UserGroupInvitation, + #[sea_orm(has_many = "super::user_group_invite::Entity")] + UserGroupInvite, + #[sea_orm(has_many = "super::user_group_joining::Entity")] + UserGroupJoining, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::MessagingMessage.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroupInvitation.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroupInvite.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroupJoining.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_group_invitation.rs b/packages/backend/native-utils/src/model/entity/user_group_invitation.rs new file mode 100644 index 000000000..baa6fea83 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_group_invitation.rs @@ -0,0 +1,58 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_group_invitation")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "userGroupId")] + pub user_group_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::notification::Entity")] + Notification, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, + #[sea_orm( + belongs_to = "super::user_group::Entity", + from = "Column::UserGroupId", + to = "super::user_group::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + UserGroup, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Notification.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroup.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_group_invite.rs b/packages/backend/native-utils/src/model/entity/user_group_invite.rs new file mode 100644 index 000000000..dbbc055f0 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_group_invite.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_group_invite")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "userGroupId")] + pub user_group_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, + #[sea_orm( + belongs_to = "super::user_group::Entity", + from = "Column::UserGroupId", + to = "super::user_group::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + UserGroup, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroup.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_group_joining.rs b/packages/backend/native-utils/src/model/entity/user_group_joining.rs new file mode 100644 index 000000000..e7741520c --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_group_joining.rs @@ -0,0 +1,58 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_group_joining")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "userGroupId")] + pub user_group_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::antenna::Entity")] + Antenna, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, + #[sea_orm( + belongs_to = "super::user_group::Entity", + from = "Column::UserGroupId", + to = "super::user_group::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + UserGroup, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Antenna.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserGroup.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_ip.rs b/packages/backend/native-utils/src/model/entity/user_ip.rs new file mode 100644 index 000000000..ce0af264d --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_ip.rs @@ -0,0 +1,20 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_ip")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + pub ip: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_keypair.rs b/packages/backend/native-utils/src/model/entity/user_keypair.rs new file mode 100644 index 000000000..0382d5d76 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_keypair.rs @@ -0,0 +1,34 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_keypair")] +pub struct Model { + #[sea_orm(column_name = "userId", primary_key, auto_increment = false, unique)] + pub user_id: String, + #[sea_orm(column_name = "publicKey")] + pub public_key: String, + #[sea_orm(column_name = "privateKey")] + pub private_key: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_list.rs b/packages/backend/native-utils/src/model/entity/user_list.rs new file mode 100644 index 000000000..7cc972133 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_list.rs @@ -0,0 +1,51 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_list")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + pub name: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::antenna::Entity")] + Antenna, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, + #[sea_orm(has_many = "super::user_list_joining::Entity")] + UserListJoining, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Antenna.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserListJoining.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_list_joining.rs b/packages/backend/native-utils/src/model/entity/user_list_joining.rs new file mode 100644 index 000000000..4f28a21db --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_list_joining.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_list_joining")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "userListId")] + pub user_list_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, + #[sea_orm( + belongs_to = "super::user_list::Entity", + from = "Column::UserListId", + to = "super::user_list::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + UserList, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::UserList.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_note_pining.rs b/packages/backend/native-utils/src/model/entity/user_note_pining.rs new file mode 100644 index 000000000..e657fcb53 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_note_pining.rs @@ -0,0 +1,50 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_note_pining")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "noteId")] + pub note_id: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::note::Entity", + from = "Column::NoteId", + to = "super::note::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + Note, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Note.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_pending.rs b/packages/backend/native-utils/src/model/entity/user_pending.rs new file mode 100644 index 000000000..297fe553c --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_pending.rs @@ -0,0 +1,21 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_pending")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + pub code: String, + pub username: String, + pub email: String, + pub password: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_profile.rs b/packages/backend/native-utils/src/model/entity/user_profile.rs new file mode 100644 index 000000000..4c2f903d4 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_profile.rs @@ -0,0 +1,112 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use super::sea_orm_active_enums::UserProfileFfvisibilityEnum; +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_profile")] +pub struct Model { + #[sea_orm(column_name = "userId", primary_key, auto_increment = false, unique)] + pub user_id: String, + pub location: Option, + pub birthday: Option, + pub description: Option, + #[sea_orm(column_type = "JsonBinary")] + pub fields: Json, + pub url: Option, + pub email: Option, + #[sea_orm(column_name = "emailVerifyCode")] + pub email_verify_code: Option, + #[sea_orm(column_name = "emailVerified")] + pub email_verified: bool, + #[sea_orm(column_name = "twoFactorTempSecret")] + pub two_factor_temp_secret: Option, + #[sea_orm(column_name = "twoFactorSecret")] + pub two_factor_secret: Option, + #[sea_orm(column_name = "twoFactorEnabled")] + pub two_factor_enabled: bool, + pub password: Option, + #[sea_orm(column_name = "clientData", column_type = "JsonBinary")] + pub client_data: Json, + #[sea_orm(column_name = "autoAcceptFollowed")] + pub auto_accept_followed: bool, + #[sea_orm(column_name = "alwaysMarkNsfw")] + pub always_mark_nsfw: bool, + #[sea_orm(column_name = "carefulBot")] + pub careful_bot: bool, + #[sea_orm(column_name = "userHost")] + pub user_host: Option, + #[sea_orm(column_name = "securityKeysAvailable")] + pub security_keys_available: bool, + #[sea_orm(column_name = "usePasswordLessLogin")] + pub use_password_less_login: bool, + #[sea_orm(column_name = "pinnedPageId", unique)] + pub pinned_page_id: Option, + #[sea_orm(column_type = "JsonBinary")] + pub room: Json, + #[sea_orm(column_type = "JsonBinary")] + pub integrations: Json, + #[sea_orm(column_name = "injectFeaturedNote")] + pub inject_featured_note: bool, + #[sea_orm(column_name = "enableWordMute")] + pub enable_word_mute: bool, + #[sea_orm(column_name = "mutedWords", column_type = "JsonBinary")] + pub muted_words: Json, + #[sea_orm(column_name = "mutingNotificationTypes")] + pub muting_notification_types: StringVec, + #[sea_orm(column_name = "noCrawle")] + pub no_crawle: bool, + #[sea_orm(column_name = "receiveAnnouncementEmail")] + pub receive_announcement_email: bool, + #[sea_orm(column_name = "emailNotificationTypes", column_type = "JsonBinary")] + pub email_notification_types: Json, + pub lang: Option, + #[sea_orm(column_name = "mutedInstances", column_type = "JsonBinary")] + pub muted_instances: Json, + #[sea_orm(column_name = "publicReactions")] + pub public_reactions: bool, + #[sea_orm(column_name = "ffVisibility")] + pub ff_visibility: UserProfileFfvisibilityEnum, + #[sea_orm(column_name = "autoSensitive")] + pub auto_sensitive: bool, + #[sea_orm(column_name = "moderationNote")] + pub moderation_note: String, + #[sea_orm(column_name = "preventAiLearning")] + pub prevent_ai_learning: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::page::Entity", + from = "Column::PinnedPageId", + to = "super::page::Column::Id", + on_update = "NoAction", + on_delete = "SetNull" + )] + Page, + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Page.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_publickey.rs b/packages/backend/native-utils/src/model/entity/user_publickey.rs new file mode 100644 index 000000000..b1f426c5b --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_publickey.rs @@ -0,0 +1,34 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_publickey")] +pub struct Model { + #[sea_orm(column_name = "userId", primary_key, auto_increment = false, unique)] + pub user_id: String, + #[sea_orm(column_name = "keyId")] + pub key_id: String, + #[sea_orm(column_name = "keyPem")] + pub key_pem: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/user_security_key.rs b/packages/backend/native-utils/src/model/entity/user_security_key.rs new file mode 100644 index 000000000..4bc976336 --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/user_security_key.rs @@ -0,0 +1,37 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "user_security_key")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "userId")] + pub user_id: String, + #[sea_orm(column_name = "publicKey")] + pub public_key: String, + #[sea_orm(column_name = "lastUsed")] + pub last_used: DateTimeWithTimeZone, + pub name: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/entity/webhook.rs b/packages/backend/native-utils/src/model/entity/webhook.rs new file mode 100644 index 000000000..06ea1516b --- /dev/null +++ b/packages/backend/native-utils/src/model/entity/webhook.rs @@ -0,0 +1,45 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3 + +use sea_orm::entity::prelude::*; + +use super::newtype::StringVec; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Default)] +#[sea_orm(table_name = "webhook")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub id: String, + #[sea_orm(column_name = "createdAt")] + pub created_at: DateTimeWithTimeZone, + #[sea_orm(column_name = "userId")] + pub user_id: String, + pub name: String, + pub on: StringVec, + pub url: String, + pub secret: String, + pub active: bool, + #[sea_orm(column_name = "latestSentAt")] + pub latest_sent_at: Option, + #[sea_orm(column_name = "latestStatus")] + pub latest_status: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::user::Entity", + from = "Column::UserId", + to = "super::user::Column::Id", + on_update = "NoAction", + on_delete = "Cascade" + )] + User, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::User.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/backend/native-utils/src/model/error.rs b/packages/backend/native-utils/src/model/error.rs new file mode 100644 index 000000000..8e9213066 --- /dev/null +++ b/packages/backend/native-utils/src/model/error.rs @@ -0,0 +1,15 @@ +use crate::impl_into_napi_error; + +#[derive(thiserror::Error, Debug, PartialEq, Eq)] +pub enum Error { + #[error("Failed to parse string: {0}")] + ParseError(#[from] parse_display::ParseError), + #[error("Failed to get database connection: {0}")] + DbConnError(#[from] crate::database::error::Error), + #[error("Database operation error: {0}")] + DbOperationError(#[from] sea_orm::DbErr), + #[error("Requested entity not found")] + NotFound, +} + +impl_into_napi_error!(Error); diff --git a/packages/backend/native-utils/src/model/mod.rs b/packages/backend/native-utils/src/model/mod.rs new file mode 100644 index 000000000..6e86ec052 --- /dev/null +++ b/packages/backend/native-utils/src/model/mod.rs @@ -0,0 +1,4 @@ +pub mod entity; +pub mod error; +pub mod repository; +pub mod schema; diff --git a/packages/backend/native-utils/src/model/repository.rs b/packages/backend/native-utils/src/model/repository.rs new file mode 100644 index 000000000..5abf7907f --- /dev/null +++ b/packages/backend/native-utils/src/model/repository.rs @@ -0,0 +1,33 @@ +pub mod antenna; + +use async_trait::async_trait; +use schemars::JsonSchema; + +use super::error::Error; + +/// Repositories have a packer that converts a database model to its +/// corresponding API schema. +#[async_trait] +pub trait Repository { + async fn pack(self) -> Result; + /// Retrieves one model by its id and pack it. + async fn pack_by_id(id: String) -> Result; +} + +mod macros { + /// Provides the default implementation of + /// [crate::model::repository::Repository::pack_by_id]. + macro_rules! impl_pack_by_id { + ($a:ty, $b:ident) => { + match <$a>::find_by_id($b) + .one(crate::database::get_database()?) + .await? + { + None => Err(Error::NotFound), + Some(m) => m.pack().await, + } + }; + } + + pub(crate) use impl_pack_by_id; +} diff --git a/packages/backend/native-utils/src/model/repository/antenna.rs b/packages/backend/native-utils/src/model/repository/antenna.rs new file mode 100644 index 000000000..7c614b954 --- /dev/null +++ b/packages/backend/native-utils/src/model/repository/antenna.rs @@ -0,0 +1,62 @@ +use async_trait::async_trait; +use cfg_if::cfg_if; +use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; + +use crate::database; +use crate::model::entity::{antenna, antenna_note, user_group_joining}; +use crate::model::error::Error; +use crate::model::schema::Antenna; + +use super::macros::impl_pack_by_id; +use super::Repository; + +#[async_trait] +impl Repository for antenna::Model { + async fn pack(self) -> Result { + 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 { + None => None, + Some(id) => user_group_joining::Entity::find_by_id(id).one(db).await?, + }; + let user_group_id = match user_group_joining { + None => None, + Some(m) => Some(m.user_group_id), + }; + + cfg_if! { + if #[cfg(feature = "napi")] { + let created_at: String = self.created_at.to_rfc3339(); + } else { + let created_at: chrono::DateTime = self.created_at.into(); + } + } + + Ok(Antenna { + id: self.id, + created_at, + name: self.name, + keywords: self.keywords.into(), + exclude_keywords: self.exclude_keywords.into(), + src: self.src.try_into()?, + user_list_id: self.user_list_id, + user_group_id, + users: self.users.into(), + instances: self.instances.into(), + case_sensitive: self.case_sensitive, + notify: self.notify, + with_replies: self.with_replies, + with_file: self.with_file, + has_unread_note, + }) + } + + async fn pack_by_id(id: String) -> Result { + impl_pack_by_id!(antenna::Entity, id) + } +} diff --git a/packages/backend/native-utils/src/model/schema.rs b/packages/backend/native-utils/src/model/schema.rs new file mode 100644 index 000000000..4c0ca7941 --- /dev/null +++ b/packages/backend/native-utils/src/model/schema.rs @@ -0,0 +1,35 @@ +pub mod antenna; +pub mod app; + +use cfg_if::cfg_if; +use jsonschema::JSONSchema; +use schemars::{schema_for, JsonSchema}; + +/// Structs of schema defitions implement this trait in order to +/// provide the JSON Schema validator [`jsonschema::JSONSchema`]. +pub trait Schema { + /// Returns the validator of [JSON Schema Draft + /// 7](https://json-schema.org/specification-links.html#draft-7) with the + /// default settings of [`schemars::gen::SchemaSettings`]. + fn validator() -> JSONSchema { + let root = schema_for!(T); + let schema = serde_json::to_value(&root).expect("Schema definition invalid"); + JSONSchema::options() + .with_draft(jsonschema::Draft::Draft7) + .compile(&schema) + .expect("Unable to compile schema") + } +} + +cfg_if! { + if #[cfg(feature = "napi")] { + // Will be disabled once we completely migrate to rust + pub use antenna::NativeAntennaSchema as Antenna; + pub use antenna::NativeAntennaSrc as AntennaSrc; + } else { + pub use antenna::Antenna; + pub use antenna::AntennaSrc; + pub use app::App; + pub use app::AppPermission; + } +} diff --git a/packages/backend/native-utils/src/model/schema/antenna.rs b/packages/backend/native-utils/src/model/schema/antenna.rs new file mode 100644 index 000000000..4ec1e0794 --- /dev/null +++ b/packages/backend/native-utils/src/model/schema/antenna.rs @@ -0,0 +1,217 @@ +use cfg_if::cfg_if; +use jsonschema::JSONSchema; +use once_cell::sync::Lazy; +use parse_display::FromStr; +use schemars::JsonSchema; +use utoipa::ToSchema; + +use super::Schema; +use crate::model; +use crate::model::entity::sea_orm_active_enums::AntennaSrcEnum; + +#[derive(Clone, Debug, PartialEq, Eq, JsonSchema, ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct Antenna { + pub id: String, + pub created_at: chrono::DateTime, + pub name: String, + pub keywords: Vec>, + pub exclude_keywords: Vec>, + #[schema(inline)] + pub src: AntennaSrc, + pub user_list_id: Option, + pub user_group_id: Option, + pub users: Vec, + pub instances: Vec, + #[serde(default)] + pub case_sensitive: bool, + #[serde(default)] + pub notify: bool, + #[serde(default)] + pub with_replies: bool, + #[serde(default)] + pub with_file: bool, + #[serde(default)] + pub has_unread_note: bool, +} + +#[derive(Clone, Debug, FromStr, PartialEq, Eq, JsonSchema, ToSchema)] +#[serde(rename_all = "camelCase")] +#[display(style = "camelCase")] +#[display("'{}'")] +pub enum AntennaSrc { + Home, + All, + Users, + List, + Group, + Instances, +} + +impl TryFrom for super::AntennaSrc { + type Error = model::error::Error; + + fn try_from(value: AntennaSrcEnum) -> Result { + value.to_string().parse().map_err(model::error::Error::from) + } +} + +// ---- TODO: could be macro +impl Schema for super::Antenna {} +pub static VALIDATOR: Lazy = Lazy::new(|| super::Antenna::validator()); +// ---- + +cfg_if! { + if #[cfg(feature = "napi")] { + use napi::bindgen_prelude::{FromNapiValue, ToNapiValue}; + use napi_derive::napi; + + use crate::model::entity::antenna; + use crate::model::repository::Repository; + + /// For NAPI because [chrono] is not supported. + #[napi(object)] + #[derive(Clone, Debug, PartialEq, Eq, JsonSchema, ToSchema)] + #[serde(rename_all = "camelCase")] + pub struct NativeAntennaSchema { + pub id: String, + pub created_at: String, + pub name: String, + pub keywords: Vec>, + pub exclude_keywords: Vec>, + #[schema(inline)] + pub src: NativeAntennaSrc, + pub user_list_id: Option, + pub user_group_id: Option, + pub users: Vec, + pub instances: Vec, + #[serde(default)] + pub case_sensitive: bool, + #[serde(default)] + pub notify: bool, + #[serde(default)] + pub with_replies: bool, + #[serde(default)] + pub with_file: bool, + #[serde(default)] + pub has_unread_note: bool, + } + + #[napi(string_enum)] + #[derive(Debug, FromStr, PartialEq, Eq, JsonSchema, ToSchema)] + #[display("'{}'")] + #[allow(non_camel_case_types)] + pub enum NativeAntennaSrc { + home, + all, + users, + list, + group, + instances, + } + + #[napi] + pub async fn native_pack_antenna_by_id(id: String) -> napi::Result { + antenna::Model::pack_by_id(id).await.map_err(Into::into) + } + } +} + +#[cfg(test)] +mod unit_test { + use cfg_if::cfg_if; + use pretty_assertions::assert_eq; + use serde_json::json; + + use crate::model::{entity::sea_orm_active_enums::AntennaSrcEnum, schema::AntennaSrc}; + + use super::VALIDATOR; + + #[test] + fn src_from_active_enum() { + let src = AntennaSrc::try_from(AntennaSrcEnum::All).unwrap(); + cfg_if! { + if #[cfg(feature = "napi")] { + assert_eq!(src, AntennaSrc::all); + } else { + assert_eq!(src, AntennaSrc::All); + } + } + } + + #[test] + fn antenna_valid() { + let instance = json!({ + "id": "9fil64s6g7cskdrb", + "createdAt": "2023-05-24T06:56:14.323Z", + "name": "Valid Antenna", + "keywords": [["first", "keyword"], ["second"]], + "excludeKeywords": [["excluding", "keywrods"], ["from", "antenna"]], + "src": "users", + // "userListId" and "userGroupId" can be null or be omitted + "userListId": null, + "users": ["9fil64s6g7cskdrb", "9fil66brl1udxau2"], + "instances": [], + // "caseSensitive", "notify", "withReplies", "withFile", and + // "hasUnreadNote" are false if ommited + "notify": false, + "withReplies": false, + "withFile": false, + "hasUnreadNote": false, + }); + + assert!(VALIDATOR.is_valid(&instance)); + } + + #[test] + fn antenna_invalid() { + let instance = json!({ + // "id" is required + "id": null, + // trailing "Z" is missing + "createdAt": "2023-05-24T07:36:34.389", + // "name" is required + // "keywords" must be an array + "keywords": "invalid keyword", + // "excludeKeywords" is required + "excludeKeywords": null, + // "src" must be one of "home", "all", "users", "list", "group", and + // "instances" + "src": "invalid_src", + // "userListId" is string + "userListId": ["9f4ziiqfxw"], + // "users" must be an array of strings + "users": [1, "9fil64s6g7cskdrb"], + "instances": ["9fil65jzhtjpi3xn"], + // "caseSensitive" is boolean + "caseSensitive": 0, + "notify": true, + "withReplies": true, + "withFile": true, + "hasUnreadNote": true, + }); + + let result = VALIDATOR + .validate(&instance) + .expect_err("validation must fail"); + let mut paths: Vec = result + .map(|e| e.instance_path.to_string()) + .filter(|e| !e.is_empty()) + .collect(); + paths.sort(); + assert_eq!( + paths, + vec![ + "/caseSensitive", + #[cfg(not(feature = "napi"))] + "/createdAt", + "/excludeKeywords", + "/id", + "/keywords", + "/src", + "/userListId", + "/users/0" + ] + ); + } +} diff --git a/packages/backend/native-utils/src/model/schema/app.rs b/packages/backend/native-utils/src/model/schema/app.rs new file mode 100644 index 000000000..682b82ec0 --- /dev/null +++ b/packages/backend/native-utils/src/model/schema/app.rs @@ -0,0 +1,147 @@ +use jsonschema::JSONSchema; +use once_cell::sync::Lazy; +use schemars::JsonSchema; +use utoipa::ToSchema; + +use super::Schema; + +#[derive(Clone, Debug, PartialEq, Eq, JsonSchema, ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct App { + pub id: String, + pub name: String, + #[schemars(url)] + pub callback_url: Option, + #[schema(inline)] + pub permission: Vec, + pub secret: Option, + pub is_authorized: Option, +} + +/// This represents `permissions` in `packages/calckey-js/src/consts.ts`. +#[derive(Clone, Debug, PartialEq, Eq, JsonSchema, ToSchema)] +pub enum AppPermission { + #[serde(rename = "read:account")] + ReadAccount, + #[serde(rename = "write:account")] + WriteAccount, + #[serde(rename = "read:blocks")] + ReadBlocks, + #[serde(rename = "write:blocks")] + WriteBlocks, + #[serde(rename = "read:drive")] + ReadDrive, + #[serde(rename = "write:drive")] + WriteDrive, + #[serde(rename = "read:favorites")] + ReadFavorites, + #[serde(rename = "write:favorites")] + WriteFavorites, + #[serde(rename = "read:following")] + ReadFollowing, + #[serde(rename = "write:following")] + WriteFollowing, + #[serde(rename = "read:messaging")] + ReadMessaging, + #[serde(rename = "write:messaging")] + WriteMessaging, + #[serde(rename = "read:mutes")] + ReadMutes, + #[serde(rename = "write:mutes")] + WriteMutes, + #[serde(rename = "read:notes")] + ReadNotes, + #[serde(rename = "write:notes")] + WriteNotes, + #[serde(rename = "read:notifications")] + ReadNotifications, + #[serde(rename = "write:notifications")] + WriteNotifications, + #[serde(rename = "read:reactions")] + ReadReactions, + #[serde(rename = "write:reactions")] + WriteReactions, + #[serde(rename = "write:votes")] + WriteVotes, + #[serde(rename = "read:pages")] + ReadPages, + #[serde(rename = "write:pages")] + WritePages, + #[serde(rename = "read:page-likes")] + ReadPageLikes, + #[serde(rename = "write:page-likes")] + WritePageLikes, + #[serde(rename = "read:user-groups")] + ReadUserGroups, + #[serde(rename = "write:user-groups")] + WriteUserGroups, + #[serde(rename = "read:channels")] + ReadChannels, + #[serde(rename = "write:channels")] + WriteChannels, + #[serde(rename = "read:gallery")] + ReadGallery, + #[serde(rename = "write:gallery")] + WriteGallery, + #[serde(rename = "read:gallery-likes")] + ReadGalleryLikes, + #[serde(rename = "write:gallery-likes")] + WriteGalleryLikes, +} + +impl Schema for App {} + +pub static VALIDATOR: Lazy = Lazy::new(|| App::validator()); + +#[cfg(test)] +mod unit_test { + use pretty_assertions::assert_eq; + use serde_json::json; + + use crate::util::id::{create_id, init_id}; + use crate::util::random::gen_string; + + use super::VALIDATOR; + + #[test] + fn app_valid() { + init_id(12, ""); + let instance = json!({ + "id": create_id().unwrap(), + "name": "Test App", + "secret": gen_string(24), + "callbackUrl": "urn:ietf:wg:oauth:2.0:oob", + "permission": ["read:account", "write:account", "read:notes"], + }); + + assert!(VALIDATOR.is_valid(&instance)); + } + + #[test] + fn app_invalid() { + init_id(12, ""); + let instance = json!({ + "id": create_id().unwrap(), + // "name" is required + "name": null, + // "permission" must be one of the app permissions + "permission": ["write:invalid_perm", "write:notes"], + // "secret" is a nullable string + "secret": 123, + // "is_authorized" is a nullable boolean + "isAuthorized": "true-ish", + }); + let result = VALIDATOR + .validate(&instance) + .expect_err("validation must fail"); + let mut paths: Vec = result + .map(|e| e.instance_path.to_string()) + .filter(|e| !e.is_empty()) + .collect(); + paths.sort(); + assert_eq!( + paths, + vec!["/isAuthorized", "/name", "/permission/0", "/secret"] + ); + } +} diff --git a/packages/backend/native-utils/src/util/id.rs b/packages/backend/native-utils/src/util/id.rs new file mode 100644 index 000000000..d922518f9 --- /dev/null +++ b/packages/backend/native-utils/src/util/id.rs @@ -0,0 +1,98 @@ +//! ID generation utility based on [cuid2] + +use cfg_if::cfg_if; +use once_cell::sync::OnceCell; + +use crate::impl_into_napi_error; + +#[derive(thiserror::Error, Debug, PartialEq, Eq)] +#[error("ID generator has not been initialized yet")] +pub struct ErrorUninitialized; + +impl_into_napi_error!(ErrorUninitialized); + +static FINGERPRINT: OnceCell = OnceCell::new(); +static GENERATOR: OnceCell = OnceCell::new(); + +/// Initializes Cuid2 generator. Must be called before any [create_id]. +pub fn init_id(length: u16, fingerprint: impl Into) { + FINGERPRINT.get_or_init(move || format!("{}{}", fingerprint.into(), cuid2::create_id())); + GENERATOR.get_or_init(move || { + cuid2::CuidConstructor::new() + .with_length(length) + .with_fingerprinter(|| FINGERPRINT.get().unwrap().clone()) + }); +} + +/// Returns Cuid2 with the length specified by [init_id]. Must be called after +/// [init_id], otherwise returns [ErrorUninitialized]. +pub fn create_id() -> Result { + match GENERATOR.get() { + None => Err(ErrorUninitialized), + Some(gen) => Ok(gen.create_id()), + } +} + +cfg_if! { + if #[cfg(feature = "napi")] { + use radix_fmt::radix_36; + use std::cmp; + use napi::bindgen_prelude::BigInt; + 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]. + #[napi] + 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(cmp::max(length - TIMESTAMP_LENGTH, 8), fingerprint); + } + + /// Generates + #[napi] + pub fn native_create_id(date_num: BigInt) -> String { + let time = cmp::max(date_num.get_u64().1 - TIME_2000, 0); + format!("{:0>8}{}", radix_36(time).to_string(), create_id().unwrap()) + } + } +} + +#[cfg(test)] +mod unit_test { + use crate::util::id; + use cfg_if::cfg_if; + use pretty_assertions::{assert_eq, assert_ne}; + 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] + fn can_generate_unique_ids() { + assert_eq!(id::create_id(), Err(id::ErrorUninitialized)); + id::init_id(12, ""); + assert_eq!(id::create_id().unwrap().len(), 12); + assert_ne!(id::create_id().unwrap(), id::create_id().unwrap()); + let id1 = thread::spawn(|| id::create_id().unwrap()); + let id2 = thread::spawn(|| id::create_id().unwrap()); + assert_ne!(id1.join().unwrap(), id2.join().unwrap()); + } + } + } +} diff --git a/packages/backend/native-utils/src/util/mod.rs b/packages/backend/native-utils/src/util/mod.rs new file mode 100644 index 000000000..1be5a7fd1 --- /dev/null +++ b/packages/backend/native-utils/src/util/mod.rs @@ -0,0 +1,2 @@ +pub mod id; +pub mod random; diff --git a/packages/backend/native-utils/src/util/random.rs b/packages/backend/native-utils/src/util/random.rs new file mode 100644 index 000000000..ffcbca980 --- /dev/null +++ b/packages/backend/native-utils/src/util/random.rs @@ -0,0 +1,33 @@ +use rand::{distributions::Alphanumeric, thread_rng, Rng}; + +/// Generate random string based on [thread_rng] and [Alphanumeric]. +pub fn gen_string(length: u16) -> String { + thread_rng() + .sample_iter(Alphanumeric) + .take(length.into()) + .map(char::from) + .collect() +} + +#[cfg(feature = "napi")] +#[napi_derive::napi] +pub fn native_random_str(length: u16) -> String { + gen_string(length) +} + +#[cfg(test)] +mod unit_test { + use pretty_assertions::{assert_eq, assert_ne}; + use std::thread; + + use super::gen_string; + + #[test] + fn can_generate_unique_strings() { + assert_eq!(gen_string(16).len(), 16); + assert_ne!(gen_string(16), gen_string(16)); + let s1 = thread::spawn(|| gen_string(16)); + let s2 = thread::spawn(|| gen_string(16)); + assert_ne!(s1.join().unwrap(), s2.join().unwrap()); + } +} diff --git a/packages/backend/native-utils/tests/common.rs b/packages/backend/native-utils/tests/common.rs new file mode 100644 index 000000000..186e862bd --- /dev/null +++ b/packages/backend/native-utils/tests/common.rs @@ -0,0 +1,216 @@ +#![cfg(not(feature = "napi"))] + +mod model; + +use chrono::Utc; +use native_utils::database; +use native_utils::model::entity; +use native_utils::model::entity::sea_orm_active_enums::AntennaSrcEnum; +use native_utils::util::{ + id::{create_id, init_id}, + random::gen_string, +}; +use sea_orm::{ + sea_query::TableCreateStatement, ActiveModelTrait, ConnectionTrait, DbBackend, DbConn, DbErr, + EntityTrait, IntoActiveModel, TransactionTrait, +}; + +/// Insert predefined entries in the database. +async fn prepare() { + database::init_database("sqlite::memory:") + .await + .expect("Unable to initialize database connection"); + let db = database::get_database().expect("Unable to get database connection from pool"); + setup_schema(db).await; + setup_model(db).await; +} + +/// Setup schemas in the database. +async fn setup_schema(db: &DbConn) { + let schema = sea_orm::Schema::new(DbBackend::Sqlite); + let mut stmts: Vec = Vec::new(); + macro_rules! create_table_statement { + ($a:tt) => { + stmts.push(schema.create_table_from_entity(entity::$a::Entity).if_not_exists().to_owned()); + }; + ($a:tt, $($b:tt),+) => { + create_table_statement!($a); + create_table_statement!($($b),+); + }; + } + create_table_statement!( + abuse_user_report, + access_token, + ad, + announcement_read, + announcement, + antenna_note, + antenna, + app, + attestation_challenge, + auth_session, + blocking, + channel_following, + channel_note_pining, + channel, + clip_note, + clip, + drive_file, + drive_folder, + emoji, + following, + follow_request, + gallery_like, + gallery_post, + hashtag, + instance, + messaging_message, + meta, + migrations, + moderation_log, + muted_note, + muting, + note_edit, + note_favorite, + note_reaction, + note, + note_thread_muting, + note_unread, + note_watching, + notification, + page_like, + page, + password_reset_request, + poll, + poll_vote, + promo_note, + promo_read, + registration_ticket, + registry_item, + relay, + renote_muting, + signin, + sw_subscription, + used_username, + user_group_invitation, + user_group_invite, + user_group_joining, + user_group, + user_ip, + user_keypair, + user_list_joining, + user_list, + user_note_pining, + user_pending, + user_profile, + user_publickey, + user, + user_security_key, + webhook + ); + db.transaction::<_, (), DbErr>(|txn| { + Box::pin(async move { + for stmt in stmts { + txn.execute(txn.get_database_backend().build(&stmt)).await?; + } + Ok(()) + }) + }) + .await + .expect("Unable to setup schemas"); +} + +/// Delete all entries in the database. +async fn cleanup() { + let db = database::get_database().expect("Unable to get database connection from pool"); + db.transaction::<_, (), DbErr>(|txn| { + Box::pin(async move { + entity::user::Entity::delete_many().exec(txn).await.unwrap(); + entity::antenna::Entity::delete_many() + .exec(txn) + .await + .unwrap(); + + Ok(()) + }) + }) + .await + .expect("Unable to delete predefined models"); +} + +async fn setup_model(db: &DbConn) { + init_id(12, ""); + + db.transaction::<_, (), DbErr>(|txn| { + Box::pin(async move { + let user_id = create_id().unwrap(); + let name = "Alice"; + let user_model = entity::user::Model { + id: user_id.to_owned(), + created_at: Utc::now().into(), + username: name.to_lowercase().to_string(), + username_lower: name.to_lowercase().to_string(), + name: Some(name.to_string()), + token: Some(gen_string(16)), + is_admin: true, + ..Default::default() + }; + user_model + .into_active_model() + .reset_all() + .insert(txn) + .await?; + let antenna_model = entity::antenna::Model { + id: create_id().unwrap(), + created_at: Utc::now().into(), + user_id: user_id.to_owned(), + name: "Alice Antenna".to_string(), + src: AntennaSrcEnum::All, + keywords: vec![ + vec!["foo".to_string(), "bar".to_string()], + vec!["foobar".to_string()], + ] + .into(), + exclude_keywords: vec![ + vec!["abc".to_string()], + vec!["def".to_string(), "ghi".to_string()], + ] + .into(), + notify: true, + case_sensitive: true, + ..Default::default() + }; + antenna_model + .into_active_model() + .reset_all() + .insert(txn) + .await?; + let note_model = entity::note::Model { + id: create_id().unwrap(), + created_at: Utc::now().into(), + text: Some("Testing 123".to_string()), + user_id: user_id.to_owned(), + ..Default::default() + }; + note_model + .into_active_model() + .reset_all() + .insert(txn) + .await?; + + Ok(()) + }) + }) + .await + .expect("Unable to setup predefined models"); +} + +mod int_test { + use super::{cleanup, prepare}; + + #[tokio::test] + async fn can_prepare_and_cleanup() { + prepare().await; + cleanup().await; + } +} diff --git a/packages/backend/native-utils/tests/model/mod.rs b/packages/backend/native-utils/tests/model/mod.rs new file mode 100644 index 000000000..a35bac056 --- /dev/null +++ b/packages/backend/native-utils/tests/model/mod.rs @@ -0,0 +1 @@ +mod repository; diff --git a/packages/backend/native-utils/tests/model/repository.rs b/packages/backend/native-utils/tests/model/repository.rs new file mode 100644 index 000000000..c11ef7687 --- /dev/null +++ b/packages/backend/native-utils/tests/model/repository.rs @@ -0,0 +1 @@ +mod antenna; diff --git a/packages/backend/native-utils/tests/model/repository/antenna.rs b/packages/backend/native-utils/tests/model/repository/antenna.rs new file mode 100644 index 000000000..3bda2ca18 --- /dev/null +++ b/packages/backend/native-utils/tests/model/repository/antenna.rs @@ -0,0 +1,118 @@ +mod int_test { + use native_utils::{database, model, util}; + + use model::{ + entity::{antenna, antenna_note, note, user}, + repository::Repository, + schema, + }; + use pretty_assertions::assert_eq; + use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter}; + + use crate::{cleanup, prepare}; + + #[tokio::test] + async fn can_pack() { + prepare().await; + let db = database::get_database().unwrap(); + + let alice_antenna = user::Entity::find() + .filter(user::Column::Username.eq("alice")) + .find_also_related(antenna::Entity) + .one(db) + .await + .unwrap() + .expect("alice not found") + .1 + .expect("alice's antenna not found"); + + let packed = alice_antenna + .to_owned() + .pack() + .await + .expect("Unable to pack"); + + let packed_by_id = antenna::Model::pack_by_id(alice_antenna.id.to_owned()) + .await + .expect("Unable to pack"); + + let result = schema::Antenna { + id: alice_antenna.id, + created_at: alice_antenna.created_at.into(), + name: "Alice Antenna".to_string(), + keywords: vec![ + vec!["foo".to_string(), "bar".to_string()], + vec!["foobar".to_string()], + ] + .into(), + exclude_keywords: vec![ + vec!["abc".to_string()], + vec!["def".to_string(), "ghi".to_string()], + ] + .into(), + src: schema::AntennaSrc::All, + user_list_id: None, + user_group_id: None, + users: vec![].into(), + instances: vec![].into(), + case_sensitive: true, + notify: true, + with_replies: false, + with_file: false, + has_unread_note: false, + }; + + assert_eq!(packed, result); + assert_eq!(packed_by_id, result); + + cleanup().await; + } + + #[tokio::test] + async fn unread_note() { + prepare().await; + let db = database::get_database().unwrap(); + + let (alice, alice_antenna) = user::Entity::find() + .filter(user::Column::Username.eq("alice")) + .find_also_related(antenna::Entity) + .one(db) + .await + .unwrap() + .expect("alice not found"); + let alice_antenna = alice_antenna.expect("alice's antenna not found"); + let packed = alice_antenna + .to_owned() + .pack() + .await + .expect("Unable to pack"); + assert_eq!(packed.has_unread_note, false); + + let note_model = note::Entity::find() + .filter(note::Column::UserId.eq(alice.id)) + .one(db) + .await + .unwrap() + .expect("note not found"); + let antenna_note = antenna_note::Model { + id: util::id::create_id().unwrap(), + antenna_id: alice_antenna.id.to_owned(), + note_id: note_model.id.to_owned(), + read: false, + }; + antenna_note + .into_active_model() + .reset_all() + .insert(db) + .await + .unwrap(); + let packed = alice_antenna + .to_owned() + .pack() + .await + .expect("Unable to pack"); + assert_eq!(packed.has_unread_note, true); + + cleanup().await; + } +} diff --git a/packages/backend/package.json b/packages/backend/package.json index 96edb7f02..47e9c415c 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -6,10 +6,14 @@ "scripts": { "start": "pnpm node ./built/index.js", "start:test": "NODE_ENV=test pnpm node ./built/index.js", - "migrate": "typeorm migration:run -d ormconfig.js", - "revertmigration": "typeorm migration:revert -d ormconfig.js", + "migrate": "pnpm run migrate:typeorm && pnpm run migrate:cargo", + "migrate:typeorm": "typeorm migration:run -d ormconfig.js", + "migrate:cargo": "cargo run --manifest-path native-utils/migration/Cargo.toml -- up", + "revertmigration": "pnpm run revertmigration:cargo && pnpm run revertmigration:typeorm", + "revertmigration:typeorm": "typeorm migration:revert -d ormconfig.js", + "revertmigration:cargo": "cargo run --manifest-path native-utils/migration/Cargo.toml -- down", "check:connect": "node ./check_connect.js", - "build": "napi build --platform --release --cargo-cwd native-utils ./native-utils/built/ && pnpm swc src -d built -D", + "build": "pnpm swc src -d built -D", "watch": "pnpm swc src -d built -D -w", "lint": "pnpm rome check \"src/**/*.ts\"", "mocha": "cross-env NODE_ENV=test TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha", @@ -23,9 +27,9 @@ "@tensorflow/tfjs-node": "3.21.1" }, "dependencies": { - "@bull-board/api": "^4.6.4", - "@bull-board/koa": "^4.6.4", - "@bull-board/ui": "^4.6.4", + "@bull-board/api": "5.2.0", + "@bull-board/koa": "5.2.0", + "@bull-board/ui": "5.2.0", "@calckey/megalodon": "5.2.0", "@discordapp/twemoji": "14.0.2", "@elastic/elasticsearch": "7.17.0", @@ -49,7 +53,7 @@ "axios": "^1.3.2", "bcryptjs": "2.4.3", "blurhash": "1.1.5", - "bull": "4.10.2", + "bull": "4.10.4", "cacheable-lookup": "7.0.0", "calckey-js": "workspace:*", "cbor": "8.1.0", @@ -59,7 +63,7 @@ "cli-highlight": "2.1.11", "color-convert": "2.0.1", "content-disposition": "0.5.4", - "date-fns": "2.29.3", + "date-fns": "2.30.0", "deep-email-validator": "0.1.21", "escape-regexp": "0.0.1", "feed": "4.2.2", @@ -67,7 +71,7 @@ "fluent-ffmpeg": "2.1.2", "got": "12.5.3", "hpagent": "0.1.2", - "ioredis": "5.2.4", + "ioredis": "5.3.2", "ip-cidr": "3.0.11", "is-svg": "4.3.2", "js-yaml": "4.1.0", @@ -85,6 +89,7 @@ "koa-send": "5.0.1", "koa-slow": "2.1.0", "koa-views": "7.0.2", + "meilisearch": "0.32.4", "mfm-js": "0.23.3", "mime-types": "2.1.35", "multer": "1.4.4-lts.1", diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index 01a98f9f0..54332c993 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -39,6 +39,12 @@ export type Source = { collection?: string; bucket?: string; }; + meilisearch: { + host: string; + port: number; + apiKey?: string; + ssl: boolean; + }; proxy?: string; proxySmtp?: string; @@ -54,7 +60,10 @@ export type Source = { onlyQueueProcessor?: boolean; - id: string; + cuid?: { + length?: number; + fingerprint?: string; + }; outgoingAddressFamily?: "ipv4" | "ipv6" | "dual"; diff --git a/packages/backend/src/daemons/server-stats.ts b/packages/backend/src/daemons/server-stats.ts index b0bf1288f..c936d619a 100644 --- a/packages/backend/src/daemons/server-stats.ts +++ b/packages/backend/src/daemons/server-stats.ts @@ -1,6 +1,7 @@ import si from "systeminformation"; import Xev from "xev"; import * as osUtils from "os-utils"; +import meilisearch from "../db/meilisearch.js"; const ev = new Xev(); @@ -24,6 +25,7 @@ export default function () { const memStats = await mem(); const netStats = await net(); const fsStats = await fs(); + const meilisearchStats = await meilisearchStatus(); const stats = { cpu: roundCpu(cpu), @@ -39,6 +41,7 @@ export default function () { r: round(Math.max(0, fsStats.rIO_sec ?? 0)), w: round(Math.max(0, fsStats.wIO_sec ?? 0)), }, + meilisearch: meilisearchStats, }; ev.emit("serverStats", stats); log.unshift(stats); @@ -77,3 +80,16 @@ async function fs() { const data = await si.disksIO().catch(() => ({ rIO_sec: 0, wIO_sec: 0 })); return data || { rIO_sec: 0, wIO_sec: 0 }; } + +// MEILI STAT +async function meilisearchStatus() { + if (meilisearch) { + return meilisearch.serverStats(); + } else { + return { + health: "unconfigured", + size: 0, + indexed_count: 0, + }; + } +} diff --git a/packages/backend/src/db/meilisearch.ts b/packages/backend/src/db/meilisearch.ts new file mode 100644 index 000000000..33553b64c --- /dev/null +++ b/packages/backend/src/db/meilisearch.ts @@ -0,0 +1,311 @@ +import { Health, Index, MeiliSearch, Stats } from "meilisearch"; +import { dbLogger } from "./logger.js"; + +import config from "@/config/index.js"; +import { Note } from "@/models/entities/note.js"; +import * as url from "url"; +import { ILocalUser } from "@/models/entities/user.js"; +import { Followings, Users } from "@/models/index.js"; + +const logger = dbLogger.createSubLogger("meilisearch", "gray", false); + +let posts: Index; +let client: MeiliSearch; + +const hasConfig = + config.meilisearch && + (config.meilisearch.host || + config.meilisearch.port || + config.meilisearch.apiKey); + +if (hasConfig) { + const host = hasConfig ? config.meilisearch.host ?? "localhost" : ""; + const port = hasConfig ? config.meilisearch.port ?? 7700 : 0; + const auth = hasConfig ? config.meilisearch.apiKey ?? "" : ""; + const ssl = hasConfig ? config.meilisearch.ssl ?? false : false; + + logger.info("Connecting to MeiliSearch"); + + client = new MeiliSearch({ + host: `${ssl ? "https" : "http"}://${host}:${port}`, + apiKey: auth, + }); + + posts = client.index("posts"); + + posts + .updateSearchableAttributes(["text"]) + .catch((e) => + logger.error(`Setting searchable attr failed, searches won't work: ${e}`), + ); + + posts + .updateFilterableAttributes([ + "userName", + "userHost", + "mediaAttachment", + "createdAt", + "userId", + ]) + .catch((e) => + logger.error( + `Setting filterable attr failed, advanced searches won't work: ${e}`, + ), + ); + + posts + .updateSortableAttributes(["createdAt"]) + .catch((e) => + logger.error( + `Setting sortable attr failed, placeholder searches won't sort properly: ${e}`, + ), + ); + + logger.info("Connected to MeiliSearch"); +} + +export type MeilisearchNote = { + id: string; + text: string; + userId: string; + userHost: string; + userName: string; + channelId: string; + mediaAttachment: string; + createdAt: number; +}; + +export default hasConfig + ? { + search: async ( + query: string, + limit: number, + offset: number, + userCtx: ILocalUser | null, + ) => { + /// Advanced search syntax + /// from:user => filter by user + optional domain + /// has:image/video/audio/text/file => filter by attachment types + /// domain:domain.com => filter by domain + /// before:Date => show posts made before Date + /// after: Date => show posts made after Date + /// "text" => get posts with exact text between quotes + /// filter:following => show results only from users you follow + /// filter:followers => show results only from followers + + const constructedFilters: string[] = []; + + const splitSearch = query.split(" "); + + // Detect search operators and remove them from the actual query + const filteredSearchTerms = ( + await Promise.all( + splitSearch.map(async (term) => { + if (term.startsWith("has:")) { + const fileType = term.slice(4); + constructedFilters.push(`mediaAttachment = "${fileType}"`); + return null; + } else if (term.startsWith("from:")) { + const user = term.slice(5); + constructedFilters.push(`userName = ${user}`); + return null; + } else if (term.startsWith("domain:")) { + const domain = term.slice(7); + constructedFilters.push(`userHost = ${domain}`); + return null; + } else if (term.startsWith("after:")) { + const timestamp = term.slice(6); + // Try to parse the timestamp as JavaScript Date + const date = Date.parse(timestamp); + if (isNaN(date)) return null; + constructedFilters.push(`createdAt > ${date / 1000}`); + return null; + } else if (term.startsWith("before:")) { + const timestamp = term.slice(7); + // Try to parse the timestamp as JavaScript Date + const date = Date.parse(timestamp); + if (isNaN(date)) return null; + constructedFilters.push(`createdAt < ${date / 1000}`); + return null; + } else if (term.startsWith("filter:following")) { + // Check if we got a context user + if (userCtx) { + // Fetch user follows from DB + const followedUsers = await Followings.find({ + where: { + followerId: userCtx.id, + }, + select: { + followeeId: true, + }, + }); + const followIDs = followedUsers.map( + (user) => user.followeeId, + ); + + if (followIDs.length === 0) return null; + + constructedFilters.push(`userId IN [${followIDs.join(",")}]`); + } else { + logger.warn( + "search filtered to follows called without user context", + ); + } + + return null; + } else if (term.startsWith("filter:followers")) { + // Check if we got a context user + if (userCtx) { + // Fetch users follows from DB + const followedUsers = await Followings.find({ + where: { + followeeId: userCtx.id, + }, + select: { + followerId: true, + }, + }); + const followIDs = followedUsers.map( + (user) => user.followerId, + ); + + if (followIDs.length === 0) return null; + + constructedFilters.push(`userId IN [${followIDs.join(",")}]`); + } else { + logger.warn( + "search filtered to followers called without user context", + ); + } + + return null; + } + + return term; + }), + ) + ).filter((term) => term !== null); + + const sortRules = []; + + // An empty search term with defined filters means we have a placeholder search => https://www.meilisearch.com/docs/reference/api/search#placeholder-search + // These have to be ordered manually, otherwise the *oldest* posts are returned first, which we don't want + if (filteredSearchTerms.length === 0 && constructedFilters.length > 0) { + sortRules.push("createdAt:desc"); + } + + logger.info(`Searching for ${filteredSearchTerms.join(" ")}`); + logger.info(`Limit: ${limit}`); + logger.info(`Offset: ${offset}`); + logger.info(`Filters: ${constructedFilters}`); + logger.info(`Ordering: ${sortRules}`); + + return posts.search(filteredSearchTerms.join(" "), { + limit: limit, + offset: offset, + filter: constructedFilters, + sort: sortRules, + }); + }, + ingestNote: async (ingestNotes: Note | Note[]) => { + if (ingestNotes instanceof Note) { + ingestNotes = [ingestNotes]; + } + + const indexingBatch: MeilisearchNote[] = []; + + for (const note of ingestNotes) { + if (note.user === undefined) { + note.user = await Users.findOne({ + where: { + id: note.userId, + }, + }); + } + + let attachmentType = ""; + if (note.attachedFileTypes.length > 0) { + attachmentType = note.attachedFileTypes[0].split("/")[0]; + switch (attachmentType) { + case "image": + case "video": + case "audio": + case "text": + break; + default: + attachmentType = "file"; + break; + } + } + + indexingBatch.push({ + id: note.id.toString(), + text: note.text ? note.text : "", + userId: note.userId, + userHost: + note.userHost !== "" + ? note.userHost + : url.parse(config.host).host, + channelId: note.channelId ? note.channelId : "", + mediaAttachment: attachmentType, + userName: note.user?.username ?? "UNKNOWN", + createdAt: note.createdAt.getTime() / 1000, // division by 1000 is necessary because Node returns in ms-accuracy + }); + } + + return posts + .addDocuments(indexingBatch, { + primaryKey: "id", + }) + .then(() => + logger.info(`sent ${indexingBatch.length} posts for indexing`), + ); + }, + serverStats: async () => { + const health: Health = await client.health(); + const stats: Stats = await client.getStats(); + + return { + health: health.status, + size: stats.databaseSize, + indexed_count: stats.indexes["posts"].numberOfDocuments, + }; + }, + deleteNotes: async (note: Note | Note[] | string | string[]) => { + if (note instanceof Note) { + note = [note]; + } + if (typeof note === "string") { + note = [note]; + } + + const deletionBatch = note + .map((n) => { + if (n instanceof Note) { + return n.id; + } + + if (n.length > 0) return n; + + logger.error( + `Failed to delete note from Meilisearch, invalid post ID: ${JSON.stringify( + n, + )}`, + ); + + throw new Error( + `Invalid note ID passed to meilisearch deleteNote: ${JSON.stringify( + n, + )}`, + ); + }) + .filter((el) => el !== null); + + await posts.deleteDocuments(deletionBatch as string[]).then(() => { + logger.info( + `submitted ${deletionBatch.length} large batch for deletion`, + ); + }); + }, + } + : null; diff --git a/packages/backend/src/db/postgre.ts b/packages/backend/src/db/postgre.ts index dd202b3de..9ffaf596c 100644 --- a/packages/backend/src/db/postgre.ts +++ b/packages/backend/src/db/postgre.ts @@ -78,6 +78,7 @@ import { entities as charts } from "@/services/chart/entities.js"; import { envOption } from "../env.js"; import { dbLogger } from "./logger.js"; import { redisClient } from "./redis.js"; +import { nativeInitDatabase } from "native-utils/built/index.js"; const sqlLogger = dbLogger.createSubLogger("sql", "gray", false); @@ -220,6 +221,9 @@ export const db = new DataSource({ }); export async function initDb(force = false) { + await nativeInitDatabase( + `postgres://${config.db.user}:${config.db.pass}@${config.db.host}:${config.db.port}/${config.db.db}`, + ); if (force) { if (db.isInitialized) { await db.destroy(); diff --git a/packages/backend/src/misc/gen-id.ts b/packages/backend/src/misc/gen-id.ts index b7cc0965a..ea0d414e7 100644 --- a/packages/backend/src/misc/gen-id.ts +++ b/packages/backend/src/misc/gen-id.ts @@ -1,27 +1,21 @@ -import { ulid } from "ulid"; -import { genAid } from "./id/aid.js"; -import { genMeid } from "./id/meid.js"; -import { genMeidg } from "./id/meidg.js"; -import { genObjectId } from "./id/object-id.js"; import config from "@/config/index.js"; +import { + nativeCreateId, + nativeInitIdGenerator, +} from "native-utils/built/index.js"; -const metohd = config.id.toLowerCase(); +const length = Math.min(Math.max(config.cuid?.length ?? 16, 16), 24); +const fingerprint = config.cuid?.fingerprint ?? ""; +nativeInitIdGenerator(length, fingerprint); +/** + * The generated ID results in the form of `[8 chars timestamp] + [cuid2]`. + * The minimum and maximum lengths are 16 and 24, respectively. + * With the length of 16, namely 8 for cuid2, roughly 1427399 IDs are needed + * in the same millisecond to reach 50% chance of collision. + * + * Ref: https://github.com/paralleldrive/cuid2#parameterized-length + */ export function genId(date?: Date): string { - if (!date || date > new Date()) date = new Date(); - - switch (metohd) { - case "aid": - return genAid(date); - case "meid": - return genMeid(date); - case "meidg": - return genMeidg(date); - case "ulid": - return ulid(date.getTime()); - case "objectid": - return genObjectId(date); - default: - throw new Error("unrecognized id generation method"); - } + return nativeCreateId(BigInt((date ?? new Date()).getTime())); } diff --git a/packages/backend/src/misc/get-note-summary.ts b/packages/backend/src/misc/get-note-summary.ts index 446e3fc14..0a662e434 100644 --- a/packages/backend/src/misc/get-note-summary.ts +++ b/packages/backend/src/misc/get-note-summary.ts @@ -20,12 +20,13 @@ export const getNoteSummary = (note: Packed<"Note">): string => { // ファイルが添付されているとき if ((note.files || []).length !== 0) { - summary += ` (📎${note.files!.length})`; + const len = note.files?.length; + summary += ` 📎${len !== 1 ? ` (${len})` : ""}`; } // 投票が添付されているとき if (note.poll) { - summary += " (📊)"; + summary += " 📊"; } /* diff --git a/packages/backend/src/misc/secure-rndstr.ts b/packages/backend/src/misc/secure-rndstr.ts index 7f5754e1c..3d69a4d4a 100644 --- a/packages/backend/src/misc/secure-rndstr.ts +++ b/packages/backend/src/misc/secure-rndstr.ts @@ -1,24 +1,5 @@ -import * as crypto from "node:crypto"; +import { nativeRandomStr } from "native-utils/built/index.js"; -const L_CHARS = "0123456789abcdefghijklmnopqrstuvwxyz"; -const LU_CHARS = - "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -export function secureRndstr(length = 32, useLU = true): string { - const chars = useLU ? LU_CHARS : L_CHARS; - const chars_len = chars.length; - - let str = ""; - - for (let i = 0; i < length; i++) { - let rand = Math.floor( - (crypto.randomBytes(1).readUInt8(0) / 0xff) * chars_len, - ); - if (rand === chars_len) { - rand = chars_len - 1; - } - str += chars.charAt(rand); - } - - return str; +export function secureRndstr(length = 32, _ = true): string { + return nativeRandomStr(length); } diff --git a/packages/backend/src/models/entities/abuse-user-report.ts b/packages/backend/src/models/entities/abuse-user-report.ts index 655fdd3ca..be183548d 100644 --- a/packages/backend/src/models/entities/abuse-user-report.ts +++ b/packages/backend/src/models/entities/abuse-user-report.ts @@ -15,8 +15,8 @@ export class AbuseUserReport { public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the AbuseUserReport.', + @Column("timestamp with time zone", { + comment: "The created date of the AbuseUserReport.", }) public createdAt: Date; @@ -24,8 +24,8 @@ export class AbuseUserReport { @Column(id()) public targetUserId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public targetUser: User | null; @@ -34,8 +34,8 @@ export class AbuseUserReport { @Column(id()) public reporterId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public reporter: User | null; @@ -46,40 +46,42 @@ export class AbuseUserReport { }) public assigneeId: User["id"] | null; - @ManyToOne(type => User, { - onDelete: 'SET NULL', + @ManyToOne((type) => User, { + onDelete: "SET NULL", }) @JoinColumn() public assignee: User | null; @Index() - @Column('boolean', { + @Column("boolean", { default: false, }) public resolved: boolean; - @Column('boolean', { - default: false + @Column("boolean", { + default: false, }) public forwarded: boolean; - @Column('varchar', { + @Column("varchar", { length: 2048, }) public comment: string; //#region Denormalized fields @Index() - @Column('varchar', { - length: 128, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 128, + nullable: true, + comment: "[Denormalized]", }) public targetUserHost: string | null; @Index() - @Column('varchar', { - length: 128, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 128, + nullable: true, + comment: "[Denormalized]", }) public reporterHost: string | null; //#endregion diff --git a/packages/backend/src/models/entities/access-token.ts b/packages/backend/src/models/entities/access-token.ts index 83d7bbda8..8b950b171 100644 --- a/packages/backend/src/models/entities/access-token.ts +++ b/packages/backend/src/models/entities/access-token.ts @@ -15,31 +15,31 @@ export class AccessToken { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the AccessToken.', + @Column("timestamp with time zone", { + comment: "The created date of the AccessToken.", }) public createdAt: Date; - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, }) public lastUsedAt: Date | null; @Index() - @Column('varchar', { + @Column("varchar", { length: 128, }) public token: string; @Index() - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public session: string | null; @Index() - @Column('varchar', { + @Column("varchar", { length: 128, }) public hash: string; @@ -48,8 +48,8 @@ export class AccessToken { @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -60,37 +60,38 @@ export class AccessToken { }) public appId: App["id"] | null; - @ManyToOne(type => App, { - onDelete: 'CASCADE', + @ManyToOne((type) => App, { + onDelete: "CASCADE", }) @JoinColumn() public app: App | null; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public name: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public description: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public iconUrl: string | null; - @Column('varchar', { - length: 64, array: true, - default: '{}', + @Column("varchar", { + length: 64, + array: true, + default: "{}", }) public permission: string[]; - @Column('boolean', { + @Column("boolean", { default: false, }) public fetched: boolean; diff --git a/packages/backend/src/models/entities/ad.ts b/packages/backend/src/models/entities/ad.ts index fa4297365..80d54ddd5 100644 --- a/packages/backend/src/models/entities/ad.ts +++ b/packages/backend/src/models/entities/ad.ts @@ -7,45 +7,51 @@ export class Ad { public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the Ad.', + @Column("timestamp with time zone", { + comment: "The created date of the Ad.", }) public createdAt: Date; @Index() - @Column('timestamp with time zone', { - comment: 'The expired date of the Ad.', + @Column("timestamp with time zone", { + comment: "The expired date of the Ad.", }) public expiresAt: Date; - @Column('varchar', { - length: 32, nullable: false, + @Column("varchar", { + length: 32, + nullable: false, }) public place: string; // 今は使われていないが将来的に活用される可能性はある - @Column('varchar', { - length: 32, nullable: false, + @Column("varchar", { + length: 32, + nullable: false, }) public priority: string; - @Column('integer', { - default: 1, nullable: false, + @Column("integer", { + default: 1, + nullable: false, }) public ratio: number; - @Column('varchar', { - length: 1024, nullable: false, + @Column("varchar", { + length: 1024, + nullable: false, }) public url: string; - @Column('varchar', { - length: 1024, nullable: false, + @Column("varchar", { + length: 1024, + nullable: false, }) public imageUrl: string; - @Column('varchar', { - length: 8192, nullable: false, + @Column("varchar", { + length: 8192, + nullable: false, }) public memo: string; diff --git a/packages/backend/src/models/entities/announcement-read.ts b/packages/backend/src/models/entities/announcement-read.ts index 87d0f0e9e..79af9e48e 100644 --- a/packages/backend/src/models/entities/announcement-read.ts +++ b/packages/backend/src/models/entities/announcement-read.ts @@ -11,13 +11,13 @@ import { Announcement } from "./announcement.js"; import { id } from "../id.js"; @Entity() -@Index(['userId', 'announcementId'], { unique: true }) +@Index(["userId", "announcementId"], { unique: true }) export class AnnouncementRead { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the AnnouncementRead.', + @Column("timestamp with time zone", { + comment: "The created date of the AnnouncementRead.", }) public createdAt: Date; @@ -25,8 +25,8 @@ export class AnnouncementRead { @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -35,8 +35,8 @@ export class AnnouncementRead { @Column(id()) public announcementId: Announcement["id"]; - @ManyToOne(type => Announcement, { - onDelete: 'CASCADE', + @ManyToOne((type) => Announcement, { + onDelete: "CASCADE", }) @JoinColumn() public announcement: Announcement | null; diff --git a/packages/backend/src/models/entities/announcement.ts b/packages/backend/src/models/entities/announcement.ts index 9d45af014..1939604b9 100644 --- a/packages/backend/src/models/entities/announcement.ts +++ b/packages/backend/src/models/entities/announcement.ts @@ -7,29 +7,32 @@ export class Announcement { public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the Announcement.', + @Column("timestamp with time zone", { + comment: "The created date of the Announcement.", }) public createdAt: Date; - @Column('timestamp with time zone', { - comment: 'The updated date of the Announcement.', + @Column("timestamp with time zone", { + comment: "The updated date of the Announcement.", nullable: true, }) public updatedAt: Date | null; - @Column('varchar', { - length: 8192, nullable: false, + @Column("varchar", { + length: 8192, + nullable: false, }) public text: string; - @Column('varchar', { - length: 256, nullable: false, + @Column("varchar", { + length: 256, + nullable: false, }) public title: string; - @Column('varchar', { - length: 1024, nullable: true, + @Column("varchar", { + length: 1024, + nullable: true, }) public imageUrl: string | null; diff --git a/packages/backend/src/models/entities/antenna-note.ts b/packages/backend/src/models/entities/antenna-note.ts index c47c796bb..fe982c19e 100644 --- a/packages/backend/src/models/entities/antenna-note.ts +++ b/packages/backend/src/models/entities/antenna-note.ts @@ -11,7 +11,7 @@ import { Antenna } from "./antenna.js"; import { id } from "../id.js"; @Entity() -@Index(['noteId', 'antennaId'], { unique: true }) +@Index(["noteId", "antennaId"], { unique: true }) export class AntennaNote { @PrimaryColumn(id()) public id: string; @@ -19,12 +19,12 @@ export class AntennaNote { @Index() @Column({ ...id(), - comment: 'The note ID.', + comment: "The note ID.", }) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; @@ -32,18 +32,18 @@ export class AntennaNote { @Index() @Column({ ...id(), - comment: 'The antenna ID.', + comment: "The antenna ID.", }) public antennaId: Antenna["id"]; - @ManyToOne(type => Antenna, { - onDelete: 'CASCADE', + @ManyToOne((type) => Antenna, { + onDelete: "CASCADE", }) @JoinColumn() public antenna: Antenna | null; @Index() - @Column('boolean', { + @Column("boolean", { default: false, }) public read: boolean; diff --git a/packages/backend/src/models/entities/antenna.ts b/packages/backend/src/models/entities/antenna.ts index c653b2a05..633dcc1d2 100644 --- a/packages/backend/src/models/entities/antenna.ts +++ b/packages/backend/src/models/entities/antenna.ts @@ -16,31 +16,33 @@ export class Antenna { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the Antenna.', + @Column("timestamp with time zone", { + comment: "The created date of the Antenna.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The owner ID.', + comment: "The owner ID.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('varchar', { + @Column("varchar", { length: 128, - comment: 'The name of the Antenna.', + comment: "The name of the Antenna.", }) public name: string; - @Column('enum', { enum: ['home', 'all', 'users', 'list', 'group', 'instances'] }) + @Column("enum", { + enum: ["home", "all", "users", "list", "group", "instances"], + }) public src: "home" | "all" | "users" | "list" | "group" | "instances"; @Column({ @@ -49,8 +51,8 @@ export class Antenna { }) public userListId: UserList["id"] | null; - @ManyToOne(type => UserList, { - onDelete: 'CASCADE', + @ManyToOne((type) => UserList, { + onDelete: "CASCADE", }) @JoinColumn() public userList: UserList | null; @@ -61,51 +63,53 @@ export class Antenna { }) public userGroupJoiningId: UserGroupJoining["id"] | null; - @ManyToOne(type => UserGroupJoining, { - onDelete: 'CASCADE', + @ManyToOne((type) => UserGroupJoining, { + onDelete: "CASCADE", }) @JoinColumn() public userGroupJoining: UserGroupJoining | null; - @Column('varchar', { - length: 1024, array: true, - default: '{}', + @Column("varchar", { + length: 1024, + array: true, + default: "{}", }) public users: string[]; - @Column('jsonb', { + @Column("jsonb", { default: [], }) public instances: string[]; - @Column('jsonb', { + @Column("jsonb", { default: [], }) public keywords: string[][]; - @Column('jsonb', { + @Column("jsonb", { default: [], }) public excludeKeywords: string[][]; - @Column('boolean', { + @Column("boolean", { default: false, }) public caseSensitive: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public withReplies: boolean; - @Column('boolean') + @Column("boolean") public withFile: boolean; - @Column('varchar', { - length: 2048, nullable: true, + @Column("varchar", { + length: 2048, + nullable: true, }) public expression: string | null; - @Column('boolean') + @Column("boolean") public notify: boolean; } diff --git a/packages/backend/src/models/entities/app.ts b/packages/backend/src/models/entities/app.ts index bb33eede4..a41e35aa9 100644 --- a/packages/backend/src/models/entities/app.ts +++ b/packages/backend/src/models/entities/app.ts @@ -8,8 +8,8 @@ export class App { public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the App.', + @Column("timestamp with time zone", { + comment: "The created date of the App.", }) public createdAt: Date; @@ -17,44 +17,46 @@ export class App { @Column({ ...id(), nullable: true, - comment: 'The owner ID.', + comment: "The owner ID.", }) public userId: User["id"] | null; - @ManyToOne(type => User, { - onDelete: 'SET NULL', + @ManyToOne((type) => User, { + onDelete: "SET NULL", nullable: true, }) public user: User | null; @Index() - @Column('varchar', { + @Column("varchar", { length: 64, - comment: 'The secret key of the App.', + comment: "The secret key of the App.", }) public secret: string; - @Column('varchar', { + @Column("varchar", { length: 128, - comment: 'The name of the App.', + comment: "The name of the App.", }) public name: string; - @Column('varchar', { + @Column("varchar", { length: 512, - comment: 'The description of the App.', + comment: "The description of the App.", }) public description: string; - @Column('varchar', { - length: 64, array: true, - comment: 'The permission of the App.', + @Column("varchar", { + length: 64, + array: true, + comment: "The permission of the App.", }) public permission: string[]; - @Column('varchar', { - length: 512, nullable: true, - comment: 'The callbackUrl of the App.', + @Column("varchar", { + length: 512, + nullable: true, + comment: "The callbackUrl of the App.", }) public callbackUrl: string | null; } diff --git a/packages/backend/src/models/entities/attestation-challenge.ts b/packages/backend/src/models/entities/attestation-challenge.ts index 7a87d42be..6a3a9c8ed 100644 --- a/packages/backend/src/models/entities/attestation-challenge.ts +++ b/packages/backend/src/models/entities/attestation-challenge.ts @@ -18,27 +18,27 @@ export class AttestationChallenge { @PrimaryColumn(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @Index() - @Column('varchar', { + @Column("varchar", { length: 64, - comment: 'Hex-encoded sha256 hash of the challenge.', + comment: "Hex-encoded sha256 hash of the challenge.", }) public challenge: string; - @Column('timestamp with time zone', { - comment: 'The date challenge was created for expiry purposes.', + @Column("timestamp with time zone", { + comment: "The date challenge was created for expiry purposes.", }) public createdAt: Date; - @Column('boolean', { + @Column("boolean", { comment: - 'Indicates that the challenge is only for registration purposes if true to prevent the challenge for being used as authentication.', + "Indicates that the challenge is only for registration purposes if true to prevent the challenge for being used as authentication.", default: false, }) public registrationChallenge: boolean; diff --git a/packages/backend/src/models/entities/auth-session.ts b/packages/backend/src/models/entities/auth-session.ts index b762f8462..b31dca56c 100644 --- a/packages/backend/src/models/entities/auth-session.ts +++ b/packages/backend/src/models/entities/auth-session.ts @@ -15,13 +15,13 @@ export class AuthSession { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the AuthSession.', + @Column("timestamp with time zone", { + comment: "The created date of the AuthSession.", }) public createdAt: Date; @Index() - @Column('varchar', { + @Column("varchar", { length: 128, }) public token: string; @@ -32,8 +32,8 @@ export class AuthSession { }) public userId: User["id"] | null; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", nullable: true, }) @JoinColumn() @@ -42,8 +42,8 @@ export class AuthSession { @Column(id()) public appId: App["id"]; - @ManyToOne(type => App, { - onDelete: 'CASCADE', + @ManyToOne((type) => App, { + onDelete: "CASCADE", }) @JoinColumn() public app: App | null; diff --git a/packages/backend/src/models/entities/blocking.ts b/packages/backend/src/models/entities/blocking.ts index 3a44a4d65..55f677a98 100644 --- a/packages/backend/src/models/entities/blocking.ts +++ b/packages/backend/src/models/entities/blocking.ts @@ -10,26 +10,26 @@ import { User } from "./user.js"; import { id } from "../id.js"; @Entity() -@Index(['blockerId', 'blockeeId'], { unique: true }) +@Index(["blockerId", "blockeeId"], { unique: true }) export class Blocking { @PrimaryColumn(id()) public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the Blocking.', + @Column("timestamp with time zone", { + comment: "The created date of the Blocking.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The blockee user ID.', + comment: "The blockee user ID.", }) public blockeeId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public blockee: User | null; @@ -37,12 +37,12 @@ export class Blocking { @Index() @Column({ ...id(), - comment: 'The blocker user ID.', + comment: "The blocker user ID.", }) public blockerId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public blocker: User | null; diff --git a/packages/backend/src/models/entities/channel-following.ts b/packages/backend/src/models/entities/channel-following.ts index 04ec193e1..ee329fa50 100644 --- a/packages/backend/src/models/entities/channel-following.ts +++ b/packages/backend/src/models/entities/channel-following.ts @@ -11,26 +11,26 @@ import { id } from "../id.js"; import { Channel } from "./channel.js"; @Entity() -@Index(['followerId', 'followeeId'], { unique: true }) +@Index(["followerId", "followeeId"], { unique: true }) export class ChannelFollowing { @PrimaryColumn(id()) public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the ChannelFollowing.', + @Column("timestamp with time zone", { + comment: "The created date of the ChannelFollowing.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The followee channel ID.', + comment: "The followee channel ID.", }) public followeeId: Channel["id"]; - @ManyToOne(type => Channel, { - onDelete: 'CASCADE', + @ManyToOne((type) => Channel, { + onDelete: "CASCADE", }) @JoinColumn() public followee: Channel | null; @@ -38,12 +38,12 @@ export class ChannelFollowing { @Index() @Column({ ...id(), - comment: 'The follower user ID.', + comment: "The follower user ID.", }) public followerId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public follower: User | null; diff --git a/packages/backend/src/models/entities/channel-note-pining.ts b/packages/backend/src/models/entities/channel-note-pining.ts index bd13f4ca3..67d1d48cc 100644 --- a/packages/backend/src/models/entities/channel-note-pining.ts +++ b/packages/backend/src/models/entities/channel-note-pining.ts @@ -11,13 +11,13 @@ import { Channel } from "./channel.js"; import { id } from "../id.js"; @Entity() -@Index(['channelId', 'noteId'], { unique: true }) +@Index(["channelId", "noteId"], { unique: true }) export class ChannelNotePining { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the ChannelNotePining.', + @Column("timestamp with time zone", { + comment: "The created date of the ChannelNotePining.", }) public createdAt: Date; @@ -25,8 +25,8 @@ export class ChannelNotePining { @Column(id()) public channelId: Channel["id"]; - @ManyToOne(type => Channel, { - onDelete: 'CASCADE', + @ManyToOne((type) => Channel, { + onDelete: "CASCADE", }) @JoinColumn() public channel: Channel | null; @@ -34,8 +34,8 @@ export class ChannelNotePining { @Column(id()) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; diff --git a/packages/backend/src/models/entities/channel.ts b/packages/backend/src/models/entities/channel.ts index 7f9851dbf..ea22fed50 100644 --- a/packages/backend/src/models/entities/channel.ts +++ b/packages/backend/src/models/entities/channel.ts @@ -16,13 +16,13 @@ export class Channel { public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the Channel.', + @Column("timestamp with time zone", { + comment: "The created date of the Channel.", }) public createdAt: Date; @Index() - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, }) public lastNotedAt: Date | null; @@ -31,52 +31,53 @@ export class Channel { @Column({ ...id(), nullable: true, - comment: 'The owner ID.', + comment: "The owner ID.", }) public userId: User["id"] | null; - @ManyToOne(type => User, { - onDelete: 'SET NULL', + @ManyToOne((type) => User, { + onDelete: "SET NULL", }) @JoinColumn() public user: User | null; - @Column('varchar', { + @Column("varchar", { length: 128, - comment: 'The name of the Channel.', + comment: "The name of the Channel.", }) public name: string; - @Column('varchar', { - length: 2048, nullable: true, - comment: 'The description of the Channel.', + @Column("varchar", { + length: 2048, + nullable: true, + comment: "The description of the Channel.", }) public description: string | null; @Column({ ...id(), nullable: true, - comment: 'The ID of banner Channel.', + comment: "The ID of banner Channel.", }) public bannerId: DriveFile["id"] | null; - @ManyToOne(type => DriveFile, { - onDelete: 'SET NULL', + @ManyToOne((type) => DriveFile, { + onDelete: "SET NULL", }) @JoinColumn() public banner: DriveFile | null; @Index() - @Column('integer', { + @Column("integer", { default: 0, - comment: 'The count of notes.', + comment: "The count of notes.", }) public notesCount: number; @Index() - @Column('integer', { + @Column("integer", { default: 0, - comment: 'The count of users.', + comment: "The count of users.", }) public usersCount: number; } diff --git a/packages/backend/src/models/entities/clip-note.ts b/packages/backend/src/models/entities/clip-note.ts index bc51daaf4..1697474a8 100644 --- a/packages/backend/src/models/entities/clip-note.ts +++ b/packages/backend/src/models/entities/clip-note.ts @@ -11,7 +11,7 @@ import { Clip } from "./clip.js"; import { id } from "../id.js"; @Entity() -@Index(['noteId', 'clipId'], { unique: true }) +@Index(["noteId", "clipId"], { unique: true }) export class ClipNote { @PrimaryColumn(id()) public id: string; @@ -19,12 +19,12 @@ export class ClipNote { @Index() @Column({ ...id(), - comment: 'The note ID.', + comment: "The note ID.", }) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; @@ -32,12 +32,12 @@ export class ClipNote { @Index() @Column({ ...id(), - comment: 'The clip ID.', + comment: "The clip ID.", }) public clipId: Clip["id"]; - @ManyToOne(type => Clip, { - onDelete: 'CASCADE', + @ManyToOne((type) => Clip, { + onDelete: "CASCADE", }) @JoinColumn() public clip: Clip | null; diff --git a/packages/backend/src/models/entities/clip.ts b/packages/backend/src/models/entities/clip.ts index 10591cbee..9554703a4 100644 --- a/packages/backend/src/models/entities/clip.ts +++ b/packages/backend/src/models/entities/clip.ts @@ -14,38 +14,39 @@ export class Clip { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the Clip.', + @Column("timestamp with time zone", { + comment: "The created date of the Clip.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The owner ID.', + comment: "The owner ID.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('varchar', { + @Column("varchar", { length: 128, - comment: 'The name of the Clip.', + comment: "The name of the Clip.", }) public name: string; - @Column('boolean', { + @Column("boolean", { default: false, }) public isPublic: boolean; - @Column('varchar', { - length: 2048, nullable: true, - comment: 'The description of the Clip.', + @Column("varchar", { + length: 2048, + nullable: true, + comment: "The description of the Clip.", }) public description: string | null; } diff --git a/packages/backend/src/models/entities/drive-file.ts b/packages/backend/src/models/entities/drive-file.ts index 32e19bc6e..d8b54fa19 100644 --- a/packages/backend/src/models/entities/drive-file.ts +++ b/packages/backend/src/models/entities/drive-file.ts @@ -12,14 +12,14 @@ import { DriveFolder } from "./drive-folder.js"; import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js"; @Entity() -@Index(['userId', 'folderId', 'id']) +@Index(["userId", "folderId", "id"]) export class DriveFile { @PrimaryColumn(id()) public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the DriveFile.', + @Column("timestamp with time zone", { + comment: "The created date of the DriveFile.", }) public createdAt: Date; @@ -27,64 +27,67 @@ export class DriveFile { @Column({ ...id(), nullable: true, - comment: 'The owner ID.', + comment: "The owner ID.", }) public userId: User["id"] | null; - @ManyToOne(type => User, { - onDelete: 'SET NULL', + @ManyToOne((type) => User, { + onDelete: "SET NULL", }) @JoinColumn() public user: User | null; @Index() - @Column('varchar', { - length: 128, nullable: true, - comment: 'The host of owner. It will be null if the user in local.', + @Column("varchar", { + length: 128, + nullable: true, + comment: "The host of owner. It will be null if the user in local.", }) public userHost: string | null; @Index() - @Column('varchar', { + @Column("varchar", { length: 32, - comment: 'The MD5 hash of the DriveFile.', + comment: "The MD5 hash of the DriveFile.", }) public md5: string; - @Column('varchar', { + @Column("varchar", { length: 256, - comment: 'The file name of the DriveFile.', + comment: "The file name of the DriveFile.", }) public name: string; @Index() - @Column('varchar', { + @Column("varchar", { length: 128, - comment: 'The content type (MIME) of the DriveFile.', + comment: "The content type (MIME) of the DriveFile.", }) public type: string; - @Column('integer', { - comment: 'The file size (bytes) of the DriveFile.', + @Column("integer", { + comment: "The file size (bytes) of the DriveFile.", }) public size: number; - @Column('varchar', { + @Column("varchar", { length: DB_MAX_IMAGE_COMMENT_LENGTH, nullable: true, - comment: 'The comment of the DriveFile.', + comment: "The comment of the DriveFile.", }) public comment: string | null; - @Column('varchar', { - length: 128, nullable: true, - comment: 'The BlurHash string.', + @Column("varchar", { + length: 128, + nullable: true, + comment: "The BlurHash string.", }) public blurhash: string | null; - @Column('jsonb', { + @Column("jsonb", { default: {}, - comment: 'The any properties of the DriveFile. For example, it includes image width/height.', + comment: + "The any properties of the DriveFile. For example, it includes image width/height.", }) public properties: { width?: number; @@ -93,59 +96,68 @@ export class DriveFile { avgColor?: string; }; - @Column('boolean') + @Column("boolean") public storedInternal: boolean; - @Column('varchar', { + @Column("varchar", { length: 512, - comment: 'The URL of the DriveFile.', + comment: "The URL of the DriveFile.", }) public url: string; - @Column('varchar', { - length: 512, nullable: true, - comment: 'The URL of the thumbnail of the DriveFile.', + @Column("varchar", { + length: 512, + nullable: true, + comment: "The URL of the thumbnail of the DriveFile.", }) public thumbnailUrl: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: 'The URL of the webpublic of the DriveFile.', + @Column("varchar", { + length: 512, + nullable: true, + comment: "The URL of the webpublic of the DriveFile.", }) public webpublicUrl: string | null; - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public webpublicType: string | null; @Index({ unique: true }) - @Column('varchar', { - length: 256, nullable: true, + @Column("varchar", { + length: 256, + nullable: true, }) public accessKey: string | null; @Index({ unique: true }) - @Column('varchar', { - length: 256, nullable: true, + @Column("varchar", { + length: 256, + nullable: true, }) public thumbnailAccessKey: string | null; @Index({ unique: true }) - @Column('varchar', { - length: 256, nullable: true, + @Column("varchar", { + length: 256, + nullable: true, }) public webpublicAccessKey: string | null; @Index() - @Column('varchar', { - length: 512, nullable: true, - comment: 'The URI of the DriveFile. it will be null when the DriveFile is local.', + @Column("varchar", { + length: 512, + nullable: true, + comment: + "The URI of the DriveFile. it will be null when the DriveFile is local.", }) public uri: string | null; - @Column('varchar', { - length: 512, nullable: true, + @Column("varchar", { + length: 512, + nullable: true, }) public src: string | null; @@ -153,32 +165,33 @@ export class DriveFile { @Column({ ...id(), nullable: true, - comment: 'The parent folder ID. If null, it means the DriveFile is located in root.', + comment: + "The parent folder ID. If null, it means the DriveFile is located in root.", }) public folderId: DriveFolder["id"] | null; - @ManyToOne(type => DriveFolder, { - onDelete: 'SET NULL', + @ManyToOne((type) => DriveFolder, { + onDelete: "SET NULL", }) @JoinColumn() public folder: DriveFolder | null; @Index() - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the DriveFile is NSFW.', + comment: "Whether the DriveFile is NSFW.", }) public isSensitive: boolean; @Index() - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the DriveFile is NSFW. (predict)', + comment: "Whether the DriveFile is NSFW. (predict)", }) public maybeSensitive: boolean; @Index() - @Column('boolean', { + @Column("boolean", { default: false, }) public maybePorn: boolean; @@ -187,20 +200,21 @@ export class DriveFile { * 外部の(信頼されていない)URLへの直リンクか否か */ @Index() - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the DriveFile is direct link to remote server.', + comment: "Whether the DriveFile is direct link to remote server.", }) public isLink: boolean; - @Column('jsonb', { + @Column("jsonb", { default: {}, nullable: true, }) public requestHeaders: Record | null; - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public requestIp: string | null; } diff --git a/packages/backend/src/models/entities/drive-folder.ts b/packages/backend/src/models/entities/drive-folder.ts index 77031ce4e..0bb2c7a3d 100644 --- a/packages/backend/src/models/entities/drive-folder.ts +++ b/packages/backend/src/models/entities/drive-folder.ts @@ -15,14 +15,14 @@ export class DriveFolder { public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the DriveFolder.', + @Column("timestamp with time zone", { + comment: "The created date of the DriveFolder.", }) public createdAt: Date; - @Column('varchar', { + @Column("varchar", { length: 128, - comment: 'The name of the DriveFolder.', + comment: "The name of the DriveFolder.", }) public name: string; @@ -30,12 +30,12 @@ export class DriveFolder { @Column({ ...id(), nullable: true, - comment: 'The owner ID.', + comment: "The owner ID.", }) public userId: User["id"] | null; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -44,12 +44,13 @@ export class DriveFolder { @Column({ ...id(), nullable: true, - comment: 'The parent folder ID. If null, it means the DriveFolder is located in root.', + comment: + "The parent folder ID. If null, it means the DriveFolder is located in root.", }) public parentId: DriveFolder["id"] | null; - @ManyToOne(type => DriveFolder, { - onDelete: 'SET NULL', + @ManyToOne((type) => DriveFolder, { + onDelete: "SET NULL", }) @JoinColumn() public parent: DriveFolder | null; diff --git a/packages/backend/src/models/entities/emoji.ts b/packages/backend/src/models/entities/emoji.ts index 773265d91..727ba2f10 100644 --- a/packages/backend/src/models/entities/emoji.ts +++ b/packages/backend/src/models/entities/emoji.ts @@ -2,73 +2,82 @@ import { PrimaryColumn, Entity, Index, Column } from "typeorm"; import { id } from "../id.js"; @Entity() -@Index(['name', 'host'], { unique: true }) +@Index(["name", "host"], { unique: true }) export class Emoji { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, }) public updatedAt: Date | null; @Index() - @Column('varchar', { + @Column("varchar", { length: 128, }) public name: string; @Index() - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public host: string | null; - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public category: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, }) public originalUrl: string; - @Column('varchar', { + @Column("varchar", { length: 512, - default: '', + default: "", }) public publicUrl: string; - @Column('varchar', { - length: 512, nullable: true, + @Column("varchar", { + length: 512, + nullable: true, }) public uri: string | null; // publicUrlの方のtypeが入る // (mime) - @Column('varchar', { - length: 64, nullable: true, + @Column("varchar", { + length: 64, + nullable: true, }) public type: string | null; - @Column('varchar', { - array: true, length: 128, default: '{}', + @Column("varchar", { + array: true, + length: 128, + default: "{}", }) public aliases: string[]; - @Column('varchar', { - length: 1024, nullable: true, + @Column("varchar", { + length: 1024, + nullable: true, }) public license: string | null; - @Column('integer', { - nullable: true, comment: 'Image width', + @Column("integer", { + nullable: true, + comment: "Image width", }) public width: number | null; - @Column('integer', { - nullable: true, comment: "Image height", + @Column("integer", { + nullable: true, + comment: "Image height", }) public height: number | null; } diff --git a/packages/backend/src/models/entities/follow-request.ts b/packages/backend/src/models/entities/follow-request.ts index 658fed5a5..281eab917 100644 --- a/packages/backend/src/models/entities/follow-request.ts +++ b/packages/backend/src/models/entities/follow-request.ts @@ -10,25 +10,25 @@ import { User } from "./user.js"; import { id } from "../id.js"; @Entity() -@Index(['followerId', 'followeeId'], { unique: true }) +@Index(["followerId", "followeeId"], { unique: true }) export class FollowRequest { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the FollowRequest.', + @Column("timestamp with time zone", { + comment: "The created date of the FollowRequest.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The followee user ID.', + comment: "The followee user ID.", }) public followeeId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public followee: User | null; @@ -36,56 +36,63 @@ export class FollowRequest { @Index() @Column({ ...id(), - comment: 'The follower user ID.', + comment: "The follower user ID.", }) public followerId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public follower: User | null; - @Column('varchar', { - length: 128, nullable: true, - comment: 'id of Follow Activity.', + @Column("varchar", { + length: 128, + nullable: true, + comment: "id of Follow Activity.", }) public requestId: string | null; //#region Denormalized fields - @Column('varchar', { - length: 128, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 128, + nullable: true, + comment: "[Denormalized]", }) public followerHost: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 512, + nullable: true, + comment: "[Denormalized]", }) public followerInbox: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 512, + nullable: true, + comment: "[Denormalized]", }) public followerSharedInbox: string | null; - @Column('varchar', { - length: 128, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 128, + nullable: true, + comment: "[Denormalized]", }) public followeeHost: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 512, + nullable: true, + comment: "[Denormalized]", }) public followeeInbox: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 512, + nullable: true, + comment: "[Denormalized]", }) public followeeSharedInbox: string | null; //#endregion diff --git a/packages/backend/src/models/entities/following.ts b/packages/backend/src/models/entities/following.ts index 11f633fcd..fafcf8885 100644 --- a/packages/backend/src/models/entities/following.ts +++ b/packages/backend/src/models/entities/following.ts @@ -10,26 +10,26 @@ import { User } from "./user.js"; import { id } from "../id.js"; @Entity() -@Index(['followerId', 'followeeId'], { unique: true }) +@Index(["followerId", "followeeId"], { unique: true }) export class Following { @PrimaryColumn(id()) public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the Following.', + @Column("timestamp with time zone", { + comment: "The created date of the Following.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The followee user ID.', + comment: "The followee user ID.", }) public followeeId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public followee: User | null; @@ -37,52 +37,58 @@ export class Following { @Index() @Column({ ...id(), - comment: 'The follower user ID.', + comment: "The follower user ID.", }) public followerId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public follower: User | null; //#region Denormalized fields @Index() - @Column('varchar', { - length: 128, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 128, + nullable: true, + comment: "[Denormalized]", }) public followerHost: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 512, + nullable: true, + comment: "[Denormalized]", }) public followerInbox: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 512, + nullable: true, + comment: "[Denormalized]", }) public followerSharedInbox: string | null; @Index() - @Column('varchar', { - length: 128, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 128, + nullable: true, + comment: "[Denormalized]", }) public followeeHost: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 512, + nullable: true, + comment: "[Denormalized]", }) public followeeInbox: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 512, + nullable: true, + comment: "[Denormalized]", }) public followeeSharedInbox: string | null; //#endregion diff --git a/packages/backend/src/models/entities/gallery-like.ts b/packages/backend/src/models/entities/gallery-like.ts index e74e3c3ce..259feb8bb 100644 --- a/packages/backend/src/models/entities/gallery-like.ts +++ b/packages/backend/src/models/entities/gallery-like.ts @@ -11,20 +11,20 @@ import { id } from "../id.js"; import { GalleryPost } from "./gallery-post.js"; @Entity() -@Index(['userId', 'postId'], { unique: true }) +@Index(["userId", "postId"], { unique: true }) export class GalleryLike { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone') + @Column("timestamp with time zone") public createdAt: Date; @Index() @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -32,8 +32,8 @@ export class GalleryLike { @Column(id()) public postId: GalleryPost["id"]; - @ManyToOne(type => GalleryPost, { - onDelete: 'CASCADE', + @ManyToOne((type) => GalleryPost, { + onDelete: "CASCADE", }) @JoinColumn() public post: GalleryPost | null; diff --git a/packages/backend/src/models/entities/gallery-post.ts b/packages/backend/src/models/entities/gallery-post.ts index a79bb8835..938348659 100644 --- a/packages/backend/src/models/entities/gallery-post.ts +++ b/packages/backend/src/models/entities/gallery-post.ts @@ -16,36 +16,37 @@ export class GalleryPost { public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the GalleryPost.', + @Column("timestamp with time zone", { + comment: "The created date of the GalleryPost.", }) public createdAt: Date; @Index() - @Column('timestamp with time zone', { - comment: 'The updated date of the GalleryPost.', + @Column("timestamp with time zone", { + comment: "The updated date of the GalleryPost.", }) public updatedAt: Date; - @Column('varchar', { + @Column("varchar", { length: 256, }) public title: string; - @Column('varchar', { - length: 2048, nullable: true, + @Column("varchar", { + length: 2048, + nullable: true, }) public description: string | null; @Index() @Column({ ...id(), - comment: 'The ID of author.', + comment: "The ID of author.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -53,26 +54,29 @@ export class GalleryPost { @Index() @Column({ ...id(), - array: true, default: '{}', + array: true, + default: "{}", }) public fileIds: DriveFile["id"][]; @Index() - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the post is sensitive.', + comment: "Whether the post is sensitive.", }) public isSensitive: boolean; @Index() - @Column('integer', { + @Column("integer", { default: 0, }) public likedCount: number; @Index() - @Column('varchar', { - length: 128, array: true, default: '{}', + @Column("varchar", { + length: 128, + array: true, + default: "{}", }) public tags: string[]; diff --git a/packages/backend/src/models/entities/hashtag.ts b/packages/backend/src/models/entities/hashtag.ts index 06fa004be..7b3df1cc2 100644 --- a/packages/backend/src/models/entities/hashtag.ts +++ b/packages/backend/src/models/entities/hashtag.ts @@ -8,7 +8,7 @@ export class Hashtag { public id: string; @Index({ unique: true }) - @Column('varchar', { + @Column("varchar", { length: 128, }) public name: string; @@ -20,7 +20,7 @@ export class Hashtag { public mentionedUserIds: User["id"][]; @Index() - @Column('integer', { + @Column("integer", { default: 0, }) public mentionedUsersCount: number; @@ -32,7 +32,7 @@ export class Hashtag { public mentionedLocalUserIds: User["id"][]; @Index() - @Column('integer', { + @Column("integer", { default: 0, }) public mentionedLocalUsersCount: number; @@ -44,7 +44,7 @@ export class Hashtag { public mentionedRemoteUserIds: User["id"][]; @Index() - @Column('integer', { + @Column("integer", { default: 0, }) public mentionedRemoteUsersCount: number; @@ -56,7 +56,7 @@ export class Hashtag { public attachedUserIds: User["id"][]; @Index() - @Column('integer', { + @Column("integer", { default: 0, }) public attachedUsersCount: number; @@ -68,7 +68,7 @@ export class Hashtag { public attachedLocalUserIds: User["id"][]; @Index() - @Column('integer', { + @Column("integer", { default: 0, }) public attachedLocalUsersCount: number; @@ -80,7 +80,7 @@ export class Hashtag { public attachedRemoteUserIds: User["id"][]; @Index() - @Column('integer', { + @Column("integer", { default: 0, }) public attachedRemoteUsersCount: number; diff --git a/packages/backend/src/models/entities/instance.ts b/packages/backend/src/models/entities/instance.ts index 2b118455d..7e0b08583 100644 --- a/packages/backend/src/models/entities/instance.ts +++ b/packages/backend/src/models/entities/instance.ts @@ -10,8 +10,8 @@ export class Instance { * このインスタンスを捕捉した日時 */ @Index() - @Column('timestamp with time zone', { - comment: 'The caught date of the Instance.', + @Column("timestamp with time zone", { + comment: "The caught date of the Instance.", }) public caughtAt: Date; @@ -19,34 +19,34 @@ export class Instance { * ホスト */ @Index({ unique: true }) - @Column('varchar', { + @Column("varchar", { length: 128, - comment: 'The host of the Instance.', + comment: "The host of the Instance.", }) public host: string; /** * インスタンスのユーザー数 */ - @Column('integer', { + @Column("integer", { default: 0, - comment: 'The count of the users of the Instance.', + comment: "The count of the users of the Instance.", }) public usersCount: number; /** * インスタンスの投稿数 */ - @Column('integer', { + @Column("integer", { default: 0, - comment: 'The count of the notes of the Instance.', + comment: "The count of the notes of the Instance.", }) public notesCount: number; /** * このインスタンスのユーザーからフォローされている、自インスタンスのユーザーの数 */ - @Column('integer', { + @Column("integer", { default: 0, }) public followingCount: number; @@ -54,7 +54,7 @@ export class Instance { /** * このインスタンスのユーザーをフォローしている、自インスタンスのユーザーの数 */ - @Column('integer', { + @Column("integer", { default: 0, }) public followersCount: number; @@ -62,7 +62,7 @@ export class Instance { /** * 直近のリクエスト送信日時 */ - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, }) public latestRequestSentAt: Date | null; @@ -70,7 +70,7 @@ export class Instance { /** * 直近のリクエスト送信時のHTTPステータスコード */ - @Column('integer', { + @Column("integer", { nullable: true, }) public latestStatus: number | null; @@ -78,7 +78,7 @@ export class Instance { /** * 直近のリクエスト受信日時 */ - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, }) public latestRequestReceivedAt: Date | null; @@ -86,13 +86,13 @@ export class Instance { /** * このインスタンスと最後にやり取りした日時 */ - @Column('timestamp with time zone') + @Column("timestamp with time zone") public lastCommunicatedAt: Date; /** * このインスタンスと不通かどうか */ - @Column('boolean', { + @Column("boolean", { default: false, }) public isNotResponding: boolean; @@ -101,63 +101,72 @@ export class Instance { * このインスタンスへの配信を停止するか */ @Index() - @Column('boolean', { + @Column("boolean", { default: false, }) public isSuspended: boolean; - @Column('varchar', { - length: 64, nullable: true, - comment: 'The software of the Instance.', + @Column("varchar", { + length: 64, + nullable: true, + comment: "The software of the Instance.", }) public softwareName: string | null; - @Column('varchar', { - length: 64, nullable: true, + @Column("varchar", { + length: 64, + nullable: true, }) public softwareVersion: string | null; - @Column('boolean', { + @Column("boolean", { nullable: true, }) public openRegistrations: boolean | null; - @Column('varchar', { - length: 256, nullable: true, + @Column("varchar", { + length: 256, + nullable: true, }) public name: string | null; - @Column('varchar', { - length: 4096, nullable: true, + @Column("varchar", { + length: 4096, + nullable: true, }) public description: string | null; - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public maintainerName: string | null; - @Column('varchar', { - length: 256, nullable: true, + @Column("varchar", { + length: 256, + nullable: true, }) public maintainerEmail: string | null; - @Column('varchar', { - length: 256, nullable: true, + @Column("varchar", { + length: 256, + nullable: true, }) public iconUrl: string | null; - @Column('varchar', { - length: 256, nullable: true, + @Column("varchar", { + length: 256, + nullable: true, }) public faviconUrl: string | null; - @Column('varchar', { - length: 64, nullable: true, + @Column("varchar", { + length: 64, + nullable: true, }) public themeColor: string | null; - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, }) public infoUpdatedAt: Date | null; diff --git a/packages/backend/src/models/entities/messaging-message.ts b/packages/backend/src/models/entities/messaging-message.ts index 9cf197fa3..d1da00eae 100644 --- a/packages/backend/src/models/entities/messaging-message.ts +++ b/packages/backend/src/models/entities/messaging-message.ts @@ -17,68 +17,73 @@ export class MessagingMessage { public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the MessagingMessage.', + @Column("timestamp with time zone", { + comment: "The created date of the MessagingMessage.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The sender user ID.', + comment: "The sender user ID.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @Index() @Column({ - ...id(), nullable: true, - comment: 'The recipient user ID.', + ...id(), + nullable: true, + comment: "The recipient user ID.", }) public recipientId: User["id"] | null; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public recipient: User | null; @Index() @Column({ - ...id(), nullable: true, - comment: 'The recipient group ID.', + ...id(), + nullable: true, + comment: "The recipient group ID.", }) public groupId: UserGroup["id"] | null; - @ManyToOne(type => UserGroup, { - onDelete: 'CASCADE', + @ManyToOne((type) => UserGroup, { + onDelete: "CASCADE", }) @JoinColumn() public group: UserGroup | null; - @Column('varchar', { - length: 4096, nullable: true, + @Column("varchar", { + length: 4096, + nullable: true, }) public text: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public isRead: boolean; - @Column('varchar', { - length: 512, nullable: true, + @Column("varchar", { + length: 512, + nullable: true, }) public uri: string | null; @Column({ ...id(), - array: true, default: '{}', + array: true, + default: "{}", }) public reads: User["id"][]; @@ -88,8 +93,8 @@ export class MessagingMessage { }) public fileId: DriveFile["id"] | null; - @ManyToOne(type => DriveFile, { - onDelete: 'CASCADE', + @ManyToOne((type) => DriveFile, { + onDelete: "CASCADE", }) @JoinColumn() public file: DriveFile | null; diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index 3a3c50d4a..b22c6510f 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -6,119 +6,144 @@ import type { Clip } from "./clip.js"; @Entity() export class Meta { @PrimaryColumn({ - type: 'varchar', + type: "varchar", length: 32, }) public id: string; - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public name: string | null; - @Column('varchar', { - length: 1024, nullable: true, + @Column("varchar", { + length: 1024, + nullable: true, }) public description: string | null; /** * メンテナの名前 */ - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public maintainerName: string | null; /** * メンテナの連絡先 */ - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public maintainerEmail: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public disableRegistration: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public disableLocalTimeline: boolean; - @Column('boolean', { + @Column("boolean", { default: true, }) public disableRecommendedTimeline: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public disableGlobalTimeline: boolean; - @Column('varchar', { - length: 256, default: '⭐', + @Column("varchar", { + length: 256, + default: "⭐", }) public defaultReaction: string; - @Column('varchar', { - length: 64, array: true, default: '{}', + @Column("varchar", { + length: 64, + array: true, + default: "{}", }) public langs: string[]; - @Column('varchar', { - length: 256, array: true, default: '{}', + @Column("varchar", { + length: 256, + array: true, + default: "{}", }) public pinnedUsers: string[]; - @Column('varchar', { - length: 256, array: true, default: '{}', + @Column("varchar", { + length: 256, + array: true, + default: "{}", }) public recommendedInstances: string[]; - @Column('varchar', { - length: 256, array: true, default: '{}', + @Column("varchar", { + length: 256, + array: true, + default: "{}", }) public customMOTD: string[]; - @Column('varchar', { - length: 256, array: true, default: '{}', + @Column("varchar", { + length: 256, + array: true, + default: "{}", }) public customSplashIcons: string[]; - @Column('varchar', { - length: 256, array: true, default: '{}', + @Column("varchar", { + length: 256, + array: true, + default: "{}", }) public hiddenTags: string[]; - @Column('varchar', { - length: 256, array: true, default: '{}', + @Column("varchar", { + length: 256, + array: true, + default: "{}", }) public blockedHosts: string[]; - @Column('varchar', { - length: 256, array: true, default: '{}', + @Column("varchar", { + length: 256, + array: true, + default: "{}", }) public silencedHosts: string[]; - @Column('boolean', { + @Column("boolean", { default: false, }) public secureMode: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public privateMode: boolean; - @Column('varchar', { - length: 256, array: true, default: '{}', + @Column("varchar", { + length: 256, + array: true, + default: "{}", }) public allowedHosts: string[]; - @Column('varchar', { - length: 512, array: true, default: '{/featured,/channels,/explore,/pages,/about-calckey}', + @Column("varchar", { + length: 512, + array: true, + default: "{/featured,/channels,/explore,/pages,/about-calckey}", }) public pinnedPages: string[]; @@ -128,51 +153,51 @@ export class Meta { }) public pinnedClipId: Clip["id"] | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public themeColor: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, - default: '/assets/ai.png', + default: "/static-assets/badges/info.png", }) public mascotImageUrl: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public bannerUrl: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public backgroundImageUrl: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public logoImageUrl: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, - default: 'https://xn--931a.moe/aiart/yubitun.png', + default: "/static-assets/badges/error.png", }) public errorImageUrl: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public iconUrl: string | null; - @Column('boolean', { + @Column("boolean", { default: true, }) public cacheRemoteFiles: boolean; @@ -183,60 +208,60 @@ export class Meta { }) public proxyAccountId: User["id"] | null; - @ManyToOne(type => User, { - onDelete: 'SET NULL', + @ManyToOne((type) => User, { + onDelete: "SET NULL", }) @JoinColumn() public proxyAccount: User | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public emailRequiredForSignup: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public enableHcaptcha: boolean; - @Column('varchar', { + @Column("varchar", { length: 64, nullable: true, }) public hcaptchaSiteKey: string | null; - @Column('varchar', { + @Column("varchar", { length: 64, nullable: true, }) public hcaptchaSecretKey: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public enableRecaptcha: boolean; - @Column('varchar', { + @Column("varchar", { length: 64, nullable: true, }) public recaptchaSiteKey: string | null; - @Column('varchar', { + @Column("varchar", { length: 64, nullable: true, }) public recaptchaSecretKey: string | null; - @Column('enum', { - enum: ['none', 'all', 'local', 'remote'], - default: 'none', + @Column("enum", { + enum: ["none", "all", "local", "remote"], + default: "none", }) public sensitiveMediaDetection: "none" | "all" | "local" | "remote"; - @Column('enum', { - enum: ['medium', 'low', 'high', 'veryLow', 'veryHigh'], - default: 'medium', + @Column("enum", { + enum: ["medium", "low", "high", "veryLow", "veryHigh"], + default: "medium", }) public sensitiveMediaDetectionSensitivity: | "medium" @@ -245,279 +270,279 @@ export class Meta { | "veryLow" | "veryHigh"; - @Column('boolean', { + @Column("boolean", { default: false, }) public setSensitiveFlagAutomatically: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public enableSensitiveMediaDetectionForVideos: boolean; - @Column('integer', { + @Column("integer", { default: 1024, - comment: 'Drive capacity of a local user (MB)', + comment: "Drive capacity of a local user (MB)", }) public localDriveCapacityMb: number; - @Column('integer', { + @Column("integer", { default: 32, - comment: 'Drive capacity of a remote user (MB)', + comment: "Drive capacity of a remote user (MB)", }) public remoteDriveCapacityMb: number; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public summalyProxy: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public enableEmail: boolean; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public email: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public smtpSecure: boolean; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public smtpHost: string | null; - @Column('integer', { + @Column("integer", { nullable: true, }) public smtpPort: number | null; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public smtpUser: string | null; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public smtpPass: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public enableServiceWorker: boolean; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public swPublicKey: string | null; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public swPrivateKey: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public enableTwitterIntegration: boolean; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public twitterConsumerKey: string | null; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public twitterConsumerSecret: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public enableGithubIntegration: boolean; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public githubClientId: string | null; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public githubClientSecret: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public enableDiscordIntegration: boolean; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public discordClientId: string | null; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public discordClientSecret: string | null; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public deeplAuthKey: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public deeplIsPro: boolean; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public libreTranslateApiUrl: string | null; - @Column('varchar', { + @Column("varchar", { length: 128, nullable: true, }) public libreTranslateApiKey: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public ToSUrl: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, - default: 'https://codeberg.org/calckey/calckey', + default: "https://codeberg.org/calckey/calckey", nullable: false, }) public repositoryUrl: string; - @Column('varchar', { + @Column("varchar", { length: 512, - default: 'https://codeberg.org/calckey/calckey/issues/new', + default: "https://codeberg.org/calckey/calckey/issues/new", nullable: true, }) public feedbackUrl: string | null; - @Column('varchar', { + @Column("varchar", { length: 8192, nullable: true, }) public defaultLightTheme: string | null; - @Column('varchar', { + @Column("varchar", { length: 8192, nullable: true, }) public defaultDarkTheme: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public useObjectStorage: boolean; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public objectStorageBucket: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public objectStoragePrefix: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public objectStorageBaseUrl: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public objectStorageEndpoint: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public objectStorageRegion: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public objectStorageAccessKey: string | null; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, }) public objectStorageSecretKey: string | null; - @Column('integer', { + @Column("integer", { nullable: true, }) public objectStoragePort: number | null; - @Column('boolean', { + @Column("boolean", { default: true, }) public objectStorageUseSSL: boolean; - @Column('boolean', { + @Column("boolean", { default: true, }) public objectStorageUseProxy: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public objectStorageSetPublicRead: boolean; - @Column('boolean', { + @Column("boolean", { default: true, }) public objectStorageS3ForcePathStyle: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public enableIpLogging: boolean; - @Column('boolean', { + @Column("boolean", { default: true, }) public enableActiveEmailValidation: boolean; - @Column('jsonb', { + @Column("jsonb", { default: {}, }) public experimentalFeatures: Record; diff --git a/packages/backend/src/models/entities/moderation-log.ts b/packages/backend/src/models/entities/moderation-log.ts index cc745e0d2..26bf1cdfa 100644 --- a/packages/backend/src/models/entities/moderation-log.ts +++ b/packages/backend/src/models/entities/moderation-log.ts @@ -14,8 +14,8 @@ export class ModerationLog { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the ModerationLog.', + @Column("timestamp with time zone", { + comment: "The created date of the ModerationLog.", }) public createdAt: Date; @@ -23,17 +23,17 @@ export class ModerationLog { @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('varchar', { + @Column("varchar", { length: 128, }) public type: string; - @Column('jsonb') + @Column("jsonb") public info: Record; } diff --git a/packages/backend/src/models/entities/muted-note.ts b/packages/backend/src/models/entities/muted-note.ts index 11a6ae95d..0ee245aea 100644 --- a/packages/backend/src/models/entities/muted-note.ts +++ b/packages/backend/src/models/entities/muted-note.ts @@ -12,7 +12,7 @@ import { id } from "../id.js"; import { mutedNoteReasons } from "../../types.js"; @Entity() -@Index(['noteId', 'userId'], { unique: true }) +@Index(["noteId", "userId"], { unique: true }) export class MutedNote { @PrimaryColumn(id()) public id: string; @@ -20,12 +20,12 @@ export class MutedNote { @Index() @Column({ ...id(), - comment: 'The note ID.', + comment: "The note ID.", }) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; @@ -33,12 +33,12 @@ export class MutedNote { @Index() @Column({ ...id(), - comment: 'The user ID.', + comment: "The user ID.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -47,9 +47,9 @@ export class MutedNote { * ミュートされた理由。 */ @Index() - @Column('enum', { + @Column("enum", { enum: mutedNoteReasons, - comment: 'The reason of the MutedNote.', + comment: "The reason of the MutedNote.", }) public reason: typeof mutedNoteReasons[number]; } diff --git a/packages/backend/src/models/entities/muting.ts b/packages/backend/src/models/entities/muting.ts index 561bcfb95..603619b46 100644 --- a/packages/backend/src/models/entities/muting.ts +++ b/packages/backend/src/models/entities/muting.ts @@ -10,19 +10,19 @@ import { User } from "./user.js"; import { id } from "../id.js"; @Entity() -@Index(['muterId', 'muteeId'], { unique: true }) +@Index(["muterId", "muteeId"], { unique: true }) export class Muting { @PrimaryColumn(id()) public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the Muting.', + @Column("timestamp with time zone", { + comment: "The created date of the Muting.", }) public createdAt: Date; @Index() - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, }) public expiresAt: Date | null; @@ -30,12 +30,12 @@ export class Muting { @Index() @Column({ ...id(), - comment: 'The mutee user ID.', + comment: "The mutee user ID.", }) public muteeId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public mutee: User | null; @@ -43,12 +43,12 @@ export class Muting { @Index() @Column({ ...id(), - comment: 'The muter user ID.', + comment: "The muter user ID.", }) public muterId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public muter: User | null; diff --git a/packages/backend/src/models/entities/note-edit.ts b/packages/backend/src/models/entities/note-edit.ts index a65375efb..8761e2b15 100644 --- a/packages/backend/src/models/entities/note-edit.ts +++ b/packages/backend/src/models/entities/note-edit.ts @@ -18,34 +18,36 @@ export class NoteEdit { @Index() @Column({ ...id(), - comment: 'The ID of note.', + comment: "The ID of note.", }) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; - @Column('text', { + @Column("text", { nullable: true, }) public text: string | null; - @Column('varchar', { - length: 512, nullable: true, + @Column("varchar", { + length: 512, + nullable: true, }) public cw: string | null; @Column({ ...id(), - array: true, default: '{}', + array: true, + default: "{}", }) public fileIds: DriveFile["id"][]; - @Column('timestamp with time zone', { - comment: 'The updated date of the Note.', + @Column("timestamp with time zone", { + comment: "The updated date of the Note.", }) public updatedAt: Date; } diff --git a/packages/backend/src/models/entities/note-favorite.ts b/packages/backend/src/models/entities/note-favorite.ts index ab12d8b1b..19641ecf4 100644 --- a/packages/backend/src/models/entities/note-favorite.ts +++ b/packages/backend/src/models/entities/note-favorite.ts @@ -11,13 +11,13 @@ import { User } from "./user.js"; import { id } from "../id.js"; @Entity() -@Index(['userId', 'noteId'], { unique: true }) +@Index(["userId", "noteId"], { unique: true }) export class NoteFavorite { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the NoteFavorite.', + @Column("timestamp with time zone", { + comment: "The created date of the NoteFavorite.", }) public createdAt: Date; @@ -25,8 +25,8 @@ export class NoteFavorite { @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -34,8 +34,8 @@ export class NoteFavorite { @Column(id()) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; diff --git a/packages/backend/src/models/entities/note-reaction.ts b/packages/backend/src/models/entities/note-reaction.ts index 0e51c33b1..5e2a8d3e8 100644 --- a/packages/backend/src/models/entities/note-reaction.ts +++ b/packages/backend/src/models/entities/note-reaction.ts @@ -11,14 +11,14 @@ import { Note } from "./note.js"; import { id } from "../id.js"; @Entity() -@Index(['userId', 'noteId'], { unique: true }) +@Index(["userId", "noteId"], { unique: true }) export class NoteReaction { @PrimaryColumn(id()) public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the NoteReaction.', + @Column("timestamp with time zone", { + comment: "The created date of the NoteReaction.", }) public createdAt: Date; @@ -26,8 +26,8 @@ export class NoteReaction { @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user?: User | null; @@ -36,15 +36,15 @@ export class NoteReaction { @Column(id()) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note?: Note | null; // TODO: 対象noteのuserIdを非正規化したい(「受け取ったリアクション一覧」のようなものを(JOIN無しで)実装したいため) - @Column('varchar', { + @Column("varchar", { length: 260, }) public reaction: string; diff --git a/packages/backend/src/models/entities/note-thread-muting.ts b/packages/backend/src/models/entities/note-thread-muting.ts index 2985b195f..704b32850 100644 --- a/packages/backend/src/models/entities/note-thread-muting.ts +++ b/packages/backend/src/models/entities/note-thread-muting.ts @@ -11,13 +11,12 @@ import { Note } from "./note.js"; import { id } from "../id.js"; @Entity() -@Index(['userId', 'threadId'], { unique: true }) +@Index(["userId", "threadId"], { unique: true }) export class NoteThreadMuting { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - }) + @Column("timestamp with time zone", {}) public createdAt: Date; @Index() @@ -26,14 +25,14 @@ export class NoteThreadMuting { }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @Index() - @Column('varchar', { + @Column("varchar", { length: 256, }) public threadId: string; diff --git a/packages/backend/src/models/entities/note-unread.ts b/packages/backend/src/models/entities/note-unread.ts index d5bba7221..95695cbc8 100644 --- a/packages/backend/src/models/entities/note-unread.ts +++ b/packages/backend/src/models/entities/note-unread.ts @@ -12,7 +12,7 @@ import { id } from "../id.js"; import type { Channel } from "./channel.js"; @Entity() -@Index(['userId', 'noteId'], { unique: true }) +@Index(["userId", "noteId"], { unique: true }) export class NoteUnread { @PrimaryColumn(id()) public id: string; @@ -21,8 +21,8 @@ export class NoteUnread { @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -31,8 +31,8 @@ export class NoteUnread { @Column(id()) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; @@ -41,21 +41,21 @@ export class NoteUnread { * メンションか否か */ @Index() - @Column('boolean') + @Column("boolean") public isMentioned: boolean; /** * ダイレクト投稿か否か */ @Index() - @Column('boolean') + @Column("boolean") public isSpecified: boolean; //#region Denormalized fields @Index() @Column({ ...id(), - comment: '[Denormalized]', + comment: "[Denormalized]", }) public noteUserId: User["id"]; @@ -63,7 +63,7 @@ export class NoteUnread { @Column({ ...id(), nullable: true, - comment: '[Denormalized]', + comment: "[Denormalized]", }) public noteChannelId: Channel["id"] | null; //#endregion diff --git a/packages/backend/src/models/entities/note-watching.ts b/packages/backend/src/models/entities/note-watching.ts index 7ac3e8e29..724b084af 100644 --- a/packages/backend/src/models/entities/note-watching.ts +++ b/packages/backend/src/models/entities/note-watching.ts @@ -11,26 +11,26 @@ import { Note } from "./note.js"; import { id } from "../id.js"; @Entity() -@Index(['userId', 'noteId'], { unique: true }) +@Index(["userId", "noteId"], { unique: true }) export class NoteWatching { @PrimaryColumn(id()) public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the NoteWatching.', + @Column("timestamp with time zone", { + comment: "The created date of the NoteWatching.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The watcher ID.', + comment: "The watcher ID.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -38,12 +38,12 @@ export class NoteWatching { @Index() @Column({ ...id(), - comment: 'The target Note ID.', + comment: "The target Note ID.", }) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; @@ -52,7 +52,7 @@ export class NoteWatching { @Index() @Column({ ...id(), - comment: '[Denormalized]', + comment: "[Denormalized]", }) public noteUserId: Note["userId"]; //#endregion diff --git a/packages/backend/src/models/entities/note.ts b/packages/backend/src/models/entities/note.ts index f4e76c1db..edcfdb635 100644 --- a/packages/backend/src/models/entities/note.ts +++ b/packages/backend/src/models/entities/note.ts @@ -13,16 +13,16 @@ import { noteVisibilities } from "../../types.js"; import { Channel } from "./channel.js"; @Entity() -@Index('IDX_NOTE_TAGS', { synchronize: false }) -@Index('IDX_NOTE_MENTIONS', { synchronize: false }) -@Index('IDX_NOTE_VISIBLE_USER_IDS', { synchronize: false }) +@Index("IDX_NOTE_TAGS", { synchronize: false }) +@Index("IDX_NOTE_MENTIONS", { synchronize: false }) +@Index("IDX_NOTE_VISIBLE_USER_IDS", { synchronize: false }) export class Note { @PrimaryColumn(id()) public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the Note.', + @Column("timestamp with time zone", { + comment: "The created date of the Note.", }) public createdAt: Date; @@ -30,12 +30,12 @@ export class Note { @Column({ ...id(), nullable: true, - comment: 'The ID of reply target.', + comment: "The ID of reply target.", }) public replyId: Note["id"] | null; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public reply: Note | null; @@ -44,66 +44,69 @@ export class Note { @Column({ ...id(), nullable: true, - comment: 'The ID of renote target.', + comment: "The ID of renote target.", }) public renoteId: Note["id"] | null; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public renote: Note | null; @Index() - @Column('varchar', { - length: 256, nullable: true, + @Column("varchar", { + length: 256, + nullable: true, }) public threadId: string | null; - @Column('text', { + @Column("text", { nullable: true, }) public text: string | null; - @Column('varchar', { - length: 256, nullable: true, + @Column("varchar", { + length: 256, + nullable: true, }) public name: string | null; - @Column('varchar', { - length: 512, nullable: true, + @Column("varchar", { + length: 512, + nullable: true, }) public cw: string | null; @Index() @Column({ ...id(), - comment: 'The ID of author.', + comment: "The ID of author.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public localOnly: boolean; - @Column('smallint', { + @Column("smallint", { default: 0, }) public renoteCount: number; - @Column('smallint', { + @Column("smallint", { default: 0, }) public repliesCount: number; - @Column('jsonb', { + @Column("jsonb", { default: {}, }) public reactions: Record; @@ -115,71 +118,84 @@ export class Note { * followers ... フォロワーのみ * specified ... visibleUserIds で指定したユーザーのみ */ - @Column('enum', { enum: noteVisibilities }) + @Column("enum", { enum: noteVisibilities }) public visibility: typeof noteVisibilities[number]; @Index({ unique: true }) - @Column('varchar', { - length: 512, nullable: true, - comment: 'The URI of a note. it will be null when the note is local.', + @Column("varchar", { + length: 512, + nullable: true, + comment: "The URI of a note. it will be null when the note is local.", }) public uri: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: 'The human readable url of a note. it will be null when the note is local.', + @Column("varchar", { + length: 512, + nullable: true, + comment: + "The human readable url of a note. it will be null when the note is local.", }) public url: string | null; - @Column('integer', { - default: 0, select: false, + @Column("integer", { + default: 0, + select: false, }) public score: number; @Index() @Column({ ...id(), - array: true, default: '{}', + array: true, + default: "{}", }) public fileIds: DriveFile["id"][]; @Index() - @Column('varchar', { - length: 256, array: true, default: '{}', + @Column("varchar", { + length: 256, + array: true, + default: "{}", }) public attachedFileTypes: string[]; @Index() @Column({ ...id(), - array: true, default: '{}', + array: true, + default: "{}", }) public visibleUserIds: User["id"][]; @Index() @Column({ ...id(), - array: true, default: '{}', + array: true, + default: "{}", }) public mentions: User["id"][]; - @Column('text', { - default: '[]', + @Column("text", { + default: "[]", }) public mentionedRemoteUsers: string; - @Column('varchar', { - length: 128, array: true, default: '{}', + @Column("varchar", { + length: 128, + array: true, + default: "{}", }) public emojis: string[]; @Index() - @Column('varchar', { - length: 128, array: true, default: '{}', + @Column("varchar", { + length: 128, + array: true, + default: "{}", }) public tags: string[]; - @Column('boolean', { + @Column("boolean", { default: false, }) public hasPoll: boolean; @@ -188,53 +204,56 @@ export class Note { @Column({ ...id(), nullable: true, - comment: 'The ID of source channel.', + comment: "The ID of source channel.", }) public channelId: Channel["id"] | null; - @ManyToOne(type => Channel, { - onDelete: 'CASCADE', + @ManyToOne((type) => Channel, { + onDelete: "CASCADE", }) @JoinColumn() public channel: Channel | null; //#region Denormalized fields @Index() - @Column('varchar', { - length: 128, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 128, + nullable: true, + comment: "[Denormalized]", }) public userHost: string | null; @Column({ ...id(), nullable: true, - comment: '[Denormalized]', + comment: "[Denormalized]", }) public replyUserId: User["id"] | null; - @Column('varchar', { - length: 128, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 128, + nullable: true, + comment: "[Denormalized]", }) public replyUserHost: string | null; @Column({ ...id(), nullable: true, - comment: '[Denormalized]', + comment: "[Denormalized]", }) public renoteUserId: User["id"] | null; - @Column('varchar', { - length: 128, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 128, + nullable: true, + comment: "[Denormalized]", }) public renoteUserHost: string | null; - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, - comment: 'The updated date of the Note.', + comment: "The updated date of the Note.", }) public updatedAt: Date; //#endregion diff --git a/packages/backend/src/models/entities/notification.ts b/packages/backend/src/models/entities/notification.ts index 2c55e988f..da23f7d3e 100644 --- a/packages/backend/src/models/entities/notification.ts +++ b/packages/backend/src/models/entities/notification.ts @@ -20,8 +20,8 @@ export class Notification { public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the Notification.', + @Column("timestamp with time zone", { + comment: "The created date of the Notification.", }) public createdAt: Date; @@ -31,12 +31,12 @@ export class Notification { @Index() @Column({ ...id(), - comment: 'The ID of recipient user of the Notification.', + comment: "The ID of recipient user of the Notification.", }) public notifieeId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public notifiee: User | null; @@ -48,12 +48,12 @@ export class Notification { @Column({ ...id(), nullable: true, - comment: 'The ID of sender user of the Notification.', + comment: "The ID of sender user of the Notification.", }) public notifierId: User["id"] | null; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public notifier: User | null; @@ -74,9 +74,9 @@ export class Notification { * app - App notifications. */ @Index() - @Column('enum', { + @Column("enum", { enum: notificationTypes, - comment: 'The type of the Notification.', + comment: "The type of the Notification.", }) public type: typeof notificationTypes[number]; @@ -84,9 +84,9 @@ export class Notification { * Whether the notification was read. */ @Index() - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the notification was read.', + comment: "Whether the notification was read.", }) public isRead: boolean; @@ -96,8 +96,8 @@ export class Notification { }) public noteId: Note["id"] | null; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; @@ -108,8 +108,8 @@ export class Notification { }) public followRequestId: FollowRequest["id"] | null; - @ManyToOne(type => FollowRequest, { - onDelete: 'CASCADE', + @ManyToOne((type) => FollowRequest, { + onDelete: "CASCADE", }) @JoinColumn() public followRequest: FollowRequest | null; @@ -120,18 +120,19 @@ export class Notification { }) public userGroupInvitationId: UserGroupInvitation["id"] | null; - @ManyToOne(type => UserGroupInvitation, { - onDelete: 'CASCADE', + @ManyToOne((type) => UserGroupInvitation, { + onDelete: "CASCADE", }) @JoinColumn() public userGroupInvitation: UserGroupInvitation | null; - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public reaction: string | null; - @Column('integer', { + @Column("integer", { nullable: true, }) public choice: number | null; @@ -139,8 +140,9 @@ export class Notification { /** * App notification body */ - @Column('varchar', { - length: 2048, nullable: true, + @Column("varchar", { + length: 2048, + nullable: true, }) public customBody: string | null; @@ -148,8 +150,9 @@ export class Notification { * App notification header * (If omitted, it is expected to be displayed with the app name) */ - @Column('varchar', { - length: 256, nullable: true, + @Column("varchar", { + length: 256, + nullable: true, }) public customHeader: string | null; @@ -157,8 +160,9 @@ export class Notification { * App notification icon (URL) * (If omitted, it is expected to be displayed as an app icon) */ - @Column('varchar', { - length: 1024, nullable: true, + @Column("varchar", { + length: 1024, + nullable: true, }) public customIcon: string | null; @@ -172,8 +176,8 @@ export class Notification { }) public appAccessTokenId: AccessToken["id"] | null; - @ManyToOne(type => AccessToken, { - onDelete: 'CASCADE', + @ManyToOne((type) => AccessToken, { + onDelete: "CASCADE", }) @JoinColumn() public appAccessToken: AccessToken | null; diff --git a/packages/backend/src/models/entities/page-like.ts b/packages/backend/src/models/entities/page-like.ts index 75f4dc49b..6304e0b24 100644 --- a/packages/backend/src/models/entities/page-like.ts +++ b/packages/backend/src/models/entities/page-like.ts @@ -11,20 +11,20 @@ import { id } from "../id.js"; import { Page } from "./page.js"; @Entity() -@Index(['userId', 'pageId'], { unique: true }) +@Index(["userId", "pageId"], { unique: true }) export class PageLike { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone') + @Column("timestamp with time zone") public createdAt: Date; @Index() @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -32,8 +32,8 @@ export class PageLike { @Column(id()) public pageId: Page["id"]; - @ManyToOne(type => Page, { - onDelete: 'CASCADE', + @ManyToOne((type) => Page, { + onDelete: "CASCADE", }) @JoinColumn() public page: Page | null; diff --git a/packages/backend/src/models/entities/page.ts b/packages/backend/src/models/entities/page.ts index 5fe9f5208..d0733c8ce 100644 --- a/packages/backend/src/models/entities/page.ts +++ b/packages/backend/src/models/entities/page.ts @@ -11,51 +11,52 @@ import { id } from "../id.js"; import { DriveFile } from "./drive-file.js"; @Entity() -@Index(['userId', 'name'], { unique: true }) +@Index(["userId", "name"], { unique: true }) export class Page { @PrimaryColumn(id()) public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the Page.', + @Column("timestamp with time zone", { + comment: "The created date of the Page.", }) public createdAt: Date; @Index() - @Column('timestamp with time zone', { - comment: 'The updated date of the Page.', + @Column("timestamp with time zone", { + comment: "The updated date of the Page.", }) public updatedAt: Date; - @Column('varchar', { + @Column("varchar", { length: 256, }) public title: string; @Index() - @Column('varchar', { + @Column("varchar", { length: 256, }) public name: string; - @Column('varchar', { - length: 256, nullable: true, + @Column("varchar", { + length: 256, + nullable: true, }) public summary: string | null; - @Column('boolean') + @Column("boolean") public alignCenter: boolean; - @Column('boolean') + @Column("boolean") public isPublic: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public hideTitleWhenPinned: boolean; - @Column('varchar', { + @Column("varchar", { length: 32, }) public font: string; @@ -63,12 +64,12 @@ export class Page { @Index() @Column({ ...id(), - comment: 'The ID of author.', + comment: "The ID of author.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -79,25 +80,25 @@ export class Page { }) public eyeCatchingImageId: DriveFile["id"] | null; - @ManyToOne(type => DriveFile, { - onDelete: 'CASCADE', + @ManyToOne((type) => DriveFile, { + onDelete: "CASCADE", }) @JoinColumn() public eyeCatchingImage: DriveFile | null; - @Column('jsonb', { + @Column("jsonb", { default: [], }) public content: Record[]; - @Column('jsonb', { + @Column("jsonb", { default: [], }) public variables: Record[]; - @Column('varchar', { + @Column("varchar", { length: 16384, - default: '', + default: "", }) public script: string; @@ -106,17 +107,18 @@ export class Page { * followers ... フォロワーのみ * specified ... visibleUserIds で指定したユーザーのみ */ - @Column('enum', { enum: ['public', 'followers', 'specified'] }) + @Column("enum", { enum: ["public", "followers", "specified"] }) public visibility: "public" | "followers" | "specified"; @Index() @Column({ ...id(), - array: true, default: '{}', + array: true, + default: "{}", }) public visibleUserIds: User["id"][]; - @Column('integer', { + @Column("integer", { default: 0, }) public likedCount: number; diff --git a/packages/backend/src/models/entities/password-reset-request.ts b/packages/backend/src/models/entities/password-reset-request.ts index 4c681d4f7..ab0bccbbe 100644 --- a/packages/backend/src/models/entities/password-reset-request.ts +++ b/packages/backend/src/models/entities/password-reset-request.ts @@ -14,11 +14,11 @@ export class PasswordResetRequest { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone') + @Column("timestamp with time zone") public createdAt: Date; @Index({ unique: true }) - @Column('varchar', { + @Column("varchar", { length: 256, }) public token: string; @@ -29,8 +29,8 @@ export class PasswordResetRequest { }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; diff --git a/packages/backend/src/models/entities/poll-vote.ts b/packages/backend/src/models/entities/poll-vote.ts index 0649951cf..d59a720c3 100644 --- a/packages/backend/src/models/entities/poll-vote.ts +++ b/packages/backend/src/models/entities/poll-vote.ts @@ -11,14 +11,14 @@ import { Note } from "./note.js"; import { id } from "../id.js"; @Entity() -@Index(['userId', 'noteId', 'choice'], { unique: true }) +@Index(["userId", "noteId", "choice"], { unique: true }) export class PollVote { @PrimaryColumn(id()) public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the PollVote.', + @Column("timestamp with time zone", { + comment: "The created date of the PollVote.", }) public createdAt: Date; @@ -26,8 +26,8 @@ export class PollVote { @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -36,12 +36,12 @@ export class PollVote { @Column(id()) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; - @Column('integer') + @Column("integer") public choice: number; } diff --git a/packages/backend/src/models/entities/poll.ts b/packages/backend/src/models/entities/poll.ts index 28a70b3c7..405cca222 100644 --- a/packages/backend/src/models/entities/poll.ts +++ b/packages/backend/src/models/entities/poll.ts @@ -16,48 +16,51 @@ export class Poll { @PrimaryColumn(id()) public noteId: Note["id"]; - @OneToOne(type => Note, { - onDelete: 'CASCADE', + @OneToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, }) public expiresAt: Date | null; - @Column('boolean') + @Column("boolean") public multiple: boolean; - @Column('varchar', { - length: 256, array: true, default: '{}', + @Column("varchar", { + length: 256, + array: true, + default: "{}", }) public choices: string[]; - @Column('integer', { + @Column("integer", { array: true, }) public votes: number[]; //#region Denormalized fields - @Column('enum', { + @Column("enum", { enum: noteVisibilities, - comment: '[Denormalized]', + comment: "[Denormalized]", }) public noteVisibility: typeof noteVisibilities[number]; @Index() @Column({ ...id(), - comment: '[Denormalized]', + comment: "[Denormalized]", }) public userId: User["id"]; @Index() - @Column('varchar', { - length: 128, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 128, + nullable: true, + comment: "[Denormalized]", }) public userHost: string | null; //#endregion diff --git a/packages/backend/src/models/entities/promo-note.ts b/packages/backend/src/models/entities/promo-note.ts index 4daacd246..caa64927e 100644 --- a/packages/backend/src/models/entities/promo-note.ts +++ b/packages/backend/src/models/entities/promo-note.ts @@ -15,20 +15,20 @@ export class PromoNote { @PrimaryColumn(id()) public noteId: Note["id"]; - @OneToOne(type => Note, { - onDelete: 'CASCADE', + @OneToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; - @Column('timestamp with time zone') + @Column("timestamp with time zone") public expiresAt: Date; //#region Denormalized fields @Index() @Column({ ...id(), - comment: '[Denormalized]', + comment: "[Denormalized]", }) public userId: User["id"]; //#endregion diff --git a/packages/backend/src/models/entities/promo-read.ts b/packages/backend/src/models/entities/promo-read.ts index 5938bfde9..b31877dc3 100644 --- a/packages/backend/src/models/entities/promo-read.ts +++ b/packages/backend/src/models/entities/promo-read.ts @@ -11,13 +11,13 @@ import { User } from "./user.js"; import { id } from "../id.js"; @Entity() -@Index(['userId', 'noteId'], { unique: true }) +@Index(["userId", "noteId"], { unique: true }) export class PromoRead { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the PromoRead.', + @Column("timestamp with time zone", { + comment: "The created date of the PromoRead.", }) public createdAt: Date; @@ -25,8 +25,8 @@ export class PromoRead { @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -34,8 +34,8 @@ export class PromoRead { @Column(id()) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; diff --git a/packages/backend/src/models/entities/registration-tickets.ts b/packages/backend/src/models/entities/registration-tickets.ts index af785fbc0..549f05d07 100644 --- a/packages/backend/src/models/entities/registration-tickets.ts +++ b/packages/backend/src/models/entities/registration-tickets.ts @@ -6,11 +6,11 @@ export class RegistrationTicket { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone') + @Column("timestamp with time zone") public createdAt: Date; @Index({ unique: true }) - @Column('varchar', { + @Column("varchar", { length: 64, }) public code: string; diff --git a/packages/backend/src/models/entities/registry-item.ts b/packages/backend/src/models/entities/registry-item.ts index 655573883..d044222e6 100644 --- a/packages/backend/src/models/entities/registry-item.ts +++ b/packages/backend/src/models/entities/registry-item.ts @@ -15,51 +15,55 @@ export class RegistryItem { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the RegistryItem.', + @Column("timestamp with time zone", { + comment: "The created date of the RegistryItem.", }) public createdAt: Date; - @Column('timestamp with time zone', { - comment: 'The updated date of the RegistryItem.', + @Column("timestamp with time zone", { + comment: "The updated date of the RegistryItem.", }) public updatedAt: Date; @Index() @Column({ ...id(), - comment: 'The owner ID.', + comment: "The owner ID.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('varchar', { + @Column("varchar", { length: 1024, - comment: 'The key of the RegistryItem.', + comment: "The key of the RegistryItem.", }) public key: string; - @Column('jsonb', { - default: {}, nullable: true, - comment: 'The value of the RegistryItem.', + @Column("jsonb", { + default: {}, + nullable: true, + comment: "The value of the RegistryItem.", }) public value: any | null; @Index() - @Column('varchar', { - length: 1024, array: true, default: '{}', + @Column("varchar", { + length: 1024, + array: true, + default: "{}", }) public scope: string[]; // サードパーティアプリに開放するときのためのカラム @Index() - @Column('varchar', { - length: 512, nullable: true, + @Column("varchar", { + length: 512, + nullable: true, }) public domain: string | null; } diff --git a/packages/backend/src/models/entities/relay.ts b/packages/backend/src/models/entities/relay.ts index 82c0779ff..c7509dcf4 100644 --- a/packages/backend/src/models/entities/relay.ts +++ b/packages/backend/src/models/entities/relay.ts @@ -7,13 +7,14 @@ export class Relay { public id: string; @Index({ unique: true }) - @Column('varchar', { - length: 512, nullable: false, + @Column("varchar", { + length: 512, + nullable: false, }) public inbox: string; - @Column('enum', { - enum: ['requesting', 'accepted', 'rejected'], + @Column("enum", { + enum: ["requesting", "accepted", "rejected"], }) public status: "requesting" | "accepted" | "rejected"; } diff --git a/packages/backend/src/models/entities/renote-muting.ts b/packages/backend/src/models/entities/renote-muting.ts index 64ec7f583..e8856492f 100644 --- a/packages/backend/src/models/entities/renote-muting.ts +++ b/packages/backend/src/models/entities/renote-muting.ts @@ -28,7 +28,7 @@ export class RenoteMuting { }) public muteeId: User["id"]; - @ManyToOne(type => User, { + @ManyToOne((type) => User, { onDelete: "CASCADE", }) @JoinColumn() @@ -41,7 +41,7 @@ export class RenoteMuting { }) public muterId: User["id"]; - @ManyToOne(type => User, { + @ManyToOne((type) => User, { onDelete: "CASCADE", }) @JoinColumn() diff --git a/packages/backend/src/models/entities/signin.ts b/packages/backend/src/models/entities/signin.ts index 785991823..517e71c8f 100644 --- a/packages/backend/src/models/entities/signin.ts +++ b/packages/backend/src/models/entities/signin.ts @@ -14,8 +14,8 @@ export class Signin { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the Signin.', + @Column("timestamp with time zone", { + comment: "The created date of the Signin.", }) public createdAt: Date; @@ -23,20 +23,20 @@ export class Signin { @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('varchar', { + @Column("varchar", { length: 128, }) public ip: string; - @Column('jsonb') + @Column("jsonb") public headers: Record; - @Column('boolean') + @Column("boolean") public success: boolean; } diff --git a/packages/backend/src/models/entities/sw-subscription.ts b/packages/backend/src/models/entities/sw-subscription.ts index 8f18688ea..f7823fbaa 100644 --- a/packages/backend/src/models/entities/sw-subscription.ts +++ b/packages/backend/src/models/entities/sw-subscription.ts @@ -14,35 +14,35 @@ export class SwSubscription { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone') + @Column("timestamp with time zone") public createdAt: Date; @Index() @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('varchar', { + @Column("varchar", { length: 512, }) public endpoint: string; - @Column('varchar', { + @Column("varchar", { length: 256, }) public auth: string; - @Column('varchar', { + @Column("varchar", { length: 128, }) public publickey: string; - @Column('boolean', { + @Column("boolean", { default: false, }) public sendReadMessage: boolean; diff --git a/packages/backend/src/models/entities/used-username.ts b/packages/backend/src/models/entities/used-username.ts index a069205a5..d00a25991 100644 --- a/packages/backend/src/models/entities/used-username.ts +++ b/packages/backend/src/models/entities/used-username.ts @@ -2,12 +2,12 @@ import { PrimaryColumn, Entity, Column } from "typeorm"; @Entity() export class UsedUsername { - @PrimaryColumn('varchar', { + @PrimaryColumn("varchar", { length: 128, }) public username: string; - @Column('timestamp with time zone') + @Column("timestamp with time zone") public createdAt: Date; constructor(data: Partial) { diff --git a/packages/backend/src/models/entities/user-group-invitation.ts b/packages/backend/src/models/entities/user-group-invitation.ts index 8037b30e1..fa2655ab6 100644 --- a/packages/backend/src/models/entities/user-group-invitation.ts +++ b/packages/backend/src/models/entities/user-group-invitation.ts @@ -11,25 +11,25 @@ import { UserGroup } from "./user-group.js"; import { id } from "../id.js"; @Entity() -@Index(['userId', 'userGroupId'], { unique: true }) +@Index(["userId", "userGroupId"], { unique: true }) export class UserGroupInvitation { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the UserGroupInvitation.', + @Column("timestamp with time zone", { + comment: "The created date of the UserGroupInvitation.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The user ID.', + comment: "The user ID.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -37,12 +37,12 @@ export class UserGroupInvitation { @Index() @Column({ ...id(), - comment: 'The group ID.', + comment: "The group ID.", }) public userGroupId: UserGroup["id"]; - @ManyToOne(type => UserGroup, { - onDelete: 'CASCADE', + @ManyToOne((type) => UserGroup, { + onDelete: "CASCADE", }) @JoinColumn() public userGroup: UserGroup | null; diff --git a/packages/backend/src/models/entities/user-group-joining.ts b/packages/backend/src/models/entities/user-group-joining.ts index 6d503b274..78f820d0e 100644 --- a/packages/backend/src/models/entities/user-group-joining.ts +++ b/packages/backend/src/models/entities/user-group-joining.ts @@ -11,25 +11,25 @@ import { UserGroup } from "./user-group.js"; import { id } from "../id.js"; @Entity() -@Index(['userId', 'userGroupId'], { unique: true }) +@Index(["userId", "userGroupId"], { unique: true }) export class UserGroupJoining { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the UserGroupJoining.', + @Column("timestamp with time zone", { + comment: "The created date of the UserGroupJoining.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The user ID.', + comment: "The user ID.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -37,12 +37,12 @@ export class UserGroupJoining { @Index() @Column({ ...id(), - comment: 'The group ID.', + comment: "The group ID.", }) public userGroupId: UserGroup["id"]; - @ManyToOne(type => UserGroup, { - onDelete: 'CASCADE', + @ManyToOne((type) => UserGroup, { + onDelete: "CASCADE", }) @JoinColumn() public userGroup: UserGroup | null; diff --git a/packages/backend/src/models/entities/user-group.ts b/packages/backend/src/models/entities/user-group.ts index 38e5af334..23876ec8b 100644 --- a/packages/backend/src/models/entities/user-group.ts +++ b/packages/backend/src/models/entities/user-group.ts @@ -15,12 +15,12 @@ export class UserGroup { public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the UserGroup.', + @Column("timestamp with time zone", { + comment: "The created date of the UserGroup.", }) public createdAt: Date; - @Column('varchar', { + @Column("varchar", { length: 256, }) public name: string; @@ -28,17 +28,17 @@ export class UserGroup { @Index() @Column({ ...id(), - comment: 'The ID of owner.', + comment: "The ID of owner.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public isPrivate: boolean; diff --git a/packages/backend/src/models/entities/user-ip.ts b/packages/backend/src/models/entities/user-ip.ts index 6b88d5221..c30e56b66 100644 --- a/packages/backend/src/models/entities/user-ip.ts +++ b/packages/backend/src/models/entities/user-ip.ts @@ -12,20 +12,19 @@ import { Note } from "./note.js"; import type { User } from "./user.js"; @Entity() -@Index(['userId', 'ip'], { unique: true }) +@Index(["userId", "ip"], { unique: true }) export class UserIp { @PrimaryGeneratedColumn() public id: string; - @Column('timestamp with time zone', { - }) + @Column("timestamp with time zone", {}) public createdAt: Date; @Index() @Column(id()) public userId: User["id"]; - @Column('varchar', { + @Column("varchar", { length: 128, }) public ip: string; diff --git a/packages/backend/src/models/entities/user-keypair.ts b/packages/backend/src/models/entities/user-keypair.ts index 212e742b9..f98384f53 100644 --- a/packages/backend/src/models/entities/user-keypair.ts +++ b/packages/backend/src/models/entities/user-keypair.ts @@ -7,18 +7,18 @@ export class UserKeypair { @PrimaryColumn(id()) public userId: User["id"]; - @OneToOne(type => User, { - onDelete: 'CASCADE', + @OneToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('varchar', { + @Column("varchar", { length: 4096, }) public publicKey: string; - @Column('varchar', { + @Column("varchar", { length: 4096, }) public privateKey: string; diff --git a/packages/backend/src/models/entities/user-list-joining.ts b/packages/backend/src/models/entities/user-list-joining.ts index e52fa7b39..4caa71ad3 100644 --- a/packages/backend/src/models/entities/user-list-joining.ts +++ b/packages/backend/src/models/entities/user-list-joining.ts @@ -11,25 +11,25 @@ import { UserList } from "./user-list.js"; import { id } from "../id.js"; @Entity() -@Index(['userId', 'userListId'], { unique: true }) +@Index(["userId", "userListId"], { unique: true }) export class UserListJoining { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the UserListJoining.', + @Column("timestamp with time zone", { + comment: "The created date of the UserListJoining.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The user ID.', + comment: "The user ID.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -37,12 +37,12 @@ export class UserListJoining { @Index() @Column({ ...id(), - comment: 'The list ID.', + comment: "The list ID.", }) public userListId: UserList["id"]; - @ManyToOne(type => UserList, { - onDelete: 'CASCADE', + @ManyToOne((type) => UserList, { + onDelete: "CASCADE", }) @JoinColumn() public userList: UserList | null; diff --git a/packages/backend/src/models/entities/user-list.ts b/packages/backend/src/models/entities/user-list.ts index 7c4345230..3c95d44d6 100644 --- a/packages/backend/src/models/entities/user-list.ts +++ b/packages/backend/src/models/entities/user-list.ts @@ -14,27 +14,27 @@ export class UserList { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the UserList.', + @Column("timestamp with time zone", { + comment: "The created date of the UserList.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The owner ID.', + comment: "The owner ID.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('varchar', { + @Column("varchar", { length: 128, - comment: 'The name of the UserList.', + comment: "The name of the UserList.", }) public name: string; } diff --git a/packages/backend/src/models/entities/user-note-pining.ts b/packages/backend/src/models/entities/user-note-pining.ts index dc6d61f7e..c30fe1e02 100644 --- a/packages/backend/src/models/entities/user-note-pining.ts +++ b/packages/backend/src/models/entities/user-note-pining.ts @@ -11,13 +11,13 @@ import { User } from "./user.js"; import { id } from "../id.js"; @Entity() -@Index(['userId', 'noteId'], { unique: true }) +@Index(["userId", "noteId"], { unique: true }) export class UserNotePining { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the UserNotePinings.', + @Column("timestamp with time zone", { + comment: "The created date of the UserNotePinings.", }) public createdAt: Date; @@ -25,8 +25,8 @@ export class UserNotePining { @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @@ -34,8 +34,8 @@ export class UserNotePining { @Column(id()) public noteId: Note["id"]; - @ManyToOne(type => Note, { - onDelete: 'CASCADE', + @ManyToOne((type) => Note, { + onDelete: "CASCADE", }) @JoinColumn() public note: Note | null; diff --git a/packages/backend/src/models/entities/user-pending.ts b/packages/backend/src/models/entities/user-pending.ts index cac85d1c0..18ae5ad99 100644 --- a/packages/backend/src/models/entities/user-pending.ts +++ b/packages/backend/src/models/entities/user-pending.ts @@ -6,26 +6,26 @@ export class UserPending { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone') + @Column("timestamp with time zone") public createdAt: Date; @Index({ unique: true }) - @Column('varchar', { + @Column("varchar", { length: 128, }) public code: string; - @Column('varchar', { + @Column("varchar", { length: 128, }) public username: string; - @Column('varchar', { + @Column("varchar", { length: 128, }) public email: string; - @Column('varchar', { + @Column("varchar", { length: 128, }) public password: string; diff --git a/packages/backend/src/models/entities/user-profile.ts b/packages/backend/src/models/entities/user-profile.ts index a5eca6f48..119eecdc7 100644 --- a/packages/backend/src/models/entities/user-profile.ts +++ b/packages/backend/src/models/entities/user-profile.ts @@ -18,31 +18,34 @@ export class UserProfile { @PrimaryColumn(id()) public userId: User["id"]; - @OneToOne(type => User, { - onDelete: 'CASCADE', + @OneToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('varchar', { - length: 128, nullable: true, - comment: 'The location of the User.', + @Column("varchar", { + length: 128, + nullable: true, + comment: "The location of the User.", }) public location: string | null; - @Column('char', { - length: 10, nullable: true, - comment: 'The birthday (YYYY-MM-DD) of the User.', + @Column("char", { + length: 10, + nullable: true, + comment: "The birthday (YYYY-MM-DD) of the User.", }) public birthday: string | null; - @Column('varchar', { - length: 2048, nullable: true, - comment: 'The description (bio) of the User.', + @Column("varchar", { + length: 2048, + nullable: true, + comment: "The description (bio) of the User.", }) public description: string | null; - @Column('jsonb', { + @Column("jsonb", { default: [], }) public fields: { @@ -50,136 +53,145 @@ export class UserProfile { value: string; }[]; - @Column('varchar', { - length: 32, nullable: true, + @Column("varchar", { + length: 32, + nullable: true, }) public lang: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: 'Remote URL of the user.', + @Column("varchar", { + length: 512, + nullable: true, + comment: "Remote URL of the user.", }) public url: string | null; - @Column('varchar', { - length: 128, nullable: true, - comment: 'The email address of the User.', + @Column("varchar", { + length: 128, + nullable: true, + comment: "The email address of the User.", }) public email: string | null; - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public emailVerifyCode: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public emailVerified: boolean; - @Column('jsonb', { - default: ['follow', 'receiveFollowRequest', 'groupInvited'], + @Column("jsonb", { + default: ["follow", "receiveFollowRequest", "groupInvited"], }) public emailNotificationTypes: string[]; - @Column('boolean', { + @Column("boolean", { default: false, }) public publicReactions: boolean; - @Column('enum', { + @Column("enum", { enum: ffVisibility, - default: 'public', + default: "public", }) public ffVisibility: typeof ffVisibility[number]; - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public twoFactorTempSecret: string | null; - @Column('varchar', { - length: 128, nullable: true, + @Column("varchar", { + length: 128, + nullable: true, }) public twoFactorSecret: string | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public twoFactorEnabled: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public securityKeysAvailable: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public usePasswordLessLogin: boolean; - @Column('varchar', { - length: 128, nullable: true, - comment: 'The password hash of the User. It will be null if the origin of the user is local.', + @Column("varchar", { + length: 128, + nullable: true, + comment: + "The password hash of the User. It will be null if the origin of the user is local.", }) public password: string | null; - @Column('varchar', { - length: 8192, default: '', + @Column("varchar", { + length: 8192, + default: "", }) public moderationNote: string | null; // TODO: そのうち消す - @Column('jsonb', { + @Column("jsonb", { default: {}, - comment: 'The client-specific data of the User.', + comment: "The client-specific data of the User.", }) public clientData: Record; // TODO: そのうち消す - @Column('jsonb', { + @Column("jsonb", { default: {}, - comment: 'The room data of the User.', + comment: "The room data of the User.", }) public room: Record; - @Column('boolean', { + @Column("boolean", { default: false, }) public autoAcceptFollowed: boolean; - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether reject index by crawler.', + comment: "Whether reject index by crawler.", }) public noCrawle: boolean; - @Column('boolean', { + @Column("boolean", { default: true, }) public preventAiLearning: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public alwaysMarkNsfw: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public autoSensitive: boolean; - @Column('boolean', { + @Column("boolean", { default: false, }) public carefulBot: boolean; - @Column('boolean', { + @Column("boolean", { default: true, }) public injectFeaturedNote: boolean; - @Column('boolean', { + @Column("boolean", { default: true, }) public receiveAnnouncementEmail: boolean; @@ -190,35 +202,36 @@ export class UserProfile { }) public pinnedPageId: Page["id"] | null; - @OneToOne(type => Page, { - onDelete: 'SET NULL', + @OneToOne((type) => Page, { + onDelete: "SET NULL", }) @JoinColumn() public pinnedPage: Page | null; - @Column('jsonb', { + @Column("jsonb", { default: {}, }) public integrations: Record; @Index() - @Column('boolean', { - default: false, select: false, + @Column("boolean", { + default: false, + select: false, }) public enableWordMute: boolean; - @Column('jsonb', { + @Column("jsonb", { default: [], }) public mutedWords: string[][]; - @Column('jsonb', { + @Column("jsonb", { default: [], - comment: 'List of instances muted by the user.', + comment: "List of instances muted by the user.", }) public mutedInstances: string[]; - @Column('enum', { + @Column("enum", { enum: notificationTypes, array: true, default: [], @@ -227,9 +240,10 @@ export class UserProfile { //#region Denormalized fields @Index() - @Column('varchar', { - length: 128, nullable: true, - comment: '[Denormalized]', + @Column("varchar", { + length: 128, + nullable: true, + comment: "[Denormalized]", }) public userHost: string | null; //#endregion diff --git a/packages/backend/src/models/entities/user-publickey.ts b/packages/backend/src/models/entities/user-publickey.ts index d1a9239d1..83a86b8a3 100644 --- a/packages/backend/src/models/entities/user-publickey.ts +++ b/packages/backend/src/models/entities/user-publickey.ts @@ -14,19 +14,19 @@ export class UserPublickey { @PrimaryColumn(id()) public userId: User["id"]; - @OneToOne(type => User, { - onDelete: 'CASCADE', + @OneToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @Index({ unique: true }) - @Column('varchar', { + @Column("varchar", { length: 256, }) public keyId: string; - @Column('varchar', { + @Column("varchar", { length: 4096, }) public keyPem: string; diff --git a/packages/backend/src/models/entities/user-security-key.ts b/packages/backend/src/models/entities/user-security-key.ts index 3b9d925d9..511cab4ae 100644 --- a/packages/backend/src/models/entities/user-security-key.ts +++ b/packages/backend/src/models/entities/user-security-key.ts @@ -11,8 +11,8 @@ import { id } from "../id.js"; @Entity() export class UserSecurityKey { - @PrimaryColumn('varchar', { - comment: 'Variable-length id given to navigator.credentials.get()', + @PrimaryColumn("varchar", { + comment: "Variable-length id given to navigator.credentials.get()", }) public id: string; @@ -20,27 +20,27 @@ export class UserSecurityKey { @Column(id()) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; @Index() - @Column('varchar', { + @Column("varchar", { comment: - 'Variable-length public key used to verify attestations (hex-encoded).', + "Variable-length public key used to verify attestations (hex-encoded).", }) public publicKey: string; - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { comment: - 'The date of the last time the UserSecurityKey was successfully validated.', + "The date of the last time the UserSecurityKey was successfully validated.", }) public lastUsed: Date; - @Column('varchar', { - comment: 'User-defined name for this key', + @Column("varchar", { + comment: "User-defined name for this key", length: 30, }) public name: string; diff --git a/packages/backend/src/models/entities/user.ts b/packages/backend/src/models/entities/user.ts index c23f4f28d..53dc7e60b 100644 --- a/packages/backend/src/models/entities/user.ts +++ b/packages/backend/src/models/entities/user.ts @@ -10,99 +10,101 @@ import { id } from "../id.js"; import { DriveFile } from "./drive-file.js"; @Entity() -@Index(['usernameLower', 'host'], { unique: true }) +@Index(["usernameLower", "host"], { unique: true }) export class User { @PrimaryColumn(id()) public id: string; @Index() - @Column('timestamp with time zone', { - comment: 'The created date of the User.', + @Column("timestamp with time zone", { + comment: "The created date of the User.", }) public createdAt: Date; @Index() - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, - comment: 'The updated date of the User.', + comment: "The updated date of the User.", }) public updatedAt: Date | null; - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, }) public lastFetchedAt: Date | null; @Index() - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, }) public lastActiveDate: Date | null; - @Column('boolean', { + @Column("boolean", { default: false, }) public hideOnlineStatus: boolean; - @Column('varchar', { + @Column("varchar", { length: 128, - comment: 'The username of the User.', + comment: "The username of the User.", }) public username: string; @Index() - @Column('varchar', { - length: 128, select: false, - comment: 'The username (lowercased) of the User.', + @Column("varchar", { + length: 128, + select: false, + comment: "The username (lowercased) of the User.", }) public usernameLower: string; - @Column('varchar', { - length: 128, nullable: true, - comment: 'The name of the User.', + @Column("varchar", { + length: 128, + nullable: true, + comment: "The name of the User.", }) public name: string | null; - @Column('integer', { + @Column("integer", { default: 0, - comment: 'The count of followers.', + comment: "The count of followers.", }) public followersCount: number; - @Column('integer', { + @Column("integer", { default: 0, - comment: 'The count of following.', + comment: "The count of following.", }) public followingCount: number; - @Column('varchar', { + @Column("varchar", { length: 512, nullable: true, - comment: 'The URI of the new account of the User', + comment: "The URI of the new account of the User", }) public movedToUri: string | null; - @Column('simple-array', { + @Column("simple-array", { nullable: true, - comment: 'URIs the user is known as too', + comment: "URIs the user is known as too", }) public alsoKnownAs: string[] | null; - @Column('integer', { + @Column("integer", { default: 0, - comment: 'The count of notes.', + comment: "The count of notes.", }) public notesCount: number; @Column({ ...id(), nullable: true, - comment: 'The ID of avatar DriveFile.', + comment: "The ID of avatar DriveFile.", }) public avatarId: DriveFile["id"] | null; - @OneToOne(type => DriveFile, { - onDelete: 'SET NULL', + @OneToOne((type) => DriveFile, { + onDelete: "SET NULL", }) @JoinColumn() public avatar: DriveFile | null; @@ -110,143 +112,162 @@ export class User { @Column({ ...id(), nullable: true, - comment: 'The ID of banner DriveFile.', + comment: "The ID of banner DriveFile.", }) public bannerId: DriveFile["id"] | null; - @OneToOne(type => DriveFile, { - onDelete: 'SET NULL', + @OneToOne((type) => DriveFile, { + onDelete: "SET NULL", }) @JoinColumn() public banner: DriveFile | null; @Index() - @Column('varchar', { - length: 128, array: true, default: '{}', + @Column("varchar", { + length: 128, + array: true, + default: "{}", }) public tags: string[]; - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the User is suspended.', + comment: "Whether the User is suspended.", }) public isSuspended: boolean; - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the User is silenced.', + comment: "Whether the User is silenced.", }) public isSilenced: boolean; - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the User is locked.', + comment: "Whether the User is locked.", }) public isLocked: boolean; - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the User is a bot.', + comment: "Whether the User is a bot.", }) public isBot: boolean; - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the User is a cat.', + comment: "Whether the User is a cat.", }) public isCat: boolean; - @Column('boolean', { + @Column("boolean", { default: true, - comment: 'Whether to speak as a cat if isCat.', + comment: "Whether to speak as a cat if isCat.", }) public speakAsCat: boolean; - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the User is the admin.', + comment: "Whether the User is the admin.", }) public isAdmin: boolean; - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the User is a moderator.', + comment: "Whether the User is a moderator.", }) public isModerator: boolean; @Index() - @Column('boolean', { + @Column("boolean", { default: true, - comment: 'Whether the User is explorable.', + comment: "Whether the User is explorable.", }) public isExplorable: boolean; // アカウントが削除されたかどうかのフラグだが、完全に削除される際は物理削除なので実質削除されるまでの「削除が進行しているかどうか」のフラグ - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether the User is deleted.', + comment: "Whether the User is deleted.", }) public isDeleted: boolean; - @Column('varchar', { - length: 128, array: true, default: '{}', + @Column("varchar", { + length: 128, + array: true, + default: "{}", }) public emojis: string[]; @Index() - @Column('varchar', { - length: 128, nullable: true, - comment: 'The host of the User. It will be null if the origin of the user is local.', + @Column("varchar", { + length: 128, + nullable: true, + comment: + "The host of the User. It will be null if the origin of the user is local.", }) public host: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: 'The inbox URL of the User. It will be null if the origin of the user is local.', + @Column("varchar", { + length: 512, + nullable: true, + comment: + "The inbox URL of the User. It will be null if the origin of the user is local.", }) public inbox: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: 'The sharedInbox URL of the User. It will be null if the origin of the user is local.', + @Column("varchar", { + length: 512, + nullable: true, + comment: + "The sharedInbox URL of the User. It will be null if the origin of the user is local.", }) public sharedInbox: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: 'The featured URL of the User. It will be null if the origin of the user is local.', + @Column("varchar", { + length: 512, + nullable: true, + comment: + "The featured URL of the User. It will be null if the origin of the user is local.", }) public featured: string | null; @Index() - @Column('varchar', { - length: 512, nullable: true, - comment: 'The URI of the User. It will be null if the origin of the user is local.', + @Column("varchar", { + length: 512, + nullable: true, + comment: + "The URI of the User. It will be null if the origin of the user is local.", }) public uri: string | null; - @Column('varchar', { - length: 512, nullable: true, - comment: 'The URI of the user Follower Collection. It will be null if the origin of the user is local.', + @Column("varchar", { + length: 512, + nullable: true, + comment: + "The URI of the user Follower Collection. It will be null if the origin of the user is local.", }) public followersUri: string | null; - @Column('boolean', { + @Column("boolean", { default: false, - comment: 'Whether to show users replying to other users in the timeline.', + comment: "Whether to show users replying to other users in the timeline.", }) public showTimelineReplies: boolean; @Index({ unique: true }) - @Column('char', { - length: 16, nullable: true, unique: true, - comment: 'The native access token of the User. It will be null if the origin of the user is local.', + @Column("char", { + length: 16, + nullable: true, + unique: true, + comment: + "The native access token of the User. It will be null if the origin of the user is local.", }) public token: string | null; - @Column('integer', { + @Column("integer", { nullable: true, - comment: 'Overrides user drive capacity limit', + comment: "Overrides user drive capacity limit", }) public driveCapacityOverrideMb: number | null; diff --git a/packages/backend/src/models/entities/webhook.ts b/packages/backend/src/models/entities/webhook.ts index 5db51c3a3..47fd79966 100644 --- a/packages/backend/src/models/entities/webhook.ts +++ b/packages/backend/src/models/entities/webhook.ts @@ -25,48 +25,50 @@ export class Webhook { @PrimaryColumn(id()) public id: string; - @Column('timestamp with time zone', { - comment: 'The created date of the Antenna.', + @Column("timestamp with time zone", { + comment: "The created date of the Antenna.", }) public createdAt: Date; @Index() @Column({ ...id(), - comment: 'The owner ID.', + comment: "The owner ID.", }) public userId: User["id"]; - @ManyToOne(type => User, { - onDelete: 'CASCADE', + @ManyToOne((type) => User, { + onDelete: "CASCADE", }) @JoinColumn() public user: User | null; - @Column('varchar', { + @Column("varchar", { length: 128, - comment: 'The name of the Antenna.', + comment: "The name of the Antenna.", }) public name: string; @Index() - @Column('varchar', { - length: 128, array: true, default: '{}', + @Column("varchar", { + length: 128, + array: true, + default: "{}", }) public on: typeof webhookEventTypes[number][]; - @Column('varchar', { + @Column("varchar", { length: 1024, }) public url: string; - @Column('varchar', { + @Column("varchar", { length: 1024, }) public secret: string; @Index() - @Column('boolean', { + @Column("boolean", { default: true, }) public active: boolean; @@ -74,7 +76,7 @@ export class Webhook { /** * 直近のリクエスト送信日時 */ - @Column('timestamp with time zone', { + @Column("timestamp with time zone", { nullable: true, }) public latestSentAt: Date | null; @@ -82,7 +84,7 @@ export class Webhook { /** * 直近のリクエスト送信時のHTTPステータスコード */ - @Column('integer', { + @Column("integer", { nullable: true, }) public latestStatus: number | null; diff --git a/packages/backend/src/models/repositories/antenna.ts b/packages/backend/src/models/repositories/antenna.ts index c325e2589..d66aab4ee 100644 --- a/packages/backend/src/models/repositories/antenna.ts +++ b/packages/backend/src/models/repositories/antenna.ts @@ -1,36 +1,14 @@ import { db } from "@/db/postgre.js"; import { Antenna } from "@/models/entities/antenna.js"; -import type { Packed } from "@/misc/schema.js"; -import { AntennaNotes, UserGroupJoinings } from "../index.js"; +import { + NativeAntennaSchema, + nativePackAntennaById, +} from "native-utils/built/index.js"; export const AntennaRepository = db.getRepository(Antenna).extend({ - async pack(src: Antenna["id"] | Antenna): Promise> { - const antenna = - typeof src === "object" ? src : await this.findOneByOrFail({ id: src }); + async pack(src: Antenna["id"] | Antenna): Promise { + const id = typeof src === "object" ? src.id : src; - const hasUnreadNote = - (await AntennaNotes.findOneBy({ antennaId: antenna.id, read: false })) != - null; - const userGroupJoining = antenna.userGroupJoiningId - ? await UserGroupJoinings.findOneBy({ id: antenna.userGroupJoiningId }) - : null; - - return { - id: antenna.id, - createdAt: antenna.createdAt.toISOString(), - name: antenna.name, - keywords: antenna.keywords, - excludeKeywords: antenna.excludeKeywords, - src: antenna.src, - userListId: antenna.userListId, - userGroupId: userGroupJoining ? userGroupJoining.userGroupId : null, - users: antenna.users, - instances: antenna.instances, - caseSensitive: antenna.caseSensitive, - notify: antenna.notify, - withReplies: antenna.withReplies, - withFile: antenna.withFile, - hasUnreadNote, - }; + return await nativePackAntennaById(id); }, }); diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index 5e0b83792..1ca9b3289 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -257,17 +257,22 @@ export const UserRepository = db.getRepository(User).extend({ async getHasUnreadAntenna(userId: User["id"]): Promise { try { - const myAntennas = (await getAntennas()).filter((a) => a.userId === userId); + const myAntennas = (await getAntennas()).filter( + (a) => a.userId === userId, + ); - const unread = - myAntennas.length > 0 - ? await AntennaNotes.findOneBy({ - antennaId: In(myAntennas.map((x) => x.id)), - read: false, - }) - : null; + const unread = + myAntennas.length > 0 + ? await AntennaNotes.findOneBy({ + antennaId: In(myAntennas.map((x) => x.id)), + read: false, + }) + : null; - return unread != null; } catch(e) { return false; } + return unread != null; + } catch (e) { + return false; + } }, async getHasUnreadChannel(userId: User["id"]): Promise { diff --git a/packages/backend/src/queue/processors/background/index-all-notes.ts b/packages/backend/src/queue/processors/background/index-all-notes.ts index 03219199d..10c332aa3 100644 --- a/packages/backend/src/queue/processors/background/index-all-notes.ts +++ b/packages/backend/src/queue/processors/background/index-all-notes.ts @@ -5,6 +5,7 @@ import { Notes } from "@/models/index.js"; import { MoreThan } from "typeorm"; import { index } from "@/services/note/create.js"; import { Note } from "@/models/entities/note.js"; +import meilisearch from "../../../db/meilisearch.js"; const logger = queueLogger.createSubLogger("index-all-notes"); @@ -38,6 +39,7 @@ export default async function indexAllNotes( order: { id: 1, }, + relations: ["user"], }); } catch (e) { logger.error(`Failed to query notes ${e}`); @@ -58,7 +60,12 @@ export default async function indexAllNotes( for (let i = 0; i < notes.length; i += batch) { const chunk = notes.slice(i, i + batch); - await Promise.all(chunk.map((note) => index(note))); + + if (meilisearch) { + await meilisearch.ingestNote(chunk); + } + + await Promise.all(chunk.map((note) => index(note, true))); indexedCount += chunk.length; const pct = (indexedCount / total) * 100; diff --git a/packages/backend/src/queue/processors/db/delete-account.ts b/packages/backend/src/queue/processors/db/delete-account.ts index 764b83db2..a356ca7ab 100644 --- a/packages/backend/src/queue/processors/db/delete-account.ts +++ b/packages/backend/src/queue/processors/db/delete-account.ts @@ -7,6 +7,7 @@ import type { DriveFile } from "@/models/entities/drive-file.js"; import { MoreThan } from "typeorm"; import { deleteFileSync } from "@/services/drive/delete-file.js"; import { sendEmail } from "@/services/send-email.js"; +import meilisearch from "@/db/meilisearch.js"; const logger = queueLogger.createSubLogger("delete-account"); @@ -43,6 +44,9 @@ export async function deleteAccount( cursor = notes[notes.length - 1].id; await Notes.delete(notes.map((note) => note.id)); + if (meilisearch) { + await meilisearch.deleteNotes(notes); + } } logger.succ("All of notes deleted"); diff --git a/packages/backend/src/queue/processors/db/import-custom-emojis.ts b/packages/backend/src/queue/processors/db/import-custom-emojis.ts index e2454405f..9e8b3b174 100644 --- a/packages/backend/src/queue/processors/db/import-custom-emojis.ts +++ b/packages/backend/src/queue/processors/db/import-custom-emojis.ts @@ -11,6 +11,7 @@ import { addFile } from "@/services/drive/add-file.js"; import { genId } from "@/misc/gen-id.js"; import { db } from "@/db/postgre.js"; import probeImageSize from "probe-image-size"; +import * as path from "path"; const logger = queueLogger.createSubLogger("import-custom-emojis"); @@ -29,11 +30,11 @@ export async function importCustomEmojis( return; } - const [path, cleanup] = await createTempDir(); + const [tempPath, cleanup] = await createTempDir(); - logger.info(`Temp dir is ${path}`); + logger.info(`Temp dir is ${tempPath}`); - const destPath = `${path}/emojis.zip`; + const destPath = `${tempPath}/emojis.zip`; try { fs.writeFileSync(destPath, "", "binary"); @@ -46,44 +47,96 @@ export async function importCustomEmojis( throw e; } - const outputPath = `${path}/emojis`; + const outputPath = `${tempPath}/emojis`; const unzipStream = fs.createReadStream(destPath); const zip = new AdmZip(destPath); zip.extractAllToAsync(outputPath, true, false, async (error) => { if (error) throw error; - const metaRaw = fs.readFileSync(`${outputPath}/meta.json`, "utf-8"); - const meta = JSON.parse(metaRaw); - for (const record of meta.emojis) { - if (!record.downloaded) continue; - const emojiInfo = record.emoji; - const emojiPath = `${outputPath}/${record.fileName}`; - await Emojis.delete({ - name: emojiInfo.name, - }); - const driveFile = await addFile({ - user: null, - path: emojiPath, - name: record.fileName, - force: true, - }); - const file = fs.createReadStream(emojiPath); - const size = await probeImageSize(file); - file.destroy(); - await Emojis.insert({ - id: genId(), - updatedAt: new Date(), - name: emojiInfo.name, - category: emojiInfo.category, - host: null, - aliases: emojiInfo.aliases, - originalUrl: driveFile.url, - publicUrl: driveFile.webpublicUrl ?? driveFile.url, - type: driveFile.webpublicType ?? driveFile.type, - license: emojiInfo.license, - width: size.width || null, - height: size.height || null, - }).then((x) => Emojis.findOneByOrFail(x.identifiers[0])); + if (fs.existsSync(`${outputPath}/meta.json`)) { + logger.info("starting emoji import with metadata"); + const metaRaw = fs.readFileSync(`${outputPath}/meta.json`, "utf-8"); + const meta = JSON.parse(metaRaw); + + for (const record of meta.emojis) { + if (!record.downloaded) continue; + const emojiInfo = record.emoji; + const emojiPath = `${outputPath}/${record.fileName}`; + await Emojis.delete({ + name: emojiInfo.name, + }); + const driveFile = await addFile({ + user: null, + path: emojiPath, + name: record.fileName, + force: true, + }); + const file = fs.createReadStream(emojiPath); + const size = await probeImageSize(file); + file.destroy(); + await Emojis.insert({ + id: genId(), + updatedAt: new Date(), + name: emojiInfo.name, + category: emojiInfo.category, + host: null, + aliases: emojiInfo.aliases, + originalUrl: driveFile.url, + publicUrl: driveFile.webpublicUrl ?? driveFile.url, + type: driveFile.webpublicType ?? driveFile.type, + license: emojiInfo.license, + width: size.width || null, + height: size.height || null, + }).then((x) => Emojis.findOneByOrFail(x.identifiers[0])); + } + } else { + logger.info("starting emoji import without metadata"); + // Since we lack metadata, we import into a randomized category name instead + let categoryName = genId(); + + let containedEmojis = fs.readdirSync(outputPath); + + // Filter out accidental JSON files + containedEmojis = containedEmojis.filter( + (emoji) => !emoji.match(/\.(json)$/i), + ); + + for (const emojiFilename of containedEmojis) { + // strip extension and get filename to use as name + const name = path.basename(emojiFilename, path.extname(emojiFilename)); + const emojiPath = `${outputPath}/${emojiFilename}`; + + logger.info(`importing ${name}`); + + await Emojis.delete({ + name: name, + }); + const driveFile = await addFile({ + user: null, + path: emojiPath, + name: path.basename(emojiFilename), + force: true, + }); + const file = fs.createReadStream(emojiPath); + const size = await probeImageSize(file); + file.destroy(); + logger.info(`emoji size: ${size.width}x${size.height}`); + + await Emojis.insert({ + id: genId(), + updatedAt: new Date(), + name: name, + category: categoryName, + host: null, + aliases: [], + originalUrl: driveFile.url, + publicUrl: driveFile.webpublicUrl ?? driveFile.url, + type: driveFile.webpublicType ?? driveFile.type, + license: null, + width: size.width || null, + height: size.height || null, + }).then((x) => Emojis.findOneByOrFail(x.identifiers[0])); + } } await db.queryResultCache!.remove(["meta_emojis"]); diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 24c895cbb..ad7031063 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -64,7 +64,7 @@ export const meta = { type: "string", optional: false, nullable: false, - default: "/assets/ai.png", + default: "/static-assets/badges/info.png", }, bannerUrl: { type: "string", @@ -75,7 +75,7 @@ export const meta = { type: "string", optional: false, nullable: false, - default: "https://xn--931a.moe/aiart/yubitun.png", + default: "/static-assets/badges/error.png", }, iconUrl: { type: "string", diff --git a/packages/backend/src/server/api/endpoints/i/known-as.ts b/packages/backend/src/server/api/endpoints/i/known-as.ts index 5e86e8b95..0d0c06180 100644 --- a/packages/backend/src/server/api/endpoints/i/known-as.ts +++ b/packages/backend/src/server/api/endpoints/i/known-as.ts @@ -1,4 +1,4 @@ -import type { User, UserDetailedNotMeOnly } from "@/models/entities/user.js"; +import type { User } from "@/models/entities/user.js"; import { Users } from "@/models/index.js"; import { resolveUser } from "@/remote/resolve-user.js"; import acceptAllFollowRequests from "@/services/following/requests/accept-all.js"; @@ -6,10 +6,9 @@ import { publishToFollowers } from "@/services/i/update.js"; import { publishMainStream } from "@/services/stream.js"; import { DAY } from "@/const.js"; import { apiLogger } from "../../logger.js"; -import { UserProfiles } from "@/models/index.js"; -import config from "@/config/index.js"; import define from "../../define.js"; import { ApiError } from "../../error.js"; +import { parse } from "@/misc/acct.js"; export const meta = { tags: ["users"], @@ -38,49 +37,57 @@ export const meta = { code: "URI_NULL", id: "bf326f31-d430-4f97-9933-5d61e4d48a23", }, + alreadyMoved: { + message: "You have already moved your account.", + code: "ALREADY_MOVED", + id: "56f20ec9-fd06-4fa5-841b-edd6d7d4fa31", + }, + yourself: { + message: "You can't set yourself as your own alias.", + code: "FORBIDDEN_TO_SET_YOURSELF", + id: "25c90186-4ab0-49c8-9bba-a1fa6c202ba4", + }, }, } as const; export const paramDef = { type: "object", properties: { - alsoKnownAs: { type: "string" }, + alsoKnownAs: { + type: "array", + maxItems: 10, + uniqueItems: true, + items: { type: "string" }, + }, }, required: ["alsoKnownAs"], } as const; export default define(meta, paramDef, async (ps, user) => { if (!ps.alsoKnownAs) throw new ApiError(meta.errors.noSuchUser); + if (user.movedToUri) throw new ApiError(meta.errors.alreadyMoved); - let unfiltered: string = ps.alsoKnownAs; - const updates = {} as Partial; + const newAka = new Set(); - if (!unfiltered) { - updates.alsoKnownAs = null; - } else { - if (unfiltered.startsWith("acct:")) unfiltered = unfiltered.substring(5); - if (unfiltered.startsWith("@")) unfiltered = unfiltered.substring(1); - if (!unfiltered.includes("@")) throw new ApiError(meta.errors.notRemote); + for (const line of ps.alsoKnownAs) { + if (!line) throw new ApiError(meta.errors.noSuchUser); + const { username, host } = parse(line); - const userAddress: string[] = unfiltered.split("@"); - const knownAs = await resolveUser(userAddress[0], userAddress[1]).catch( - (e) => { - apiLogger.warn(`failed to resolve remote user: ${e}`); - throw new ApiError(meta.errors.noSuchUser); - }, - ); + const aka = await resolveUser(username, host).catch((e) => { + apiLogger.warn(`failed to resolve remote user: ${e}`); + throw new ApiError(meta.errors.noSuchUser); + }); - const toUrl: string | null = knownAs.uri; - if (!toUrl) { - throw new ApiError(meta.errors.uriNull); - } - if (updates.alsoKnownAs == null || updates.alsoKnownAs.length === 0) { - updates.alsoKnownAs = [toUrl]; - } else { - updates.alsoKnownAs.push(toUrl); - } + if (aka.id === user.id) throw new ApiError(meta.errors.yourself); + if (!aka.uri) throw new ApiError(meta.errors.uriNull); + + newAka.add(aka.uri); } + const updates = { + alsoKnownAs: newAka.size > 0 ? Array.from(newAka) : null, + } as Partial; + await Users.update(user.id, updates); const iObj = await Users.pack(user.id, user, { diff --git a/packages/backend/src/server/api/endpoints/i/move.ts b/packages/backend/src/server/api/endpoints/i/move.ts index 3d947063f..d972aaf1d 100644 --- a/packages/backend/src/server/api/endpoints/i/move.ts +++ b/packages/backend/src/server/api/endpoints/i/move.ts @@ -10,9 +10,9 @@ import deleteFollowing from "@/services/following/delete.js"; import create from "@/services/following/create.js"; import { getUser } from "@/server/api/common/getters.js"; import { Followings, Users } from "@/models/index.js"; -import { UserProfiles } from "@/models/index.js"; import config from "@/config/index.js"; import { publishMainStream } from "@/services/stream.js"; +import { parse } from "@/misc/acct.js"; export const meta = { tags: ["users"], @@ -95,22 +95,13 @@ export default define(meta, paramDef, async (ps, user) => { if (user.isAdmin) throw new ApiError(meta.errors.adminForbidden); if (user.movedToUri) throw new ApiError(meta.errors.alreadyMoved); - let unfiltered: string = ps.moveToAccount; - if (!unfiltered) { + const { username, host } = parse(ps.moveToAccount); + if (!host) throw new ApiError(meta.errors.notRemote); + + const moveTo: User = await resolveUser(username, host).catch((e) => { + apiLogger.warn(`failed to resolve remote user: ${e}`); throw new ApiError(meta.errors.noSuchMoveTarget); - } - - if (unfiltered.startsWith("acct:")) unfiltered = unfiltered.substring(5); - if (unfiltered.startsWith("@")) unfiltered = unfiltered.substring(1); - if (!unfiltered.includes("@")) throw new ApiError(meta.errors.notRemote); - - const userAddress: string[] = unfiltered.split("@"); - const moveTo: User = await resolveUser(userAddress[0], userAddress[1]).catch( - (e) => { - apiLogger.warn(`failed to resolve remote user: ${e}`); - throw new ApiError(meta.errors.noSuchMoveTarget); - }, - ); + }); let fromUrl: string | null = user.uri; if (!fromUrl) { fromUrl = `${config.url}/users/${user.id}`; @@ -134,6 +125,7 @@ export default define(meta, paramDef, async (ps, user) => { if (!toUrl) toUrl = ""; updates.movedToUri = toUrl; + updates.alsoKnownAs = user.alsoKnownAs?.concat(toUrl) ?? [toUrl]; await Users.update(user.id, updates); const iObj = await Users.pack(user.id, user, { diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 139afc88b..c603cb9ac 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -1,3 +1,4 @@ +import * as JSON5 from "json5"; import { IsNull, MoreThan } from "typeorm"; import config from "@/config/index.js"; import { fetchMeta } from "@/misc/fetch-meta.js"; @@ -154,7 +155,7 @@ export const meta = { type: "string", optional: false, nullable: false, - default: "/assets/ai.png", + default: "/static-assets/badges/info.png", }, bannerUrl: { type: "string", @@ -165,7 +166,7 @@ export const meta = { type: "string", optional: false, nullable: false, - default: "https://xn--931a.moe/aiart/yubitun.png", + default: "/static-assets/badges/error.png", }, iconUrl: { type: "string", @@ -462,8 +463,13 @@ export default define(meta, paramDef, async (ps, me) => { maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため maxCaptionTextLength: MAX_CAPTION_TEXT_LENGTH, emojis: instance.privateMode && !me ? [] : await Emojis.packMany(emojis), - defaultLightTheme: instance.defaultLightTheme, - defaultDarkTheme: instance.defaultDarkTheme, + // クライアントの手間を減らすためあらかじめJSONに変換しておく + defaultLightTheme: instance.defaultLightTheme + ? JSON.stringify(JSON5.parse(instance.defaultLightTheme)) + : null, + defaultDarkTheme: instance.defaultDarkTheme + ? JSON.stringify(JSON5.parse(instance.defaultDarkTheme)) + : null, ads: instance.privateMode && !me ? [] diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index 93392acdd..d0c2f8d77 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -4,6 +4,7 @@ import { Note } from "@/models/entities/note.js"; import config from "@/config/index.js"; import es from "../../../../db/elasticsearch.js"; import sonic from "../../../../db/sonic.js"; +import meilisearch, { MeilisearchNote } from "../../../../db/meilisearch.js"; import define from "../../define.js"; import { makePaginationQuery } from "../../common/make-pagination-query.js"; import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; @@ -62,7 +63,7 @@ export const paramDef = { } as const; export default define(meta, paramDef, async (ps, me) => { - if (es == null && sonic == null) { + if (es == null && sonic == null && meilisearch == null) { const query = makePaginationQuery( Notes.createQueryBuilder("note"), ps.sinceId, @@ -170,6 +171,70 @@ export default define(meta, paramDef, async (ps, me) => { found.length = ps.limit; } + return found; + } else if (meilisearch) { + let start = 0; + const chunkSize = 100; + + // Use meilisearch to fetch and step through all search results that could match the requirements + const ids = []; + while (true) { + const results = await meilisearch.search(ps.query, chunkSize, start, me); + + start += chunkSize; + + if (results.hits.length === 0) { + break; + } + + const res = results.hits + .filter((key: MeilisearchNote) => { + if (ps.userId && key.userId !== ps.userId) { + return false; + } + if (ps.channelId && key.channelId !== ps.channelId) { + return false; + } + if (ps.sinceId && key.id <= ps.sinceId) { + return false; + } + if (ps.untilId && key.id >= ps.untilId) { + return false; + } + return true; + }) + .map((key) => key.id); + + ids.push(...res); + } + + // Sort all the results by note id DESC (newest first) + ids.sort((a, b) => b - a); + + // Fetch the notes from the database until we have enough to satisfy the limit + start = 0; + const found = []; + while (found.length < ps.limit && start < ids.length) { + const chunk = ids.slice(start, start + chunkSize); + const notes: Note[] = await Notes.find({ + where: { + id: In(chunk), + }, + order: { + id: "DESC", + }, + }); + + // The notes are checked for visibility and muted/blocked users when packed + found.push(...(await Notes.packMany(notes, me))); + start += chunkSize; + } + + // If we have more results than the limit, trim them + if (found.length > ps.limit) { + found.length = ps.limit; + } + return found; } else { const userQuery = diff --git a/packages/backend/src/server/api/endpoints/server-info.ts b/packages/backend/src/server/api/endpoints/server-info.ts index 1ce27e262..cc9aa91b2 100644 --- a/packages/backend/src/server/api/endpoints/server-info.ts +++ b/packages/backend/src/server/api/endpoints/server-info.ts @@ -1,6 +1,7 @@ import * as os from "node:os"; import si from "systeminformation"; import define from "../define.js"; +import meilisearch from "../../../db/meilisearch.js"; export const meta = { requireCredential: false, @@ -18,6 +19,7 @@ export const paramDef = { export default define(meta, paramDef, async () => { const memStats = await si.mem(); const fsStats = await si.fsSize(); + const meilisearchStats = await meilisearchStatus(); return { machine: os.hostname(), @@ -34,3 +36,15 @@ export default define(meta, paramDef, async () => { }, }; }); + +async function meilisearchStatus() { + if (meilisearch) { + return meilisearch.serverStats(); + } else { + return { + health: "unconfigured", + size: 0, + indexed_count: 0, + }; + } +} diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts index 49cac81fd..bead8df0a 100644 --- a/packages/backend/src/server/api/endpoints/users/show.ts +++ b/packages/backend/src/server/api/endpoints/users/show.ts @@ -54,7 +54,7 @@ export const paramDef = { anyOf: [ { properties: { - userId: { type: "string", format: "misskey:id" }, + userId: { type: "string" }, }, required: ["userId"], }, @@ -65,7 +65,6 @@ export const paramDef = { uniqueItems: true, items: { type: "string", - format: "misskey:id", }, }, }, @@ -95,21 +94,27 @@ export default define(meta, paramDef, async (ps, me) => { return []; } - const users = await Users.findBy( - isAdminOrModerator - ? { - id: In(ps.userIds), - } - : { - id: In(ps.userIds), - isSuspended: false, - }, - ); + const isUrl = ps.userIds[0].startsWith("http"); + let users: User[]; + if (isUrl) { + users = await Users.findBy( + isAdminOrModerator + ? { uri: In(ps.userIds) } + : { uri: In(ps.userIds), isSuspended: false }, + ); + } else { + users = await Users.findBy( + isAdminOrModerator + ? { id: In(ps.userIds) } + : { id: In(ps.userIds), isSuspended: false }, + ); + } // リクエストされた通りに並べ替え const _users: User[] = []; for (const id of ps.userIds) { - _users.push(users.find((x) => x.id === id)!); + const res = users.find((x) => (isUrl ? x.uri === id : x.id === id)); + if (res) _users.push(res); } return await Promise.all( @@ -129,7 +134,9 @@ export default define(meta, paramDef, async (ps, me) => { } else { const q: FindOptionsWhere = ps.userId != null - ? { id: ps.userId } + ? ps.userId.startsWith("http") + ? { uri: ps.userId } + : { id: ps.userId } : { usernameLower: ps.username!.toLowerCase(), host: IsNull() }; user = await Users.findOneBy(q); diff --git a/packages/backend/src/server/api/stream/index.ts b/packages/backend/src/server/api/stream/index.ts index 055fe200b..b8482c568 100644 --- a/packages/backend/src/server/api/stream/index.ts +++ b/packages/backend/src/server/api/stream/index.ts @@ -394,7 +394,6 @@ export default class Connection { * クライアントにメッセージ送信 */ public sendMessageToWs(type: string, payload: any) { - console.log(payload, this.isMastodonCompatible); if (this.isMastodonCompatible) { if (payload.type === "note") { this.wsConnection.send( diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index f1e0ed692..0d4034f55 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -590,24 +590,6 @@ router.get("/channels/:channel", async (ctx, next) => { }); //#endregion -router.get("/_info_card_", async (ctx) => { - const meta = await fetchMeta(true); - if (meta.privateMode) { - ctx.status = 403; - return; - } - - ctx.remove("X-Frame-Options"); - - await ctx.render("info-card", { - version: config.version, - host: config.host, - meta: meta, - originalUsersCount: await Users.countBy({ host: IsNull() }), - originalNotesCount: await Notes.countBy({ userHost: IsNull() }), - }); -}); - router.get("/bios", async (ctx) => { await ctx.render("bios", { version: config.version, diff --git a/packages/backend/src/server/web/manifest.json b/packages/backend/src/server/web/manifest.json index 1e662fb20..647a5d437 100644 --- a/packages/backend/src/server/web/manifest.json +++ b/packages/backend/src/server/web/manifest.json @@ -41,7 +41,7 @@ "url": "url" } }, - "screenshots" : [ + "screenshots": [ { "src": "/static-assets/screenshots/1.webp", "sizes": "1195x579", @@ -57,7 +57,7 @@ "label": "Posts" } ], - "shortcuts" : [ + "shortcuts": [ { "name": "Notifications", "short_name": "Notifs", @@ -68,7 +68,5 @@ "url": "/my/messaging" } ], - "categories": [ - "social" - ] + "categories": ["social"] } diff --git a/packages/backend/src/server/web/views/channel.pug b/packages/backend/src/server/web/views/channel.pug index c4594b766..2427144fb 100644 --- a/packages/backend/src/server/web/views/channel.pug +++ b/packages/backend/src/server/web/views/channel.pug @@ -13,7 +13,7 @@ block desc block og unless privateMode - meta(property='og:type' content='article') + meta(property='og:type' content='article') meta(property='og:title' content= title) meta(property='og:description' content= channel.description) meta(property='og:url' content= url) diff --git a/packages/backend/src/server/web/views/clip.pug b/packages/backend/src/server/web/views/clip.pug index 4c29d64d1..79d629380 100644 --- a/packages/backend/src/server/web/views/clip.pug +++ b/packages/backend/src/server/web/views/clip.pug @@ -14,7 +14,7 @@ block desc block og unless privateMode - meta(property='og:type' content='article') + meta(property='og:type' content='article') meta(property='og:title' content= title) meta(property='og:description' content= clip.description) meta(property='og:url' content= url) diff --git a/packages/backend/src/server/web/views/gallery-post.pug b/packages/backend/src/server/web/views/gallery-post.pug index 86bbb4769..561a19b25 100644 --- a/packages/backend/src/server/web/views/gallery-post.pug +++ b/packages/backend/src/server/web/views/gallery-post.pug @@ -14,7 +14,7 @@ block desc block og unless privateMode - meta(property='og:type' content='article') + meta(property='og:type' content='article') meta(property='og:title' content= title) meta(property='og:description' content= post.description) meta(property='og:url' content= url) diff --git a/packages/backend/src/server/web/views/info-card.pug b/packages/backend/src/server/web/views/info-card.pug deleted file mode 100644 index be52d0c39..000000000 --- a/packages/backend/src/server/web/views/info-card.pug +++ /dev/null @@ -1,50 +0,0 @@ -doctype html - -html - - head - meta(charset='utf-8') - meta(name='application-name' content='Calckey') - title= meta.name || host - style. - html, body { - margin: 0; - padding: 0; - min-height: 100vh; - background: #fff; - } - - #a { - display: block; - } - - #banner { - background-size: cover; - background-position: center center; - } - - #title { - display: inline-block; - margin: 24px; - padding: 0.5em 0.8em; - color: #fff; - background: rgba(0, 0, 0, 0.5); - font-weight: bold; - font-size: 1.3em; - } - - #content { - overflow: auto; - color: #353c3e; - } - - #description { - margin: 24px; - } - - body - a#a(href=`https://${host}` target="_blank") - header#banner(style=`background-image: url(${meta.bannerUrl})`) - div#title= meta.name || host - div#content - div#description= meta.description diff --git a/packages/backend/src/server/web/views/note.pug b/packages/backend/src/server/web/views/note.pug index ff2a77165..dae0a82d5 100644 --- a/packages/backend/src/server/web/views/note.pug +++ b/packages/backend/src/server/web/views/note.pug @@ -18,7 +18,7 @@ block desc block og unless privateMode - meta(property='og:type' content='article') + meta(property='og:type' content='article') meta(property='og:title' content= title) meta(property='og:description' content= summary) meta(property='og:url' content= url) @@ -27,7 +27,7 @@ block og meta(property='og:image:width' content=note.files[0].properties.width) meta(property='og:image:height' content=note.files[0].properties.height) meta(property='og:image:type' content=note.files[0].type) - meta(property='twitter:card' content="summary_large_image") + meta(property='twitter:card' content="summary_large_image") if isVideo meta(property='og:video:type' content=note.files[0].type) meta(property='og:video' content=note.files[0].url) diff --git a/packages/backend/src/server/web/views/page.pug b/packages/backend/src/server/web/views/page.pug index eacaaab98..bfc7ebf79 100644 --- a/packages/backend/src/server/web/views/page.pug +++ b/packages/backend/src/server/web/views/page.pug @@ -14,7 +14,7 @@ block desc block og unless privateMode - meta(property='og:type' content='article') + meta(property='og:type' content='article') meta(property='og:title' content= title) meta(property='og:description' content= page.summary) meta(property='og:url' content= url) diff --git a/packages/backend/src/server/web/views/user.pug b/packages/backend/src/server/web/views/user.pug index 1cc429156..f5820f55f 100644 --- a/packages/backend/src/server/web/views/user.pug +++ b/packages/backend/src/server/web/views/user.pug @@ -13,11 +13,12 @@ block desc block og unless privateMode - meta(property='og:type' content='blog') - meta(property='og:title' content= title) - meta(property='og:description' content= profile.description) - meta(property='og:url' content= url) - meta(property='og:image' content= avatarUrl) + meta(property='og:type' content='profile') + meta(property='og:title' content= title) + meta(property='og:description' content= profile.description) + meta(property='og:url' content= url) + meta(property='og:image' content= avatarUrl) + meta(property='profile:username' content= user.username) block meta unless privateMode diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 66c5b8508..bd54db7e2 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -67,6 +67,7 @@ import type { UserProfile } from "@/models/entities/user-profile.js"; import { db } from "@/db/postgre.js"; import { getActiveWebhooks } from "@/misc/webhook-cache.js"; import { shouldSilenceInstance } from "@/misc/should-block-instance.js"; +import meilisearch from "../../db/meilisearch.js"; const mutedWordsCache = new Cache< { userId: UserProfile["userId"]; mutedWords: UserProfile["mutedWords"] }[] @@ -748,7 +749,7 @@ async function insertNote( } } -export async function index(note: Note): Promise { +export async function index(note: Note, reindexing: boolean): Promise { if (!note.text) return; if (config.elasticsearch && es) { @@ -776,6 +777,10 @@ export async function index(note: Note): Promise { note.text, ); } + + if (meilisearch && !reindexing) { + await meilisearch.ingestNote(note); + } } async function notifyToWatchersOfRenotee( diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts index 392578e2f..90175ccdc 100644 --- a/packages/backend/src/services/note/delete.ts +++ b/packages/backend/src/services/note/delete.ts @@ -21,6 +21,7 @@ import { import { countSameRenotes } from "@/misc/count-same-renotes.js"; import { registerOrFetchInstanceDoc } from "../register-or-fetch-instance-doc.js"; import { deliverToRelays } from "../relay.js"; +import meilisearch from "@/db/meilisearch.js"; /** * 投稿を削除します。 @@ -119,6 +120,10 @@ export default async function ( id: note.id, userId: user.id, }); + + if (meilisearch) { + await meilisearch.deleteNotes(note.id); + } } async function findCascadingNotes(note: Note) { diff --git a/packages/calckey-js/package.json b/packages/calckey-js/package.json index 598dd1cdb..6f724fc21 100644 --- a/packages/calckey-js/package.json +++ b/packages/calckey-js/package.json @@ -34,9 +34,7 @@ "tsd": "^0.19.1", "typescript": "4.5.4" }, - "files": [ - "built" - ], + "files": ["built"], "dependencies": { "autobind-decorator": "^2.4.0", "eventemitter3": "^4.0.7", diff --git a/packages/calckey-js/tsconfig.json b/packages/calckey-js/tsconfig.json index a03a24262..642bcc45b 100644 --- a/packages/calckey-js/tsconfig.json +++ b/packages/calckey-js/tsconfig.json @@ -15,11 +15,6 @@ "noImplicitReturns": true, "esModuleInterop": true }, - "include": [ - "src/**/*" - ], - "exclude": [ - "node_modules", - "test/**/*" - ] + "include": ["src/**/*"], + "exclude": ["node_modules", "test/**/*"] } diff --git a/packages/client/.vscode/settings.json b/packages/client/.vscode/settings.json index 1950a66b9..d654bb166 100644 --- a/packages/client/.vscode/settings.json +++ b/packages/client/.vscode/settings.json @@ -1,6 +1,15 @@ { - "typescript.tsdk": "node_modules\\typescript\\lib", + "typescript.tsdk": "node_modules/typescript/lib", "path-intellisense.mappings": { "@": "${workspaceRoot}/packages/client/src/" }, + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true, + "**/_client_dist_": true + } } diff --git a/packages/client/package.json b/packages/client/package.json index 1af31dd09..83ea429c4 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -33,17 +33,17 @@ "broadcast-channel": "4.19.1", "browser-image-resizer": "github:misskey-dev/browser-image-resizer", "calckey-js": "workspace:*", - "chart.js": "4.1.1", - "chartjs-adapter-date-fns": "2.0.1", + "chart.js": "4.3.0", + "chartjs-adapter-date-fns": "3.0.0", "chartjs-chart-matrix": "^2.0.1", - "chartjs-plugin-gradient": "0.5.1", - "chartjs-plugin-zoom": "1.2.1", + "chartjs-plugin-gradient": "0.6.1", + "chartjs-plugin-zoom": "2.0.1", "city-timezones": "^1.2.1", "compare-versions": "5.0.3", "cropperjs": "2.0.0-beta.2", "cross-env": "7.0.3", "cypress": "10.11.0", - "date-fns": "2.29.3", + "date-fns": "2.30.0", "escape-regexp": "0.0.1", "eventemitter3": "4.0.7", "gsap": "^3.11.4", @@ -79,7 +79,7 @@ "typescript": "4.9.4", "uuid": "9.0.0", "vanilla-tilt": "1.8.0", - "vite": "^4.1.1", + "vite": "4.3.9", "vite-plugin-compression": "^0.5.1", "vue": "3.2.45", "vue-isyourpasswordsafe": "^2.0.0", diff --git a/packages/client/src/components/MkCheatSheetDialog.vue b/packages/client/src/components/MkCheatSheetDialog.vue index 04b8cec6e..3b723cde5 100644 --- a/packages/client/src/components/MkCheatSheetDialog.vue +++ b/packages/client/src/components/MkCheatSheetDialog.vue @@ -6,12 +6,7 @@ @closed="$emit('closed')" > - -
-
- -
-
+ diff --git a/packages/client/src/components/MkInfo.vue b/packages/client/src/components/MkInfo.vue index 43f2de29e..ba3a606ab 100644 --- a/packages/client/src/components/MkInfo.vue +++ b/packages/client/src/components/MkInfo.vue @@ -1,34 +1,91 @@ diff --git a/packages/client/src/components/MkMediaImage.vue b/packages/client/src/components/MkMediaImage.vue index 74f45c69c..9097a4771 100644 --- a/packages/client/src/components/MkMediaImage.vue +++ b/packages/client/src/components/MkMediaImage.vue @@ -91,7 +91,7 @@ watch( align-items: center; padding: 30px; box-sizing: border-box; - background: rgba(0,0,0,0.5); + background: rgba(0, 0, 0, 0.5); > .wrapper { display: table-cell; diff --git a/packages/client/src/components/MkMediaList.vue b/packages/client/src/components/MkMediaList.vue index 901aceeff..c01ccd5d8 100644 --- a/packages/client/src/components/MkMediaList.vue +++ b/packages/client/src/components/MkMediaList.vue @@ -11,10 +11,7 @@ :data-count="previewableCount < 5 ? previewableCount : null" :class="{ dmWidth: inDm }" > -
+
@@ -167,6 +187,7 @@ import MkUrlPreview from "@/components/MkUrlPreview.vue"; import XShowMoreButton from "@/components/MkShowMoreButton.vue"; import XCwButton from "@/components/MkCwButton.vue"; import MkButton from "@/components/MkButton.vue"; +import { notePage } from "@/filters/note"; import { extractUrlFromMfm } from "@/scripts/extract-url-from-mfm"; import { extractMfmWithAnimation } from "@/scripts/extract-mfm"; import { i18n } from "@/i18n"; @@ -188,13 +209,13 @@ const emit = defineEmits<{ const cwButton = ref(); const showMoreButton = ref(); -const isLong = !props.detailedView - && ( props.note.cw == null - && (props.note.text != null - && (props.note.text.split("\n").length > 9 || props.note.text.length > 500) - ) - || props.note.files.length > 4 - ); +const isLong = + !props.detailedView && + ((props.note.cw == null && + props.note.text != null && + (props.note.text.split("\n").length > 9 || + props.note.text.length > 500)) || + props.note.files.length > 4); const collapsed = $ref(props.note.cw == null && isLong); @@ -238,7 +259,8 @@ function focusFooter(ev) { diff --git a/packages/client/src/pages/admin/overview.metrics.vue b/packages/client/src/pages/admin/overview.metrics.vue new file mode 100644 index 000000000..cfd497439 --- /dev/null +++ b/packages/client/src/pages/admin/overview.metrics.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/packages/client/src/pages/admin/overview.vue b/packages/client/src/pages/admin/overview.vue index 4c3391ce4..d88022595 100644 --- a/packages/client/src/pages/admin/overview.vue +++ b/packages/client/src/pages/admin/overview.vue @@ -50,6 +50,11 @@ + +
@@ -71,6 +76,7 @@ import XActiveUsers from "./overview.active-users.vue"; import XStats from "./overview.stats.vue"; import XModerators from "./overview.moderators.vue"; import XHeatmap from "./overview.heatmap.vue"; +// import XMetrics from "./overview.metrics.vue"; import MkTagCloud from "@/components/MkTagCloud.vue"; import { version, url } from "@/config"; import * as os from "@/os"; diff --git a/packages/client/src/pages/channels.vue b/packages/client/src/pages/channels.vue index d03fb61d5..b79985baf 100644 --- a/packages/client/src/pages/channels.vue +++ b/packages/client/src/pages/channels.vue @@ -7,6 +7,9 @@ :tabs="headerTabs" /> + {{ + i18n.ts.channelFederationWarn + }} - + -
+
{{ i18n.ts._mfm.intro }}

@@ -449,6 +449,10 @@ import { definePageMetadata } from "@/scripts/page-metadata"; import { i18n } from "@/i18n"; import { instance } from "@/instance"; +defineProps<{ + popup?: boolean; +}>(); + let preview_mention = $ref("@example"); let preview_hashtag = $ref("#test"); let preview_link = $ref(`[${i18n.ts._mfm.dummy}](https://calckey.org)`); @@ -514,10 +518,8 @@ definePageMetadata({ }); - diff --git a/packages/client/src/widgets/server-metric/cpu.vue b/packages/client/src/widgets/server-metric/cpu.vue index 5aa4d2698..563fe3b0f 100644 --- a/packages/client/src/widgets/server-metric/cpu.vue +++ b/packages/client/src/widgets/server-metric/cpu.vue @@ -2,7 +2,7 @@
-

CPU

+

CPU

{{ meta.cpu.cores }} Logical cores

{{ meta.cpu.model }}

diff --git a/packages/client/src/widgets/server-metric/index.vue b/packages/client/src/widgets/server-metric/index.vue index 96dd3333d..1eb9f56b8 100644 --- a/packages/client/src/widgets/server-metric/index.vue +++ b/packages/client/src/widgets/server-metric/index.vue @@ -38,6 +38,11 @@ :connection="connection" :meta="meta" /> +
@@ -56,6 +61,7 @@ import XNet from "./net.vue"; import XCpu from "./cpu.vue"; import XMemory from "./mem.vue"; import XDisk from "./disk.vue"; +import XMeili from "./meilisearch.vue"; import MkContainer from "@/components/MkContainer.vue"; import { GetFormResultType } from "@/scripts/form"; import * as os from "@/os"; @@ -102,7 +108,7 @@ os.api("server-info", {}).then((res) => { }); const toggleView = () => { - if (widgetProps.view === 4) { + if (widgetProps.view === 5) { widgetProps.view = 0; } else { widgetProps.view++; diff --git a/packages/client/src/widgets/server-metric/meilisearch.vue b/packages/client/src/widgets/server-metric/meilisearch.vue new file mode 100644 index 000000000..78032cb6e --- /dev/null +++ b/packages/client/src/widgets/server-metric/meilisearch.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/packages/client/src/widgets/server-metric/mem.vue b/packages/client/src/widgets/server-metric/mem.vue index e3ef00d5e..80cad4a82 100644 --- a/packages/client/src/widgets/server-metric/mem.vue +++ b/packages/client/src/widgets/server-metric/mem.vue @@ -2,7 +2,7 @@
-

RAM

+

RAM

Total: {{ bytes(total, 1) }}

Used: {{ bytes(used, 1) }}

Free: {{ bytes(free, 1) }}

diff --git a/packages/sw/package.json b/packages/sw/package.json index 112005ba7..0d0ac52df 100644 --- a/packages/sw/package.json +++ b/packages/sw/package.json @@ -6,9 +6,7 @@ "watch": "pnpm swc src -d built -D -w", "lint": "pnpm rome check \"src/**/*.ts\"" }, - "dependencies": { - - }, + "dependencies": {}, "devDependencies": { "@swc/cli": "^0.1.62", "@swc/core": "^1.3.50", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 493e9fc06..f001fec77 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,8 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false overrides: chokidar: ^3.3.1 @@ -8,14 +12,14 @@ importers: .: dependencies: '@bull-board/api': - specifier: ^4.10.2 - version: 4.10.2 + specifier: 5.2.0 + version: 5.2.0(@bull-board/ui@5.2.0) '@bull-board/ui': - specifier: ^4.10.2 - version: 4.10.2 + specifier: 5.2.0 + version: 5.2.0 '@napi-rs/cli': - specifier: ^2.15.0 - version: 2.15.0 + specifier: ^2.16.1 + version: 2.16.1 '@tensorflow/tfjs': specifier: ^3.21.0 version: 3.21.0(seedrandom@3.0.5) @@ -78,14 +82,14 @@ importers: packages/backend: dependencies: '@bull-board/api': - specifier: ^4.6.4 - version: 4.10.2 + specifier: 5.2.0 + version: 5.2.0(@bull-board/ui@5.2.0) '@bull-board/koa': - specifier: ^4.6.4 - version: 4.10.2(@types/koa@2.13.5)(pug@3.0.2) + specifier: 5.2.0 + version: 5.2.0(@types/koa@2.13.5)(pug@3.0.2) '@bull-board/ui': - specifier: ^4.6.4 - version: 4.10.2 + specifier: 5.2.0 + version: 5.2.0 '@calckey/megalodon': specifier: 5.2.0 version: 5.2.0 @@ -156,8 +160,8 @@ importers: specifier: 1.1.5 version: 1.1.5 bull: - specifier: 4.10.2 - version: 4.10.2 + specifier: 4.10.4 + version: 4.10.4 cacheable-lookup: specifier: 7.0.0 version: 7.0.0 @@ -186,8 +190,8 @@ importers: specifier: 0.5.4 version: 0.5.4 date-fns: - specifier: 2.29.3 - version: 2.29.3 + specifier: 2.30.0 + version: 2.30.0 deep-email-validator: specifier: 0.1.21 version: 0.1.21 @@ -210,8 +214,8 @@ importers: specifier: 0.1.2 version: 0.1.2 ioredis: - specifier: 5.2.4 - version: 5.2.4 + specifier: 5.3.2 + version: 5.3.2 ip-cidr: specifier: 3.0.11 version: 3.0.11 @@ -263,6 +267,9 @@ importers: koa-views: specifier: 7.0.2 version: 7.0.2(@types/koa@2.13.5)(ejs@3.1.8)(pug@3.0.2) + meilisearch: + specifier: 0.32.4 + version: 0.32.4 mfm-js: specifier: 0.23.3 version: 0.23.3 @@ -388,7 +395,7 @@ importers: version: 14.0.0 typeorm: specifier: 0.3.11 - version: 0.3.11(ioredis@5.2.4)(pg@8.8.0)(ts-node@10.9.1) + version: 0.3.11(ioredis@5.3.2)(pg@8.8.0)(ts-node@10.9.1) ulid: specifier: 2.3.0 version: 2.3.0 @@ -602,6 +609,15 @@ importers: specifier: 8.11.0 version: 8.11.0 + packages/backend/native-utils: + devDependencies: + '@napi-rs/cli': + specifier: 2.16.1 + version: 2.16.1 + ava: + specifier: 5.1.1 + version: 5.1.1 + packages/calckey-js: dependencies: autobind-decorator: @@ -715,7 +731,7 @@ importers: version: 8.3.4 '@vitejs/plugin-vue': specifier: 4.0.0 - version: 4.0.0(vite@4.1.1)(vue@3.2.45) + version: 4.0.0(vite@4.3.9)(vue@3.2.45) '@vue/compiler-sfc': specifier: 3.2.45 version: 3.2.45 @@ -738,20 +754,20 @@ importers: specifier: workspace:* version: link:../calckey-js chart.js: - specifier: 4.1.1 - version: 4.1.1 + specifier: 4.3.0 + version: 4.3.0 chartjs-adapter-date-fns: - specifier: 2.0.1 - version: 2.0.1(chart.js@4.1.1) + specifier: 3.0.0 + version: 3.0.0(chart.js@4.3.0)(date-fns@2.30.0) chartjs-chart-matrix: specifier: ^2.0.1 - version: 2.0.1(chart.js@4.1.1) + version: 2.0.1(chart.js@4.3.0) chartjs-plugin-gradient: - specifier: 0.5.1 - version: 0.5.1(chart.js@4.1.1) + specifier: 0.6.1 + version: 0.6.1(chart.js@4.3.0) chartjs-plugin-zoom: - specifier: 1.2.1 - version: 1.2.1(chart.js@4.1.1) + specifier: 2.0.1 + version: 2.0.1(chart.js@4.3.0) city-timezones: specifier: ^1.2.1 version: 1.2.1 @@ -768,8 +784,8 @@ importers: specifier: 10.11.0 version: 10.11.0 date-fns: - specifier: 2.29.3 - version: 2.29.3 + specifier: 2.30.0 + version: 2.30.0 escape-regexp: specifier: 0.0.1 version: 0.0.1 @@ -876,11 +892,11 @@ importers: specifier: 1.8.0 version: 1.8.0 vite: - specifier: ^4.1.1 - version: 4.1.1(sass@1.57.1) + specifier: 4.3.9 + version: 4.3.9(sass@1.57.1) vite-plugin-compression: specifier: ^0.5.1 - version: 0.5.1(vite@4.1.1) + version: 0.5.1(vite@4.3.9) vue: specifier: 3.2.45 version: 3.2.45 @@ -1246,6 +1262,12 @@ packages: regenerator-runtime: 0.13.11 dev: true + /@babel/runtime@7.22.3: + resolution: {integrity: sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + /@babel/template@7.20.7: resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} engines: {node: '>=6.9.0'} @@ -1310,17 +1332,20 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true - /@bull-board/api@4.10.2: - resolution: {integrity: sha512-lRHo0A7hsz71aOx1ZN0SmLLWfSuvKdL6EZ4imlgo5SuXGozybvlRc5KPIJU2/E1w5meoUGi+nFezBwp1gT/SMw==} + /@bull-board/api@5.2.0(@bull-board/ui@5.2.0): + resolution: {integrity: sha512-1HGF2EF/4zI3+Cj414nQzwFprLXOJTlVdqXUf5UEBS4HtYafWv93mGIwkrD8S4Bpz4VSvM87adF6tQPJ7Ewt+w==} + peerDependencies: + '@bull-board/ui': 5.2.0 dependencies: + '@bull-board/ui': 5.2.0 redis-info: 3.1.0 dev: false - /@bull-board/koa@4.10.2(@types/koa@2.13.5)(pug@3.0.2): - resolution: {integrity: sha512-gabPtsMOt2SQHkS5VcY1q/FCpbBRFiFrbWbcouZ7zWKg413J8nG+yErz3pc0rbmp23kbKX6wTG/diWKhE7EWbA==} + /@bull-board/koa@5.2.0(@types/koa@2.13.5)(pug@3.0.2): + resolution: {integrity: sha512-jntDAl/POouD0PS/iiKXBNl26SuUf7Y5uL3EgpDN7isvwFcpKhvdk0VdBypjrkRHN6rPaEJJPkEtK30qv01XYw==} dependencies: - '@bull-board/api': 4.10.2 - '@bull-board/ui': 4.10.2 + '@bull-board/api': 5.2.0(@bull-board/ui@5.2.0) + '@bull-board/ui': 5.2.0 ejs: 3.1.8 koa: 2.13.4 koa-mount: 4.0.0 @@ -1384,10 +1409,10 @@ packages: - whiskers dev: false - /@bull-board/ui@4.10.2: - resolution: {integrity: sha512-vaHGojG5D3xjnaed3nwOaLy4Y06RgDJdYRaFR5E06SjZ0vOvjVYGD6s4cykK512Aw/ElFhKDPwzhf8BvpwAtDQ==} + /@bull-board/ui@5.2.0: + resolution: {integrity: sha512-f2sgs7AjOVch7tFhbmlVCkhZjJWboxwNxWEfAsIUd1WidUC+Ef5J02tpQvu7apzRtu5zcn8IiJtI5HFO6oKaCA==} dependencies: - '@bull-board/api': 4.10.2 + '@bull-board/api': 5.2.0(@bull-board/ui@5.2.0) dev: false /@calckey/megalodon@5.2.0: @@ -1596,8 +1621,8 @@ packages: - supports-color dev: false - /@esbuild/android-arm64@0.16.17: - resolution: {integrity: sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==} + /@esbuild/android-arm64@0.17.19: + resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} engines: {node: '>=12'} cpu: [arm64] os: [android] @@ -1605,8 +1630,8 @@ packages: dev: true optional: true - /@esbuild/android-arm@0.16.17: - resolution: {integrity: sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==} + /@esbuild/android-arm@0.17.19: + resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} engines: {node: '>=12'} cpu: [arm] os: [android] @@ -1614,8 +1639,8 @@ packages: dev: true optional: true - /@esbuild/android-x64@0.16.17: - resolution: {integrity: sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==} + /@esbuild/android-x64@0.17.19: + resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} engines: {node: '>=12'} cpu: [x64] os: [android] @@ -1623,8 +1648,8 @@ packages: dev: true optional: true - /@esbuild/darwin-arm64@0.16.17: - resolution: {integrity: sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==} + /@esbuild/darwin-arm64@0.17.19: + resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] @@ -1632,8 +1657,8 @@ packages: dev: true optional: true - /@esbuild/darwin-x64@0.16.17: - resolution: {integrity: sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==} + /@esbuild/darwin-x64@0.17.19: + resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] @@ -1641,8 +1666,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-arm64@0.16.17: - resolution: {integrity: sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==} + /@esbuild/freebsd-arm64@0.17.19: + resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] @@ -1650,8 +1675,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-x64@0.16.17: - resolution: {integrity: sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==} + /@esbuild/freebsd-x64@0.17.19: + resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] @@ -1659,8 +1684,8 @@ packages: dev: true optional: true - /@esbuild/linux-arm64@0.16.17: - resolution: {integrity: sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==} + /@esbuild/linux-arm64@0.17.19: + resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} engines: {node: '>=12'} cpu: [arm64] os: [linux] @@ -1668,8 +1693,8 @@ packages: dev: true optional: true - /@esbuild/linux-arm@0.16.17: - resolution: {integrity: sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==} + /@esbuild/linux-arm@0.17.19: + resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} engines: {node: '>=12'} cpu: [arm] os: [linux] @@ -1677,8 +1702,8 @@ packages: dev: true optional: true - /@esbuild/linux-ia32@0.16.17: - resolution: {integrity: sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==} + /@esbuild/linux-ia32@0.17.19: + resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -1686,8 +1711,8 @@ packages: dev: true optional: true - /@esbuild/linux-loong64@0.16.17: - resolution: {integrity: sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==} + /@esbuild/linux-loong64@0.17.19: + resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} engines: {node: '>=12'} cpu: [loong64] os: [linux] @@ -1695,8 +1720,8 @@ packages: dev: true optional: true - /@esbuild/linux-mips64el@0.16.17: - resolution: {integrity: sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==} + /@esbuild/linux-mips64el@0.17.19: + resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] @@ -1704,8 +1729,8 @@ packages: dev: true optional: true - /@esbuild/linux-ppc64@0.16.17: - resolution: {integrity: sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==} + /@esbuild/linux-ppc64@0.17.19: + resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] @@ -1713,8 +1738,8 @@ packages: dev: true optional: true - /@esbuild/linux-riscv64@0.16.17: - resolution: {integrity: sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==} + /@esbuild/linux-riscv64@0.17.19: + resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] @@ -1722,8 +1747,8 @@ packages: dev: true optional: true - /@esbuild/linux-s390x@0.16.17: - resolution: {integrity: sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==} + /@esbuild/linux-s390x@0.17.19: + resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} engines: {node: '>=12'} cpu: [s390x] os: [linux] @@ -1731,8 +1756,8 @@ packages: dev: true optional: true - /@esbuild/linux-x64@0.16.17: - resolution: {integrity: sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==} + /@esbuild/linux-x64@0.17.19: + resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -1740,8 +1765,8 @@ packages: dev: true optional: true - /@esbuild/netbsd-x64@0.16.17: - resolution: {integrity: sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==} + /@esbuild/netbsd-x64@0.17.19: + resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] @@ -1749,8 +1774,8 @@ packages: dev: true optional: true - /@esbuild/openbsd-x64@0.16.17: - resolution: {integrity: sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==} + /@esbuild/openbsd-x64@0.17.19: + resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] @@ -1758,8 +1783,8 @@ packages: dev: true optional: true - /@esbuild/sunos-x64@0.16.17: - resolution: {integrity: sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==} + /@esbuild/sunos-x64@0.17.19: + resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] @@ -1767,8 +1792,8 @@ packages: dev: true optional: true - /@esbuild/win32-arm64@0.16.17: - resolution: {integrity: sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==} + /@esbuild/win32-arm64@0.17.19: + resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} engines: {node: '>=12'} cpu: [arm64] os: [win32] @@ -1776,8 +1801,8 @@ packages: dev: true optional: true - /@esbuild/win32-ia32@0.16.17: - resolution: {integrity: sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==} + /@esbuild/win32-ia32@0.17.19: + resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} engines: {node: '>=12'} cpu: [ia32] os: [win32] @@ -1785,8 +1810,8 @@ packages: dev: true optional: true - /@esbuild/win32-x64@0.16.17: - resolution: {integrity: sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==} + /@esbuild/win32-x64@0.17.19: + resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -2140,7 +2165,7 @@ packages: detect-libc: 2.0.1 https-proxy-agent: 5.0.1 make-dir: 3.1.0 - node-fetch: 2.6.8 + node-fetch: 2.6.11 nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 @@ -2158,7 +2183,7 @@ packages: detect-libc: 2.0.1 https-proxy-agent: 5.0.1 make-dir: 3.1.0 - node-fetch: 2.6.8 + node-fetch: 2.6.11 nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 @@ -2271,11 +2296,10 @@ packages: dev: false optional: true - /@napi-rs/cli@2.15.0: - resolution: {integrity: sha512-RDDr7ZF0cgbd37+NBGeQOjP7Tm/iNM+y3FmrT5bVQBXLePOTuKVC/dBsdN5UZv3Sl2XAwEvBfaGR90E0d8AA6g==} + /@napi-rs/cli@2.16.1: + resolution: {integrity: sha512-L0Gr5iEQIDEbvWdDr1HUaBOxBSHL1VZhWSk1oryawoT8qJIY+KGfLFelU+Qma64ivCPbxYpkfPoKYVG3rcoGIA==} engines: {node: '>= 10'} hasBin: true - dev: false /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -2819,7 +2843,7 @@ packages: '@types/webgl-ext': 0.0.30 '@webgpu/types': 0.1.16 long: 4.0.0 - node-fetch: 2.6.8 + node-fetch: 2.6.11 seedrandom: 3.0.5 transitivePeerDependencies: - encoding @@ -2835,7 +2859,7 @@ packages: '@types/webgl-ext': 0.0.30 '@webgpu/types': 0.1.21 long: 4.0.0 - node-fetch: 2.6.8 + node-fetch: 2.6.11 seedrandom: 3.0.5 transitivePeerDependencies: - encoding @@ -2849,7 +2873,7 @@ packages: dependencies: '@tensorflow/tfjs-core': 3.21.0 '@types/node-fetch': 2.6.2 - node-fetch: 2.6.8 + node-fetch: 2.6.11 seedrandom: 3.0.5 string_decoder: 1.3.0 transitivePeerDependencies: @@ -2864,7 +2888,7 @@ packages: dependencies: '@tensorflow/tfjs-core': 4.2.0 '@types/node-fetch': 2.6.2 - node-fetch: 2.6.8 + node-fetch: 2.6.11 seedrandom: 3.0.5 string_decoder: 1.3.0 transitivePeerDependencies: @@ -3194,7 +3218,7 @@ packages: resolution: {integrity: sha512-zJbJ3FVE17CNl5KXzdeSPtdltc4tMT3TzC6fxQS0sQngkbFZ6h+0uTafsRqu+eSLIugf6Yb0Ea0SUuRr42Nk9g==} deprecated: This is a stub types definition. ioredis provides its own type definitions, so you do not need this installed. dependencies: - ioredis: 5.2.4 + ioredis: 5.3.2 transitivePeerDependencies: - supports-color dev: true @@ -3788,14 +3812,14 @@ packages: eslint-visitor-keys: 3.3.0 dev: true - /@vitejs/plugin-vue@4.0.0(vite@4.1.1)(vue@3.2.45): + /@vitejs/plugin-vue@4.0.0(vite@4.3.9)(vue@3.2.45): resolution: {integrity: sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^4.0.0 vue: ^3.2.25 dependencies: - vite: 4.1.1(sass@1.57.1) + vite: 4.3.9(sass@1.57.1) vue: 3.2.45 dev: true @@ -3817,7 +3841,7 @@ packages: resolution: {integrity: sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==} dependencies: '@babel/parser': 7.20.7 - postcss: 8.4.21 + postcss: 8.4.24 source-map: 0.6.1 dev: true @@ -4147,6 +4171,14 @@ packages: clean-stack: 2.2.0 indent-string: 4.0.0 + /aggregate-error@4.0.1: + resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} + engines: {node: '>=12'} + dependencies: + clean-stack: 4.2.0 + indent-string: 5.0.0 + dev: true + /ajv-keywords@3.5.2(ajv@6.12.6): resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} peerDependencies: @@ -4216,6 +4248,11 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + /ansi-styles@2.2.1: resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} engines: {node: '>=0.10.0'} @@ -4238,6 +4275,11 @@ packages: engines: {node: '>=10'} dev: true + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + /ansi-wrap@0.1.0: resolution: {integrity: sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==} engines: {node: '>=0.10.0'} @@ -4397,6 +4439,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /array-find-index@1.0.2: + resolution: {integrity: sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==} + engines: {node: '>=0.10.0'} + dev: true + /array-initial@1.1.0: resolution: {integrity: sha512-BC4Yl89vneCYfpLrs5JU2aAu9/a+xWbeKhvISg9PT7eWFB9UlRvI+rKEtk6mgxWr3dSkk9gQ8hCrdqt06NXPdw==} engines: {node: '>=0.10.0'} @@ -4436,11 +4483,21 @@ packages: engines: {node: '>=0.10.0'} dev: true + /arrgv@1.0.2: + resolution: {integrity: sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==} + engines: {node: '>=8.0.0'} + dev: true + /arrify@1.0.1: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} engines: {node: '>=0.10.0'} dev: true + /arrify@3.0.0: + resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==} + engines: {node: '>=12'} + dev: true + /asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} @@ -4546,6 +4603,65 @@ packages: oauth: 0.9.15 dev: false + /ava@5.1.1: + resolution: {integrity: sha512-od1CWgWVIKZSdEc1dhQWhbsd6KBs0EYjek7eqZNGPvy+NyC9Q1bXixcadlgOXwDG9aM0zLMQZwRXfe9gMb1LQQ==} + engines: {node: '>=14.19 <15 || >=16.15 <17 || >=18'} + hasBin: true + peerDependencies: + '@ava/typescript': '*' + peerDependenciesMeta: + '@ava/typescript': + optional: true + dependencies: + acorn: 8.8.1 + acorn-walk: 8.2.0 + ansi-styles: 6.2.1 + arrgv: 1.0.2 + arrify: 3.0.0 + callsites: 4.0.0 + cbor: 8.1.0 + chalk: 5.2.0 + chokidar: 3.5.3 + chunkd: 2.0.1 + ci-info: 3.7.1 + ci-parallel-vars: 1.0.1 + clean-yaml-object: 0.1.0 + cli-truncate: 3.1.0 + code-excerpt: 4.0.0 + common-path-prefix: 3.0.0 + concordance: 5.0.4 + currently-unhandled: 0.4.1 + debug: 4.3.4(supports-color@8.1.1) + del: 7.0.0 + emittery: 1.0.1 + figures: 5.0.0 + globby: 13.1.4 + ignore-by-default: 2.1.0 + indent-string: 5.0.0 + is-error: 2.2.2 + is-plain-object: 5.0.0 + is-promise: 4.0.0 + matcher: 5.0.0 + mem: 9.0.2 + ms: 2.1.3 + p-event: 5.0.1 + p-map: 5.5.0 + picomatch: 2.3.1 + pkg-conf: 4.0.0 + plur: 5.1.0 + pretty-ms: 8.0.0 + resolve-cwd: 3.0.0 + slash: 3.0.0 + stack-utils: 2.0.6 + strip-ansi: 7.1.0 + supertap: 3.0.1 + temp-dir: 3.0.0 + write-file-atomic: 5.0.1 + yargs: 17.6.2 + transitivePeerDependencies: + - supports-color + dev: true + /available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} @@ -4810,6 +4926,10 @@ packages: /bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + /blueimp-md5@2.19.0: + resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} + dev: true + /blurhash@1.1.5: resolution: {integrity: sha512-a+LO3A2DfxTaTztsmkbLYmUzUeApi0LZuKalwbNmqAHR6HhJGMt1qSV/R3wc+w4DL28holjqO3Bg74aUGavGjg==} @@ -4960,17 +5080,16 @@ packages: node-gyp-build: 4.6.0 dev: false - /bull@4.10.2: - resolution: {integrity: sha512-xa65xtWjQsLqYU/eNaXxq9VRG8xd6qNsQEjR7yjYuae05xKrzbVMVj2QgrYsTMmSs/vsqJjHqHSRRiW1+IkGXQ==} + /bull@4.10.4: + resolution: {integrity: sha512-o9m/7HjS/Or3vqRd59evBlWCXd9Lp+ALppKseoSKHaykK46SmRjAilX98PgmOz1yeVaurt8D5UtvEt4bUjM3eA==} engines: {node: '>=12'} dependencies: cron-parser: 4.7.1 debuglog: 1.0.1 get-port: 5.1.1 - ioredis: 5.2.4 + ioredis: 5.3.2 lodash: 4.17.21 msgpackr: 1.8.1 - p-timeout: 3.2.0 semver: 7.3.8 uuid: 8.3.2 transitivePeerDependencies: @@ -5087,6 +5206,11 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + /callsites@4.0.0: + resolution: {integrity: sha512-y3jRROutgpKdz5vzEhWM34TidDU8vkJppF8dszITeb1PQmSqV3DTxyV8G/lyO/DNvtE1YTedehmw9MPZsCBHxQ==} + engines: {node: '>=12.20'} + dev: true + /camelcase-keys@6.2.2: resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} engines: {node: '>=8'} @@ -5183,7 +5307,6 @@ packages: /chalk@5.2.0: resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: false /char-regex@1.0.2: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} @@ -5198,43 +5321,45 @@ packages: resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} dev: true - /chart.js@4.1.1: - resolution: {integrity: sha512-P0pCosNXp+LR8zO/QTkZKT6Hb7p0DPFtypEeVOf+6x06hX13NIb75R0DXUA4Ksx/+48chDQKtCCmRCviQRTqsA==} - engines: {pnpm: ^7.0.0} + /chart.js@4.3.0: + resolution: {integrity: sha512-ynG0E79xGfMaV2xAHdbhwiPLczxnNNnasrmPEXriXsPJGjmhOBYzFVEsB65w2qMDz+CaBJJuJD0inE/ab/h36g==} + engines: {pnpm: '>=7'} dependencies: '@kurkle/color': 0.3.2 dev: true - /chartjs-adapter-date-fns@2.0.1(chart.js@4.1.1): - resolution: {integrity: sha512-v3WV9rdnQ05ce3A0ZCjzUekJCAbfm6+3HqSoeY2BIkdMYZoYr/4T+ril1tZyDl869lz6xdNVMXejUFT9YKpw4A==} + /chartjs-adapter-date-fns@3.0.0(chart.js@4.3.0)(date-fns@2.30.0): + resolution: {integrity: sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==} peerDependencies: chart.js: '>=2.8.0' + date-fns: '>=2.0.0' dependencies: - chart.js: 4.1.1 + chart.js: 4.3.0 + date-fns: 2.30.0 dev: true - /chartjs-chart-matrix@2.0.1(chart.js@4.1.1): + /chartjs-chart-matrix@2.0.1(chart.js@4.3.0): resolution: {integrity: sha512-BGfeY+/PHnITyDlc7WfnKJ1RyOfgOzIqWp/gxzzl7pUjyoGzHDcw51qd2xJF9gdT9Def7ZwOnOMm8GJUXDxI0w==} peerDependencies: chart.js: '>=3.0.0' dependencies: - chart.js: 4.1.1 + chart.js: 4.3.0 dev: true - /chartjs-plugin-gradient@0.5.1(chart.js@4.1.1): - resolution: {integrity: sha512-vhwlYGZWan4MGZZ4Wj64Y4aIql1uCPCU1JcggLWn3cgYEv4G7pXp1YgM4XH5ugmyn6BVCgQqAhiJ2h6hppzHmQ==} + /chartjs-plugin-gradient@0.6.1(chart.js@4.3.0): + resolution: {integrity: sha512-TGHNIh8KqQMLdb+UfY80cBHYRyOC47eeokmgkeajRdKGbFt462lJiyiq4ZJ25fiM7BGsmzoBLhmVyEw4B3gQxw==} peerDependencies: chart.js: '>=2.6.0' dependencies: - chart.js: 4.1.1 + chart.js: 4.3.0 dev: true - /chartjs-plugin-zoom@1.2.1(chart.js@4.1.1): - resolution: {integrity: sha512-2zbWvw2pljrtMLMXkKw1uxYzAne5PtjJiOZftcut4Lo3Ee8qUt95RpMKDWrZ+pBZxZKQKOD/etdU4pN2jxZUmg==} + /chartjs-plugin-zoom@2.0.1(chart.js@4.3.0): + resolution: {integrity: sha512-ogOmLu6e+Q7E1XWOCOz9YwybMslz9qNfGV2a+qjfmqJYpsw5ZMoRHZBUyW+NGhkpQ5PwwPA/+rikHpBZb7PZuA==} peerDependencies: - chart.js: ^3.2.0 + chart.js: '>=3.2.0' dependencies: - chart.js: 4.1.1 + chart.js: 4.3.0 hammerjs: 2.0.8 dev: true @@ -5293,11 +5418,19 @@ packages: engines: {node: '>=6.0'} dev: true + /chunkd@2.0.1: + resolution: {integrity: sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==} + dev: true + /ci-info@3.7.1: resolution: {integrity: sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==} engines: {node: '>=8'} dev: true + /ci-parallel-vars@1.0.1: + resolution: {integrity: sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==} + dev: true + /city-timezones@1.2.1: resolution: {integrity: sha512-hruuB611QFoUFMsan7xd9B2VPMrA8XC716O/999WW34kmaJUT1hxKF2W8TSXAWkhSqgvbu70DjcDv7/wpM6vow==} dependencies: @@ -5329,6 +5462,18 @@ packages: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} + /clean-stack@4.2.0: + resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==} + engines: {node: '>=12'} + dependencies: + escape-string-regexp: 5.0.0 + dev: true + + /clean-yaml-object@0.1.0: + resolution: {integrity: sha512-3yONmlN9CSAkzNwnRCiJQ7Q2xK5mWuEfL3PuTZcAUzhObbXsfsnMptJzXwz93nc5zn9V9TwCVMmV7w4xsm43dw==} + engines: {node: '>=0.10.0'} + dev: true + /cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -5366,6 +5511,14 @@ packages: string-width: 4.2.3 dev: true + /cli-truncate@3.1.0: + resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + slice-ansi: 5.0.0 + string-width: 5.1.2 + dev: true + /cliui@3.2.0: resolution: {integrity: sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==} dependencies: @@ -5396,7 +5549,6 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: false /clone-buffer@1.0.0: resolution: {integrity: sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==} @@ -5477,6 +5629,13 @@ packages: q: 1.5.1 dev: true + /code-excerpt@4.0.0: + resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + convert-to-spaces: 2.0.1 + dev: true + /code-point-at@1.1.0: resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} engines: {node: '>=0.10.0'} @@ -5608,6 +5767,10 @@ packages: engines: {node: ^12.20.0 || >=14} dev: true + /common-path-prefix@3.0.0: + resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} + dev: true + /common-tags@1.8.2: resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} engines: {node: '>=4.0.0'} @@ -5643,6 +5806,20 @@ packages: readable-stream: 2.3.7 typedarray: 0.0.6 + /concordance@5.0.4: + resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==} + engines: {node: '>=10.18.0 <11 || >=12.14.0 <13 || >=14'} + dependencies: + date-time: 3.1.0 + esutils: 2.0.3 + fast-diff: 1.3.0 + js-string-escape: 1.0.1 + lodash: 4.17.21 + md5-hex: 3.0.1 + semver: 7.3.8 + well-known-symbols: 2.0.0 + dev: true + /condense-newlines@0.2.1: resolution: {integrity: sha512-P7X+QL9Hb9B/c8HI5BFFKmjgBu2XpQuF98WZ9XkO+dBGgk5XgwiQz7o1SmpglNWId3581UcS0SFAWfoIhMHPfg==} engines: {node: '>=0.10.0'} @@ -5851,6 +6028,11 @@ packages: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} dev: true + /convert-to-spaces@2.0.1: + resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /cookies@0.8.0: resolution: {integrity: sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==} engines: {node: '>= 0.8'} @@ -5880,8 +6062,8 @@ packages: requiresBuild: true dev: false - /core-js@3.30.1: - resolution: {integrity: sha512-ZNS5nbiSwDTq4hFosEDqm65izl2CWmLz0hARJMyNQBgkUZMIF51cQiMvIQKA6hvuaeWxQDP3hEedM1JZIgTldQ==} + /core-js@3.30.2: + resolution: {integrity: sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==} requiresBuild: true dev: true @@ -5938,6 +6120,14 @@ packages: - encoding dev: true + /cross-fetch@3.1.6: + resolution: {integrity: sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==} + dependencies: + node-fetch: 2.6.11 + transitivePeerDependencies: + - encoding + dev: false + /cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} dependencies: @@ -6045,6 +6235,13 @@ packages: resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} dev: true + /currently-unhandled@0.4.1: + resolution: {integrity: sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==} + engines: {node: '>=0.10.0'} + dependencies: + array-find-index: 1.0.2 + dev: true + /custom-event-polyfill@1.0.7: resolution: {integrity: sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==} dev: true @@ -6143,9 +6340,18 @@ packages: whatwg-url: 11.0.0 dev: false - /date-fns@2.29.3: - resolution: {integrity: sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==} + /date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} + dependencies: + '@babel/runtime': 7.22.3 + + /date-time@3.1.0: + resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==} + engines: {node: '>=6'} + dependencies: + time-zone: 1.0.0 + dev: true /dayjs@1.11.7: resolution: {integrity: sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==} @@ -6311,6 +6517,20 @@ packages: resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==} dev: true + /del@7.0.0: + resolution: {integrity: sha512-tQbV/4u5WVB8HMJr08pgw0b6nG4RGt/tj+7Numvq+zqcvUFeMaIWWOUFltiU+6go8BSO2/ogsB4EasDaj0y68Q==} + engines: {node: '>=14.16'} + dependencies: + globby: 13.1.4 + graceful-fs: 4.2.11 + is-glob: 4.0.3 + is-path-cwd: 3.0.0 + is-path-inside: 4.0.0 + p-map: 5.5.0 + rimraf: 3.0.2 + slash: 4.0.0 + dev: true + /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -6490,6 +6710,10 @@ packages: object.defaults: 1.1.0 dev: true + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + /ecc-jsbn@0.1.2: resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} dependencies: @@ -6531,9 +6755,18 @@ packages: engines: {node: '>=10'} dev: true + /emittery@1.0.1: + resolution: {integrity: sha512-2ID6FdrMD9KDLldGesP6317G78K7km/kMcwItRtVFva7I/cSEOIaLpewaUb+YLXVwdAp3Ctfxh/V5zIl1sj7dQ==} + engines: {node: '>=14.16'} + dev: true + /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + /emojis-list@3.0.0: resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} engines: {node: '>= 4'} @@ -6656,34 +6889,34 @@ packages: es6-symbol: 3.1.3 dev: true - /esbuild@0.16.17: - resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==} + /esbuild@0.17.19: + resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.16.17 - '@esbuild/android-arm64': 0.16.17 - '@esbuild/android-x64': 0.16.17 - '@esbuild/darwin-arm64': 0.16.17 - '@esbuild/darwin-x64': 0.16.17 - '@esbuild/freebsd-arm64': 0.16.17 - '@esbuild/freebsd-x64': 0.16.17 - '@esbuild/linux-arm': 0.16.17 - '@esbuild/linux-arm64': 0.16.17 - '@esbuild/linux-ia32': 0.16.17 - '@esbuild/linux-loong64': 0.16.17 - '@esbuild/linux-mips64el': 0.16.17 - '@esbuild/linux-ppc64': 0.16.17 - '@esbuild/linux-riscv64': 0.16.17 - '@esbuild/linux-s390x': 0.16.17 - '@esbuild/linux-x64': 0.16.17 - '@esbuild/netbsd-x64': 0.16.17 - '@esbuild/openbsd-x64': 0.16.17 - '@esbuild/sunos-x64': 0.16.17 - '@esbuild/win32-arm64': 0.16.17 - '@esbuild/win32-ia32': 0.16.17 - '@esbuild/win32-x64': 0.16.17 + '@esbuild/android-arm': 0.17.19 + '@esbuild/android-arm64': 0.17.19 + '@esbuild/android-x64': 0.17.19 + '@esbuild/darwin-arm64': 0.17.19 + '@esbuild/darwin-x64': 0.17.19 + '@esbuild/freebsd-arm64': 0.17.19 + '@esbuild/freebsd-x64': 0.17.19 + '@esbuild/linux-arm': 0.17.19 + '@esbuild/linux-arm64': 0.17.19 + '@esbuild/linux-ia32': 0.17.19 + '@esbuild/linux-loong64': 0.17.19 + '@esbuild/linux-mips64el': 0.17.19 + '@esbuild/linux-ppc64': 0.17.19 + '@esbuild/linux-riscv64': 0.17.19 + '@esbuild/linux-s390x': 0.17.19 + '@esbuild/linux-x64': 0.17.19 + '@esbuild/netbsd-x64': 0.17.19 + '@esbuild/openbsd-x64': 0.17.19 + '@esbuild/sunos-x64': 0.17.19 + '@esbuild/win32-arm64': 0.17.19 + '@esbuild/win32-ia32': 0.17.19 + '@esbuild/win32-x64': 0.17.19 dev: true /escalade@3.1.1: @@ -7168,6 +7401,10 @@ packages: /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + /fast-glob@3.2.12: resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} engines: {node: '>=8.6.0'} @@ -7239,6 +7476,14 @@ packages: escape-string-regexp: 1.0.5 dev: true + /figures@5.0.0: + resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} + engines: {node: '>=14'} + dependencies: + escape-string-regexp: 5.0.0 + is-unicode-supported: 1.3.0 + dev: true + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -7315,6 +7560,14 @@ packages: locate-path: 6.0.0 path-exists: 4.0.0 + /find-up@6.3.0: + resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + dev: true + /find-versions@5.1.0: resolution: {integrity: sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==} engines: {node: '>=12'} @@ -7541,7 +7794,7 @@ packages: engines: {node: '>=10'} dependencies: at-least-node: 1.0.0 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.0 dev: true @@ -7564,7 +7817,7 @@ packages: resolution: {integrity: sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==} engines: {node: '>= 0.10'} dependencies: - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 through2: 2.0.5 dev: true @@ -7852,6 +8105,17 @@ packages: slash: 3.0.0 dev: true + /globby@13.1.4: + resolution: {integrity: sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + /glogg@1.0.2: resolution: {integrity: sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==} engines: {node: '>= 0.10'} @@ -8363,6 +8627,11 @@ packages: /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + /ignore-by-default@2.1.0: + resolution: {integrity: sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==} + engines: {node: '>=10 <11 || >=12 <13 || >=14'} + dev: true + /ignore@4.0.6: resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} engines: {node: '>= 4'} @@ -8405,6 +8674,11 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} + /indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + dev: true + /indexes-of@1.0.1: resolution: {integrity: sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==} dev: true @@ -8469,8 +8743,8 @@ packages: engines: {node: '>=0.10.0'} dev: true - /ioredis@5.2.4: - resolution: {integrity: sha512-qIpuAEt32lZJQ0XyrloCRdlEdUUNGG9i0UOk6zgzK6igyudNWqEBxfH6OlbnOOoBBvr1WB02mm8fR55CnikRng==} + /ioredis@5.3.2: + resolution: {integrity: sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==} engines: {node: '>=12.22.0'} dependencies: '@ioredis/commands': 1.2.0 @@ -8629,6 +8903,10 @@ packages: resolution: {integrity: sha512-r8EEQQsqT+Gn0aXFx7lTFygYQhILLCB+wn0WCDL5LZRINeLH/Rvw1j2oKodELLXYNImQ3CRlVsY8wW4cGOsyuw==} dev: false + /is-error@2.2.2: + resolution: {integrity: sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==} + dev: true + /is-expression@4.0.0: resolution: {integrity: sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==} dependencies: @@ -8661,6 +8939,11 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + /is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + dev: true + /is-generator-fn@2.1.0: resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} engines: {node: '>=6'} @@ -8726,10 +9009,20 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + /is-path-cwd@3.0.0: + resolution: {integrity: sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /is-path-inside@3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} + /is-path-inside@4.0.0: + resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} + engines: {node: '>=12'} + dev: true + /is-plain-obj@1.1.0: resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} engines: {node: '>=0.10.0'} @@ -8757,6 +9050,10 @@ packages: /is-promise@2.2.2: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + /is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + dev: true + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -8826,6 +9123,11 @@ packages: engines: {node: '>=10'} dev: true + /is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + dev: true + /is-url@1.2.4: resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} dev: false @@ -9471,6 +9773,11 @@ packages: /js-sdsl@4.2.0: resolution: {integrity: sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==} + /js-string-escape@1.0.1: + resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==} + engines: {node: '>= 0.8'} + dev: true + /js-stringify@1.0.2: resolution: {integrity: sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==} @@ -10103,6 +10410,11 @@ packages: strip-bom: 2.0.0 dev: true + /load-json-file@7.0.1: + resolution: {integrity: sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /loader-runner@4.3.0: resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} engines: {node: '>=6.11.5'} @@ -10133,6 +10445,13 @@ packages: dependencies: p-locate: 5.0.0 + /locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-locate: 6.0.0 + dev: true + /lodash.assignin@4.2.0: resolution: {integrity: sha512-yX/rx6d/UTVh7sSVWVSIMjfnz95evAgDFdb1ZozC35I9mSFCkmzptOzevxjgbQUsc78NR44LVHWjsoMQXy9FDg==} dev: false @@ -10335,6 +10654,13 @@ packages: tmpl: 1.0.5 dev: true + /map-age-cleaner@0.1.3: + resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==} + engines: {node: '>=6'} + dependencies: + p-defer: 1.0.0 + dev: true + /map-cache@0.2.2: resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} engines: {node: '>=0.10.0'} @@ -10373,6 +10699,13 @@ packages: - supports-color dev: true + /matcher@5.0.0: + resolution: {integrity: sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + escape-string-regexp: 5.0.0 + dev: true + /math-expression-evaluator@1.4.0: resolution: {integrity: sha512-4vRUvPyxdO8cWULGTh9dZWL2tZK6LDBvj+OGHBER7poH9Qdt7kXEoj20wiz4lQUbUXQZFjPbe5mVDo9nutizCw==} dev: true @@ -10381,11 +10714,34 @@ packages: resolution: {integrity: sha512-/ZVem4WygUnbmo/iE4oHZpZS97btfBtYy5Iwn1396vUZU7YhgVEN8J4UWwfZwY1ZqoTYlPgjvSw9WXauuXL0mg==} dev: true + /md5-hex@3.0.1: + resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==} + engines: {node: '>=8'} + dependencies: + blueimp-md5: 2.19.0 + dev: true + /media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} dev: false + /meilisearch@0.32.4: + resolution: {integrity: sha512-QvPtQ6F2TaqAT9fw072/MDjSCMpQifdtUBFeIk3M5jSnFpeSiv1iwfJWNfP6ByaCgR/s++K1Cqtf9vjcZe7prg==} + dependencies: + cross-fetch: 3.1.6 + transitivePeerDependencies: + - encoding + dev: false + + /mem@9.0.2: + resolution: {integrity: sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A==} + engines: {node: '>=12.20'} + dependencies: + map-age-cleaner: 0.1.3 + mimic-fn: 4.0.0 + dev: true + /meow@9.0.0: resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==} engines: {node: '>=10'} @@ -10743,8 +11099,8 @@ packages: hasBin: true dev: true - /nanoid@3.3.4: - resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} + /nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -10854,6 +11210,18 @@ packages: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} + /node-fetch@2.6.11: + resolution: {integrity: sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + /node-fetch@2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} @@ -11272,9 +11640,22 @@ packages: engines: {node: '>=12.20'} dev: false + /p-defer@1.0.0: + resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==} + engines: {node: '>=4'} + dev: true + + /p-event@5.0.1: + resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-timeout: 5.1.0 + dev: true + /p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} + dev: true /p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} @@ -11288,6 +11669,13 @@ packages: dependencies: yocto-queue: 0.1.0 + /p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + dev: true + /p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -11300,12 +11688,26 @@ packages: dependencies: p-limit: 3.1.0 + /p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + p-limit: 4.0.0 + dev: true + /p-map@4.0.0: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} dependencies: aggregate-error: 3.1.0 + /p-map@5.5.0: + resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==} + engines: {node: '>=12'} + dependencies: + aggregate-error: 4.0.1 + dev: true + /p-queue@6.6.2: resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} engines: {node: '>=8'} @@ -11319,6 +11721,12 @@ packages: engines: {node: '>=8'} dependencies: p-finally: 1.0.0 + dev: true + + /p-timeout@5.1.0: + resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==} + engines: {node: '>=12'} + dev: true /p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} @@ -11372,6 +11780,11 @@ packages: xtend: 4.0.2 dev: false + /parse-ms@3.0.0: + resolution: {integrity: sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==} + engines: {node: '>=12'} + dev: true + /parse-node-version@1.0.1: resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} engines: {node: '>= 0.10'} @@ -11433,6 +11846,11 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + /path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -11595,6 +12013,14 @@ packages: engines: {node: '>= 6'} dev: true + /pkg-conf@4.0.0: + resolution: {integrity: sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + find-up: 6.3.0 + load-json-file: 7.0.1 + dev: true + /pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -11625,6 +12051,13 @@ packages: irregular-plurals: 3.5.0 dev: true + /plur@5.1.0: + resolution: {integrity: sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + irregular-plurals: 3.5.0 + dev: true + /pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} @@ -11865,10 +12298,19 @@ packages: resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} engines: {node: ^10 || ^12 || >=14} dependencies: - nanoid: 3.3.4 + nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 + /postcss@8.4.24: + resolution: {integrity: sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + /postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} @@ -11954,6 +12396,13 @@ packages: engines: {node: '>= 0.8'} dev: true + /pretty-ms@8.0.0: + resolution: {integrity: sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==} + engines: {node: '>=14.16'} + dependencies: + parse-ms: 3.0.0 + dev: true + /pretty@2.0.0: resolution: {integrity: sha512-G9xUchgTEiNpormdYBl+Pha50gOUovT18IvAe7EYMZ1/f9W/WWMPRn+xI68yXNMUk3QXHDwo/1wV/4NejVNe1w==} engines: {node: '>=0.10.0'} @@ -12758,8 +13207,8 @@ packages: rangestr: 0.0.1 seedrandom: 2.4.2 - /rollup@3.12.1: - resolution: {integrity: sha512-t9elERrz2i4UU9z7AwISj3CQcXP39cWxgRWLdf4Tm6aKm1eYrqHIgjzXBgb67GNY1sZckTFFi0oMozh3/S++Ig==} + /rollup@3.23.0: + resolution: {integrity: sha512-h31UlwEi7FHihLe1zbk+3Q7z1k/84rb9BSwmBSr/XjOCEaBJ2YyedQDuM0t/kfOS0IxM+vk1/zI9XxYj9V+NJQ==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: @@ -12924,6 +13373,13 @@ packages: dependencies: lru-cache: 6.0.0 + /serialize-error@7.0.1: + resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} + engines: {node: '>=10'} + dependencies: + type-fest: 0.13.1 + dev: true + /serialize-javascript@6.0.0: resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} dependencies: @@ -13025,6 +13481,11 @@ packages: /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + /signal-exit@4.0.2: + resolution: {integrity: sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==} + engines: {node: '>=14'} + dev: true + /simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} dev: false @@ -13052,6 +13513,11 @@ packages: engines: {node: '>=8'} dev: true + /slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: true + /slice-ansi@3.0.0: resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} engines: {node: '>=8'} @@ -13070,6 +13536,14 @@ packages: is-fullwidth-code-point: 3.0.0 dev: true + /slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + dev: true + /smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} @@ -13393,6 +13867,15 @@ packages: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + /string_decoder@0.10.31: resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} dev: false @@ -13425,6 +13908,13 @@ packages: dependencies: ansi-regex: 5.0.1 + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + /strip-bom@2.0.0: resolution: {integrity: sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==} engines: {node: '>=0.10.0'} @@ -13507,6 +13997,16 @@ packages: - supports-color dev: false + /supertap@3.0.1: + resolution: {integrity: sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + indent-string: 5.0.0 + js-yaml: 3.14.1 + serialize-error: 7.0.1 + strip-ansi: 7.1.0 + dev: true + /supports-color@2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} engines: {node: '>=0.8.0'} @@ -13664,6 +14164,11 @@ packages: yallist: 4.0.0 dev: false + /temp-dir@3.0.0: + resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} + engines: {node: '>=14.16'} + dev: true + /terminal-link@2.1.1: resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} engines: {node: '>=8'} @@ -13816,6 +14321,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /time-zone@1.0.0: + resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} + engines: {node: '>=4'} + dev: true + /timsort@0.3.0: resolution: {integrity: sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==} dev: true @@ -14140,6 +14650,11 @@ packages: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} + /type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + dev: true + /type-fest@0.18.1: resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} engines: {node: '>=10'} @@ -14186,7 +14701,7 @@ packages: /typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - /typeorm@0.3.11(ioredis@5.2.4)(pg@8.8.0)(ts-node@10.9.1): + /typeorm@0.3.11(ioredis@5.3.2)(pg@8.8.0)(ts-node@10.9.1): resolution: {integrity: sha512-pzdOyWbVuz/z8Ww6gqvBW4nylsM0KLdUCDExr2gR20/x1khGSVxQkjNV/3YqliG90jrWzrknYbYscpk8yxFJVg==} engines: {node: '>= 12.9.0'} hasBin: true @@ -14249,11 +14764,11 @@ packages: buffer: 6.0.3 chalk: 4.1.2 cli-highlight: 2.1.11 - date-fns: 2.29.3 + date-fns: 2.30.0 debug: 4.3.4(supports-color@8.1.1) dotenv: 16.0.3 glob: 7.2.3 - ioredis: 5.2.4 + ioredis: 5.3.2 js-yaml: 4.1.0 mkdirp: 1.0.4 pg: 8.8.0 @@ -14548,7 +15063,7 @@ packages: dependencies: fs-mkdirp-stream: 1.0.0 glob-stream: 6.1.0 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 is-valid-glob: 1.0.0 lazystream: 1.0.1 lead: 1.0.0 @@ -14571,7 +15086,7 @@ packages: dependencies: append-buffer: 1.0.2 convert-source-map: 1.9.0 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 normalize-path: 2.1.1 now-and-later: 2.0.1 remove-bom-buffer: 3.0.0 @@ -14596,7 +15111,7 @@ packages: replace-ext: 1.0.1 dev: true - /vite-plugin-compression@0.5.1(vite@4.1.1): + /vite-plugin-compression@0.5.1(vite@4.3.9): resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==} peerDependencies: vite: '>=2.0.0' @@ -14604,13 +15119,13 @@ packages: chalk: 4.1.2 debug: 4.3.4(supports-color@8.1.1) fs-extra: 10.1.0 - vite: 4.1.1(sass@1.57.1) + vite: 4.3.9(sass@1.57.1) transitivePeerDependencies: - supports-color dev: true - /vite@4.1.1(sass@1.57.1): - resolution: {integrity: sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==} + /vite@4.3.9(sass@1.57.1): + resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: @@ -14634,10 +15149,9 @@ packages: terser: optional: true dependencies: - esbuild: 0.16.17 - postcss: 8.4.21 - resolve: 1.22.1 - rollup: 3.12.1 + esbuild: 0.17.19 + postcss: 8.4.24 + rollup: 3.23.0 sass: 1.57.1 optionalDependencies: fsevents: 2.3.2 @@ -14885,6 +15399,11 @@ packages: - supports-color dev: false + /well-known-symbols@2.0.0: + resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==} + engines: {node: '>=6'} + dev: true + /whatwg-encoding@1.0.5: resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} dependencies: @@ -15031,6 +15550,14 @@ packages: typedarray-to-buffer: 3.1.5 dev: true + /write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.0.2 + dev: true + /ws@7.5.9: resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} engines: {node: '>=8.3.0'} @@ -15229,7 +15756,6 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: false /yargs@7.1.2: resolution: {integrity: sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==} @@ -15269,6 +15795,11 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true + /z-schema@5.0.5: resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} engines: {node: '>=8.0.0'} @@ -15309,7 +15840,7 @@ packages: name: plyr version: 3.7.0 dependencies: - core-js: 3.30.1 + core-js: 3.30.2 custom-event-polyfill: 1.0.7 loadjs: 4.2.0 rangetouch: 2.0.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a2ebb0465..2bf4474f0 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,6 @@ packages: - 'packages/backend' + - 'packages/backend/native-utils' - 'packages/client' - 'packages/sw' - 'packages/calckey-js' diff --git a/pull_request_template.yml b/pull_request_template.yml new file mode 100644 index 000000000..41d04f59f --- /dev/null +++ b/pull_request_template.yml @@ -0,0 +1,28 @@ +name: Pull Request +about: Create a pull request +title: "[PR]: " +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to make Calckey better! + - type: textarea + id: about + attributes: + label: What does this PR do? + description: Please give us a brief description of what this PR does. + placeholder: Makes Calckey so amazing by... + validations: + required: true + - type: checkboxes + id: terms + attributes: + label: Contribution Guidelines + description: By submitting this issue, you agree to follow our [Contribution Guidelines](https://codeberg.org/calckey/calckey/src/branch/develop/CONTRIBUTING.md) + options: + - label: I agree to follow this project's Contribution Guidelines + required: true + - label: I have made sure to test this pull request + required: true + - label: I have made sure to run `pnpm run format` before submitting this pull request + required: true diff --git a/rome.json b/rome.json index 6b74808ed..7a51b60e6 100644 --- a/rome.json +++ b/rome.json @@ -5,5 +5,18 @@ "rules": { "recommended": true } - } -} \ No newline at end of file + }, + "formatter": { + "ignore": [ + "packages/calckey-js/api-extractor.json", + "packages/*/tsconfig.json", + "packages/*/package-lock.json", + "packages/backend/src/server/web/manifest.ts", + "packages/backend/built/", + "packages/backend/nsfw-model/", + "packages/client/src/emojilist.json", + "*.md", + "*/.yml" + ] + } +}