From 145bb045e97cf93cfb6828e31675ebd9bb760d90 Mon Sep 17 00:00:00 2001
From: thehrz
Date: Fri, 24 Jan 2025 16:57:58 +0800
Subject: [PATCH] fork from xmdhs/authlib-skin
---
.gitea/workflows/ci.yml | 25 +
.gitignore | 8 +
.vscode/settings.json | 5 +
Dockerfile | 26 +
LICENSE | 21 +
README.md | 16 +
config/config.go | 100 +
db/cache/cache.go | 40 +
db/cache/cache_test.go | 38 +
db/cache/fastcache.go | 55 +
db/cache/no_redis.go | 7 +
db/cache/redis.go | 53 +
db/ent/client.go | 1021 ++++++
db/ent/ent.go | 616 ++++
db/ent/enttest/enttest.go | 84 +
db/ent/for_update.tmpl | 40 +
db/ent/generate.go | 3 +
db/ent/hook/hook.go | 247 ++
db/ent/migrate/migrate.go | 64 +
db/ent/migrate/schema.go | 192 +
db/ent/mutation.go | 3105 ++++++++++++++++
db/ent/predicate/predicate.go | 22 +
db/ent/runtime.go | 9 +
db/ent/runtime/runtime.go | 9 +
db/ent/schema/texture.go | 37 +
db/ent/schema/user.go | 52 +
db/ent/schema/userprofile.go | 42 +
db/ent/schema/usertexture.go | 51 +
db/ent/schema/usertoken.go | 34 +
db/ent/texture.go | 176 +
db/ent/texture/texture.go | 146 +
db/ent/texture/where.go | 225 ++
db/ent/texture_create.go | 275 ++
db/ent/texture_delete.go | 88 +
db/ent/texture_query.go | 850 +++++
db/ent/texture_update.go | 634 ++++
db/ent/tx.go | 222 ++
db/ent/user.go | 226 ++
db/ent/user/user.go | 164 +
db/ent/user/where.go | 525 +++
db/ent/user_create.go | 348 ++
db/ent/user_delete.go | 88 +
db/ent/user_query.go | 805 +++++
db/ent/user_update.go | 704 ++++
db/ent/userprofile.go | 187 +
db/ent/userprofile/userprofile.go | 154 +
db/ent/userprofile/where.go | 295 ++
db/ent/userprofile_create.go | 288 ++
db/ent/userprofile_delete.go | 88 +
db/ent/userprofile_query.go | 850 +++++
db/ent/userprofile_update.go | 652 ++++
db/ent/usertexture.go | 188 +
db/ent/usertexture/usertexture.go | 118 +
db/ent/usertexture/where.go | 322 ++
db/ent/usertexture_create.go | 262 ++
db/ent/usertexture_delete.go | 88 +
db/ent/usertexture_query.go | 737 ++++
db/ent/usertexture_update.go | 425 +++
db/ent/usertoken.go | 142 +
db/ent/usertoken/usertoken.go | 82 +
db/ent/usertoken/where.go | 154 +
db/ent/usertoken_create.go | 216 ++
db/ent/usertoken_delete.go | 88 +
db/ent/usertoken_query.go | 670 ++++
db/ent/usertoken_update.go | 322 ++
docker-compose.yml | 23 +
frontend/.env | 1 +
frontend/.env.development | 1 +
frontend/.eslintrc.cjs | 18 +
frontend/.gitignore | 24 +
frontend/README.md | 27 +
frontend/index.html | 13 +
frontend/package.json | 39 +
frontend/pnpm-lock.yaml | 3195 +++++++++++++++++
frontend/public/vite.svg | 1 +
frontend/src/App.tsx | 13 +
frontend/src/Route.tsx | 58 +
frontend/src/apis/apis.ts | 156 +
frontend/src/apis/error.ts | 8 +
frontend/src/apis/model.ts | 66 +
frontend/src/apis/utils.ts | 10 +
frontend/src/components/CaptchaWidget.tsx | 65 +
frontend/src/components/CheckInput.tsx | 65 +
frontend/src/components/Loading.tsx | 15 +
frontend/src/components/NeedLogin.tsx | 41 +
frontend/src/components/SkinViewUUID.tsx | 89 +
frontend/src/components/Skinview3d.tsx | 101 +
frontend/src/hooks/useTitle.ts | 16 +
frontend/src/main.tsx | 11 +
frontend/src/store/store.ts | 10 +
frontend/src/utils/email.ts | 3 +
frontend/src/utils/root.ts | 6 +
frontend/src/utils/skin.ts | 17 +
frontend/src/views/Forgot.tsx | 120 +
frontend/src/views/Index.tsx | 9 +
frontend/src/views/Layout.tsx | 291 ++
frontend/src/views/Login.tsx | 169 +
frontend/src/views/Register.tsx | 225 ++
frontend/src/views/SendEmail.tsx | 181 +
frontend/src/views/admin/UserAdmin.tsx | 237 ++
frontend/src/views/profile/Profile.tsx | 70 +
frontend/src/views/profile/Security.tsx | 202 ++
frontend/src/views/profile/Textures.tsx | 133 +
frontend/src/vite-env.d.ts | 1 +
frontend/tsconfig.json | 39 +
frontend/tsconfig.node.json | 10 +
frontend/vite.config.ts | 17 +
go.mod | 49 +
go.sum | 136 +
handle/admin.go | 137 +
handle/config.go | 31 +
handle/handelerror/error.go | 67 +
handle/handle.go | 29 +
handle/user.go | 338 ++
handle/yggdrasil/error.go | 23 +
handle/yggdrasil/session.go | 54 +
handle/yggdrasil/texture.go | 77 +
handle/yggdrasil/user.go | 172 +
handle/yggdrasil/yggdrasil.go | 146 +
main.go | 51 +
model/const.go | 19 +
model/model.go | 102 +
model/yggdrasil/model.go | 103 +
model/yggdrasil/textures.go | 28 +
server/provide.go | 114 +
server/route/middleware.go | 82 +
server/route/route.go | 109 +
server/server.go | 19 +
server/slog.go | 27 +
server/sqlite_init.go | 5 +
server/static/static.go | 36 +
server/wire.go | 32 +
server/wire_gen.go | 90 +
service/admin.go | 201 ++
service/admin_test.go | 65 +
service/auth/auth.go | 141 +
service/auth/utils.go | 52 +
service/captcha/captcha.go | 85 +
service/email/email.go | 191 +
service/service.go | 5 +
service/texture.go | 112 +
service/user.go | 288 ++
service/user_test.go | 164 +
service/utils/texture.go | 68 +
service/web.go | 43 +
service/yggdrasil/session.go | 57 +
service/yggdrasil/texture.go | 36 +
service/yggdrasil/user.go | 318 ++
service/yggdrasil/user_test.go | 62 +
service/yggdrasil/yggdrasil.go | 111 +
.../yggdrasil/yggdrasil_session_pubkey.der | Bin 0 -> 550 bytes
test/auth_test.go | 35 +
test/config.toml | 107 +
test/server_test.go | 26 +
utils/argon2id.go | 32 +
utils/decode.go | 25 +
utils/ip.go | 19 +
utils/sign/rsa.go | 90 +
utils/sign/rsa_test.go | 105 +
utils/tx.go | 31 +
utils/uuid.go | 16 +
utils/uuid_test.go | 11 +
162 files changed, 28194 insertions(+)
create mode 100644 .gitea/workflows/ci.yml
create mode 100644 .gitignore
create mode 100644 .vscode/settings.json
create mode 100644 Dockerfile
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 config/config.go
create mode 100644 db/cache/cache.go
create mode 100644 db/cache/cache_test.go
create mode 100644 db/cache/fastcache.go
create mode 100644 db/cache/no_redis.go
create mode 100644 db/cache/redis.go
create mode 100644 db/ent/client.go
create mode 100644 db/ent/ent.go
create mode 100644 db/ent/enttest/enttest.go
create mode 100644 db/ent/for_update.tmpl
create mode 100644 db/ent/generate.go
create mode 100644 db/ent/hook/hook.go
create mode 100644 db/ent/migrate/migrate.go
create mode 100644 db/ent/migrate/schema.go
create mode 100644 db/ent/mutation.go
create mode 100644 db/ent/predicate/predicate.go
create mode 100644 db/ent/runtime.go
create mode 100644 db/ent/runtime/runtime.go
create mode 100644 db/ent/schema/texture.go
create mode 100644 db/ent/schema/user.go
create mode 100644 db/ent/schema/userprofile.go
create mode 100644 db/ent/schema/usertexture.go
create mode 100644 db/ent/schema/usertoken.go
create mode 100644 db/ent/texture.go
create mode 100644 db/ent/texture/texture.go
create mode 100644 db/ent/texture/where.go
create mode 100644 db/ent/texture_create.go
create mode 100644 db/ent/texture_delete.go
create mode 100644 db/ent/texture_query.go
create mode 100644 db/ent/texture_update.go
create mode 100644 db/ent/tx.go
create mode 100644 db/ent/user.go
create mode 100644 db/ent/user/user.go
create mode 100644 db/ent/user/where.go
create mode 100644 db/ent/user_create.go
create mode 100644 db/ent/user_delete.go
create mode 100644 db/ent/user_query.go
create mode 100644 db/ent/user_update.go
create mode 100644 db/ent/userprofile.go
create mode 100644 db/ent/userprofile/userprofile.go
create mode 100644 db/ent/userprofile/where.go
create mode 100644 db/ent/userprofile_create.go
create mode 100644 db/ent/userprofile_delete.go
create mode 100644 db/ent/userprofile_query.go
create mode 100644 db/ent/userprofile_update.go
create mode 100644 db/ent/usertexture.go
create mode 100644 db/ent/usertexture/usertexture.go
create mode 100644 db/ent/usertexture/where.go
create mode 100644 db/ent/usertexture_create.go
create mode 100644 db/ent/usertexture_delete.go
create mode 100644 db/ent/usertexture_query.go
create mode 100644 db/ent/usertexture_update.go
create mode 100644 db/ent/usertoken.go
create mode 100644 db/ent/usertoken/usertoken.go
create mode 100644 db/ent/usertoken/where.go
create mode 100644 db/ent/usertoken_create.go
create mode 100644 db/ent/usertoken_delete.go
create mode 100644 db/ent/usertoken_query.go
create mode 100644 db/ent/usertoken_update.go
create mode 100644 docker-compose.yml
create mode 100644 frontend/.env
create mode 100644 frontend/.env.development
create mode 100644 frontend/.eslintrc.cjs
create mode 100644 frontend/.gitignore
create mode 100644 frontend/README.md
create mode 100644 frontend/index.html
create mode 100644 frontend/package.json
create mode 100644 frontend/pnpm-lock.yaml
create mode 100644 frontend/public/vite.svg
create mode 100644 frontend/src/App.tsx
create mode 100644 frontend/src/Route.tsx
create mode 100644 frontend/src/apis/apis.ts
create mode 100644 frontend/src/apis/error.ts
create mode 100644 frontend/src/apis/model.ts
create mode 100644 frontend/src/apis/utils.ts
create mode 100644 frontend/src/components/CaptchaWidget.tsx
create mode 100644 frontend/src/components/CheckInput.tsx
create mode 100644 frontend/src/components/Loading.tsx
create mode 100644 frontend/src/components/NeedLogin.tsx
create mode 100644 frontend/src/components/SkinViewUUID.tsx
create mode 100644 frontend/src/components/Skinview3d.tsx
create mode 100644 frontend/src/hooks/useTitle.ts
create mode 100644 frontend/src/main.tsx
create mode 100644 frontend/src/store/store.ts
create mode 100644 frontend/src/utils/email.ts
create mode 100644 frontend/src/utils/root.ts
create mode 100644 frontend/src/utils/skin.ts
create mode 100644 frontend/src/views/Forgot.tsx
create mode 100644 frontend/src/views/Index.tsx
create mode 100644 frontend/src/views/Layout.tsx
create mode 100644 frontend/src/views/Login.tsx
create mode 100644 frontend/src/views/Register.tsx
create mode 100644 frontend/src/views/SendEmail.tsx
create mode 100644 frontend/src/views/admin/UserAdmin.tsx
create mode 100644 frontend/src/views/profile/Profile.tsx
create mode 100644 frontend/src/views/profile/Security.tsx
create mode 100644 frontend/src/views/profile/Textures.tsx
create mode 100644 frontend/src/vite-env.d.ts
create mode 100644 frontend/tsconfig.json
create mode 100644 frontend/tsconfig.node.json
create mode 100644 frontend/vite.config.ts
create mode 100644 go.mod
create mode 100644 go.sum
create mode 100644 handle/admin.go
create mode 100644 handle/config.go
create mode 100644 handle/handelerror/error.go
create mode 100644 handle/handle.go
create mode 100644 handle/user.go
create mode 100644 handle/yggdrasil/error.go
create mode 100644 handle/yggdrasil/session.go
create mode 100644 handle/yggdrasil/texture.go
create mode 100644 handle/yggdrasil/user.go
create mode 100644 handle/yggdrasil/yggdrasil.go
create mode 100644 main.go
create mode 100644 model/const.go
create mode 100644 model/model.go
create mode 100644 model/yggdrasil/model.go
create mode 100644 model/yggdrasil/textures.go
create mode 100644 server/provide.go
create mode 100644 server/route/middleware.go
create mode 100644 server/route/route.go
create mode 100644 server/server.go
create mode 100644 server/slog.go
create mode 100644 server/sqlite_init.go
create mode 100644 server/static/static.go
create mode 100644 server/wire.go
create mode 100644 server/wire_gen.go
create mode 100644 service/admin.go
create mode 100644 service/admin_test.go
create mode 100644 service/auth/auth.go
create mode 100644 service/auth/utils.go
create mode 100644 service/captcha/captcha.go
create mode 100644 service/email/email.go
create mode 100644 service/service.go
create mode 100644 service/texture.go
create mode 100644 service/user.go
create mode 100644 service/user_test.go
create mode 100644 service/utils/texture.go
create mode 100644 service/web.go
create mode 100644 service/yggdrasil/session.go
create mode 100644 service/yggdrasil/texture.go
create mode 100644 service/yggdrasil/user.go
create mode 100644 service/yggdrasil/user_test.go
create mode 100644 service/yggdrasil/yggdrasil.go
create mode 100644 service/yggdrasil/yggdrasil_session_pubkey.der
create mode 100644 test/auth_test.go
create mode 100644 test/config.toml
create mode 100644 test/server_test.go
create mode 100644 utils/argon2id.go
create mode 100644 utils/decode.go
create mode 100644 utils/ip.go
create mode 100644 utils/sign/rsa.go
create mode 100644 utils/sign/rsa_test.go
create mode 100644 utils/tx.go
create mode 100644 utils/uuid.go
create mode 100644 utils/uuid_test.go
diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml
new file mode 100644
index 0000000..5539551
--- /dev/null
+++ b/.gitea/workflows/ci.yml
@@ -0,0 +1,25 @@
+name: CI
+
+on:
+ push:
+ branches:
+ - master
+
+ pull_request:
+ branches:
+ - master
+
+jobs:
+ deploy:
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ submodules: true
+
+ # - name: Install Docker
+ # run: curl -fsSL https://get.docker.com | sh
+
+ - name: Deploy with Docker
+ run: docker compose up --build --force-recreate -d
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3bf30a3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+cmd/testserver
+cmd/authlibskin/config.yaml
+cmd/authlibskin/skin
+cmd/authlibskin/authlibskin.exe
+server/static/files
+cmd/authlibskin/config.toml
+out/
+stats.html
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..e86f901
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+ "gopls": {
+ "buildFlags":["-tags=wireinject,redis,sqlite"]
+ },
+}
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..0811f36
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,26 @@
+FROM node:20-alpine AS frontend-stage
+
+WORKDIR /app
+RUN corepack enable
+
+COPY frontend/package.json frontend/pnpm-lock.yaml ./
+RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store \
+ pnpm install --frozen-lockfile
+
+COPY frontend .
+
+RUN pnpm build
+
+FROM golang:1.23 AS build-stage
+
+WORKDIR /app
+ENV GOPROXY https://goproxy.cn,direct
+
+COPY --from=frontend-stage /app/dist ./server/static/files
+COPY . .
+
+RUN go build -o app .
+
+VOLUME /app/config
+
+ENTRYPOINT ["/app/app", "-c", "./config/config.toml"]
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..9efc233
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 xmdhs
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ff39aae
--- /dev/null
+++ b/README.md
@@ -0,0 +1,16 @@
+# TinySkin
+
+Fork from [authlib-skin](https://github.com/xmdhs/authlib-skin).
+
+轻量级的 Yggdrasil 服务端实现,后端 Go,前端 react。
+
+适合于只需要用于 [authlib-injector](https://github.com/yushijinhun/authlib-injector) 的验证服务器的情况,部署简单。
+
+实现了 [Yggdrasil](https://github.com/yushijinhun/authlib-injector/wiki/Yggdrasil-%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%8A%80%E6%9C%AF%E8%A7%84%E8%8C%83) 规范,可用于一些启动器中的外置登录,和服务器的外置登录。
+
+## 特性
+
+- 支持用于聊天签名的 /player/certificates 接口
+- 支持于离线模式相同的方式生成用户 uuid(开启后不可更改用户名)
+- 基本的用户管理
+- Cloudflare Turnstile 支持
diff --git a/config/config.go b/config/config.go
new file mode 100644
index 0000000..f8cf9a7
--- /dev/null
+++ b/config/config.go
@@ -0,0 +1,100 @@
+package config
+
+type Config struct {
+ OfflineUUID bool `toml:"offlineUUID" comment:"为 true 则 uuid 生成方式于离线模式相同,若从离线模式切换不会丢失数据。\n已有用户数据的情况下勿更改此项"`
+ Port string `toml:"port"`
+ Log Log `toml:"log"`
+ Sql Sql `toml:"sql"`
+ Debug bool `toml:"debug" comment:"输出每条执行的 sql 语句"`
+ Cache Cache `toml:"cache"`
+ RaelIP bool `toml:"raelIP" comment:"位于反向代理后启用,用于记录真实 ip\n若直接提供服务,请勿打开,否则会被伪造 ip"`
+ MaxIpUser int `toml:"maxIpUser" comment:"ip 段最大注册用户,ipv4 为 /24 ipv6 为 /48"`
+ RsaPriKey string `toml:"rsaPriKey,multiline" comment:"运行后勿修改,若为集群需设置为一致"`
+ TexturePath string `toml:"texturePath" comment:"材质文件保存路径,如果需要对象存储可以把对象储存挂载到本地目录上"`
+ TextureBaseUrl string `toml:"textureBaseUrl" comment:"材质静态文件提供基础地址\n如果静态文件位于 oss 上,比如 https://s3.amazonaws.com/example/1.png\n则填写 https://s3.amazonaws.com/example \n若通过反向代理提供服务并启用了 https,请在在此处填写带有 https 的基础路径,否则游戏内无法加载皮肤"`
+ WebBaseUrl string `toml:"webBaseUrl" comment:"用于在支持的启动器中展示本站的注册地址\n填写类似 https://example.com"`
+ ServerName string `toml:"serverName" comment:"皮肤站名字,用于在多个地方展示"`
+ Captcha Captcha `toml:"captcha"`
+ Email EmailConfig `toml:"email"`
+}
+
+type Log struct {
+ Level string `toml:"level"`
+ Json bool `toml:"json" comment:"json 格式输出"`
+}
+
+type Sql struct {
+ DriverName string `toml:"driverName" comment:"可填 mysql 或 sqlite3"`
+ Dsn string `toml:"dsn" comment:"填写见 mysql https://github.com/go-sql-driver/mysql#dsn-data-source-name\nsqlite https://github.com/mattn/go-sqlite3\n例如 mysql 用户名:密码@tcp(mysqlIP:端口)/数据库名\nsqlite data.db?_txlock=IMMEDIATE&_journal_mode=WAL&_fk=true"`
+}
+
+type Cache struct {
+ Type string `toml:"type" comment:"默认使用内存缓存,若需要集群部署,填写 redis"`
+ Ram int `toml:"ram" comment:"内存缓存使用大小,单位 b"`
+ Addr string `toml:"addr" comment:"redis 服务端地址,如 127.0.0.1:6379"`
+ Password string `toml:"password" comment:"redis 密码"`
+}
+
+type Captcha struct {
+ Type string `toml:"type" comment:"验证码类型,目前只支持 cloudflare turnstile,若需要填写 turnstile"`
+ SiteKey string `toml:"siteKey"`
+ Secret string `toml:"secret"`
+}
+
+type EmailConfig struct {
+ Enable bool `toml:"enable" comment:"注册验证邮件,且允许使用邮箱找回账号"`
+ Smtp []SmtpUser `toml:"smtp"`
+ AllowDomain []string `toml:"allow_domain" comment:"允许用于注册的邮箱域名,留空则允许全部"`
+ EmailReg string `toml:"email_reg" comment:"邮箱正则,留空则不处理,如 ^[0-9]+@qq.com$|^[^+\\.A-Z]+@gmail.com$"`
+ EmailRegMsg string `toml:"email_reg_msg" comment:"不满足要求时的提示信息"`
+}
+
+type SmtpUser struct {
+ Host string `toml:"host"`
+ Port int `toml:"port"`
+ SSL bool `toml:"SSL" comment:"启用 ssl"`
+ Name string `toml:"name"`
+ Pass string `toml:"password"`
+}
+
+func Default() Config {
+ return Config{
+ OfflineUUID: true,
+ Port: ":8080",
+ Log: Log{
+ Level: "debug",
+ Json: false,
+ },
+ Sql: Sql{
+ DriverName: "sqlite3",
+ Dsn: "data.db?_txlock=IMMEDIATE&_journal_mode=WAL&_fk=true",
+ },
+ Debug: false,
+ Cache: Cache{
+ Type: "",
+ Ram: 10000000,
+ Addr: "",
+ Password: "",
+ },
+ RaelIP: false,
+ MaxIpUser: 0,
+ RsaPriKey: "",
+ TexturePath: "",
+ TextureBaseUrl: "",
+ WebBaseUrl: "",
+ ServerName: "没有设置名字",
+ Captcha: Captcha{},
+ Email: EmailConfig{
+ Smtp: []SmtpUser{
+ {
+ Host: "",
+ Port: 0,
+ SSL: false,
+ Name: "",
+ Pass: "",
+ },
+ },
+ AllowDomain: []string{},
+ },
+ }
+}
diff --git a/db/cache/cache.go b/db/cache/cache.go
new file mode 100644
index 0000000..e952760
--- /dev/null
+++ b/db/cache/cache.go
@@ -0,0 +1,40 @@
+package cache
+
+import (
+ "encoding/json"
+ "time"
+)
+
+type Cache interface {
+ Del(k []byte) error
+ Get(k []byte) ([]byte, error)
+ Put(k []byte, v []byte, timeOut time.Time) error
+}
+
+type CacheHelp[T any] struct {
+ Cache
+}
+
+func (c CacheHelp[T]) Get(k []byte) (T, error) {
+ var t T
+ b, err := c.Cache.Get(k)
+ if err != nil {
+ return t, err
+ }
+ if b == nil {
+ return t, nil
+ }
+ err = json.Unmarshal(b, &t)
+ if err != nil {
+ return t, err
+ }
+ return t, nil
+}
+
+func (c CacheHelp[T]) Put(k []byte, v T, timeOut time.Time) error {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return err
+ }
+ return c.Cache.Put(k, b, timeOut)
+}
diff --git a/db/cache/cache_test.go b/db/cache/cache_test.go
new file mode 100644
index 0000000..d227dba
--- /dev/null
+++ b/db/cache/cache_test.go
@@ -0,0 +1,38 @@
+package cache
+
+import (
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestCache(t *testing.T) {
+ cl := []Cache{NewFastCache(100000), NewRedis("127.0.0.1:6379", "")}
+
+ for i, c := range cl {
+ key := []byte("key")
+ value := []byte("value")
+
+ require.Nil(t, c.Put(key, value, time.Now().Add(1*time.Hour)), i)
+
+ v, err := c.Get(key)
+ require.Nil(t, err, i)
+
+ assert.Equal(t, v, value, i)
+
+ require.Nil(t, c.Del(key), i)
+
+ v, err = c.Get(key)
+ require.Nil(t, err, i)
+ require.Nil(t, v, i)
+
+ require.Nil(t, c.Put(key, value, time.Now().Add(2*time.Second)), i)
+ time.Sleep(3 * time.Second)
+
+ v, err = c.Get(key)
+ require.Nil(t, err, i)
+ require.Nil(t, v, i)
+ }
+}
diff --git a/db/cache/fastcache.go b/db/cache/fastcache.go
new file mode 100644
index 0000000..b6c8fb2
--- /dev/null
+++ b/db/cache/fastcache.go
@@ -0,0 +1,55 @@
+package cache
+
+import (
+ "fmt"
+ "time"
+
+ "github.com/VictoriaMetrics/fastcache"
+ "github.com/alecthomas/binary"
+)
+
+var _ Cache = (*FastCache)(nil)
+
+type FastCache struct {
+ c *fastcache.Cache
+}
+
+type ttlCache struct {
+ TimeOut int64
+ V []byte
+}
+
+func NewFastCache(maxBytes int) *FastCache {
+ c := fastcache.New(maxBytes)
+ return &FastCache{c: c}
+}
+
+func (f *FastCache) Put(k []byte, v []byte, timeOut time.Time) error {
+ b, err := binary.Marshal(ttlCache{V: v, TimeOut: timeOut.Unix()})
+ if err != nil {
+ return fmt.Errorf("FastCache.Put: %w", err)
+ }
+ f.c.SetBig(k, b)
+ return nil
+}
+
+func (f *FastCache) Del(k []byte) error {
+ f.c.Del(k)
+ return nil
+}
+
+func (f *FastCache) Get(k []byte) ([]byte, error) {
+ b := f.c.GetBig(nil, k)
+ if b == nil {
+ return nil, nil
+ }
+ me := ttlCache{}
+ err := binary.Unmarshal(b, &me)
+ if err != nil {
+ return nil, fmt.Errorf("FastCache.Get: %w", err)
+ }
+ if time.Unix(me.TimeOut, 0).Before(time.Now()) {
+ return nil, nil
+ }
+ return me.V, nil
+}
diff --git a/db/cache/no_redis.go b/db/cache/no_redis.go
new file mode 100644
index 0000000..b2ae414
--- /dev/null
+++ b/db/cache/no_redis.go
@@ -0,0 +1,7 @@
+//go:build !redis
+
+package cache
+
+func NewRedis(addr, pass string) Cache {
+ panic("not tag redis")
+}
diff --git a/db/cache/redis.go b/db/cache/redis.go
new file mode 100644
index 0000000..de3261f
--- /dev/null
+++ b/db/cache/redis.go
@@ -0,0 +1,53 @@
+//go:build redis
+
+package cache
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "time"
+
+ "github.com/redis/go-redis/v9"
+)
+
+var _ Cache = (*RedisCache)(nil)
+
+type RedisCache struct {
+ c *redis.Client
+}
+
+func NewRedis(addr, pass string) Cache {
+ rdb := redis.NewClient(&redis.Options{
+ Addr: addr,
+ Password: pass,
+ })
+ return &RedisCache{c: rdb}
+}
+
+func (r *RedisCache) Del(k []byte) error {
+ _, err := r.c.Del(context.Background(), string(k)).Result()
+ if err != nil {
+ return fmt.Errorf("RedisCache.Del: %w", err)
+ }
+ return nil
+}
+
+func (r *RedisCache) Get(k []byte) ([]byte, error) {
+ value, err := r.c.Get(context.Background(), string(k)).Bytes()
+ if err != nil {
+ if errors.Is(err, redis.Nil) {
+ return nil, nil
+ }
+ return nil, fmt.Errorf("RedisCache.Get: %w", err)
+ }
+ return value, nil
+}
+
+func (r *RedisCache) Put(k []byte, v []byte, timeOut time.Time) error {
+ err := r.c.Set(context.Background(), string(k), v, timeOut.Sub(time.Now())).Err()
+ if err != nil {
+ return fmt.Errorf("RedisCache.Put: %w", err)
+ }
+ return nil
+}
diff --git a/db/ent/client.go b/db/ent/client.go
new file mode 100644
index 0000000..d03837c
--- /dev/null
+++ b/db/ent/client.go
@@ -0,0 +1,1021 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "log"
+
+ "github.com/xmdhs/authlib-skin/db/ent/migrate"
+
+ "entgo.io/ent"
+ "entgo.io/ent/dialect"
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+// Client is the client that holds all ent builders.
+type Client struct {
+ config
+ // Schema is the client for creating, migrating and dropping schema.
+ Schema *migrate.Schema
+ // Texture is the client for interacting with the Texture builders.
+ Texture *TextureClient
+ // User is the client for interacting with the User builders.
+ User *UserClient
+ // UserProfile is the client for interacting with the UserProfile builders.
+ UserProfile *UserProfileClient
+ // UserTexture is the client for interacting with the UserTexture builders.
+ UserTexture *UserTextureClient
+ // UserToken is the client for interacting with the UserToken builders.
+ UserToken *UserTokenClient
+}
+
+// NewClient creates a new client configured with the given options.
+func NewClient(opts ...Option) *Client {
+ cfg := config{log: log.Println, hooks: &hooks{}, inters: &inters{}}
+ cfg.options(opts...)
+ client := &Client{config: cfg}
+ client.init()
+ return client
+}
+
+func (c *Client) init() {
+ c.Schema = migrate.NewSchema(c.driver)
+ c.Texture = NewTextureClient(c.config)
+ c.User = NewUserClient(c.config)
+ c.UserProfile = NewUserProfileClient(c.config)
+ c.UserTexture = NewUserTextureClient(c.config)
+ c.UserToken = NewUserTokenClient(c.config)
+}
+
+type (
+ // config is the configuration for the client and its builder.
+ config struct {
+ // driver used for executing database requests.
+ driver dialect.Driver
+ // debug enable a debug logging.
+ debug bool
+ // log used for logging on debug mode.
+ log func(...any)
+ // hooks to execute on mutations.
+ hooks *hooks
+ // interceptors to execute on queries.
+ inters *inters
+ }
+ // Option function to configure the client.
+ Option func(*config)
+)
+
+// options applies the options on the config object.
+func (c *config) options(opts ...Option) {
+ for _, opt := range opts {
+ opt(c)
+ }
+ if c.debug {
+ c.driver = dialect.Debug(c.driver, c.log)
+ }
+}
+
+// Debug enables debug logging on the ent.Driver.
+func Debug() Option {
+ return func(c *config) {
+ c.debug = true
+ }
+}
+
+// Log sets the logging function for debug mode.
+func Log(fn func(...any)) Option {
+ return func(c *config) {
+ c.log = fn
+ }
+}
+
+// Driver configures the client driver.
+func Driver(driver dialect.Driver) Option {
+ return func(c *config) {
+ c.driver = driver
+ }
+}
+
+// Open opens a database/sql.DB specified by the driver name and
+// the data source name, and returns a new client attached to it.
+// Optional parameters can be added for configuring the client.
+func Open(driverName, dataSourceName string, options ...Option) (*Client, error) {
+ switch driverName {
+ case dialect.MySQL, dialect.Postgres, dialect.SQLite:
+ drv, err := sql.Open(driverName, dataSourceName)
+ if err != nil {
+ return nil, err
+ }
+ return NewClient(append(options, Driver(drv))...), nil
+ default:
+ return nil, fmt.Errorf("unsupported driver: %q", driverName)
+ }
+}
+
+// Tx returns a new transactional client. The provided context
+// is used until the transaction is committed or rolled back.
+func (c *Client) Tx(ctx context.Context) (*Tx, error) {
+ if _, ok := c.driver.(*txDriver); ok {
+ return nil, errors.New("ent: cannot start a transaction within a transaction")
+ }
+ tx, err := newTx(ctx, c.driver)
+ if err != nil {
+ return nil, fmt.Errorf("ent: starting a transaction: %w", err)
+ }
+ cfg := c.config
+ cfg.driver = tx
+ return &Tx{
+ ctx: ctx,
+ config: cfg,
+ Texture: NewTextureClient(cfg),
+ User: NewUserClient(cfg),
+ UserProfile: NewUserProfileClient(cfg),
+ UserTexture: NewUserTextureClient(cfg),
+ UserToken: NewUserTokenClient(cfg),
+ }, nil
+}
+
+// BeginTx returns a transactional client with specified options.
+func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
+ if _, ok := c.driver.(*txDriver); ok {
+ return nil, errors.New("ent: cannot start a transaction within a transaction")
+ }
+ tx, err := c.driver.(interface {
+ BeginTx(context.Context, *sql.TxOptions) (dialect.Tx, error)
+ }).BeginTx(ctx, opts)
+ if err != nil {
+ return nil, fmt.Errorf("ent: starting a transaction: %w", err)
+ }
+ cfg := c.config
+ cfg.driver = &txDriver{tx: tx, drv: c.driver}
+ return &Tx{
+ ctx: ctx,
+ config: cfg,
+ Texture: NewTextureClient(cfg),
+ User: NewUserClient(cfg),
+ UserProfile: NewUserProfileClient(cfg),
+ UserTexture: NewUserTextureClient(cfg),
+ UserToken: NewUserTokenClient(cfg),
+ }, nil
+}
+
+// Debug returns a new debug-client. It's used to get verbose logging on specific operations.
+//
+// client.Debug().
+// Texture.
+// Query().
+// Count(ctx)
+func (c *Client) Debug() *Client {
+ if c.debug {
+ return c
+ }
+ cfg := c.config
+ cfg.driver = dialect.Debug(c.driver, c.log)
+ client := &Client{config: cfg}
+ client.init()
+ return client
+}
+
+// Close closes the database connection and prevents new queries from starting.
+func (c *Client) Close() error {
+ return c.driver.Close()
+}
+
+// Use adds the mutation hooks to all the entity clients.
+// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
+func (c *Client) Use(hooks ...Hook) {
+ c.Texture.Use(hooks...)
+ c.User.Use(hooks...)
+ c.UserProfile.Use(hooks...)
+ c.UserTexture.Use(hooks...)
+ c.UserToken.Use(hooks...)
+}
+
+// Intercept adds the query interceptors to all the entity clients.
+// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
+func (c *Client) Intercept(interceptors ...Interceptor) {
+ c.Texture.Intercept(interceptors...)
+ c.User.Intercept(interceptors...)
+ c.UserProfile.Intercept(interceptors...)
+ c.UserTexture.Intercept(interceptors...)
+ c.UserToken.Intercept(interceptors...)
+}
+
+// Mutate implements the ent.Mutator interface.
+func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
+ switch m := m.(type) {
+ case *TextureMutation:
+ return c.Texture.mutate(ctx, m)
+ case *UserMutation:
+ return c.User.mutate(ctx, m)
+ case *UserProfileMutation:
+ return c.UserProfile.mutate(ctx, m)
+ case *UserTextureMutation:
+ return c.UserTexture.mutate(ctx, m)
+ case *UserTokenMutation:
+ return c.UserToken.mutate(ctx, m)
+ default:
+ return nil, fmt.Errorf("ent: unknown mutation type %T", m)
+ }
+}
+
+// TextureClient is a client for the Texture schema.
+type TextureClient struct {
+ config
+}
+
+// NewTextureClient returns a client for the Texture from the given config.
+func NewTextureClient(c config) *TextureClient {
+ return &TextureClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `texture.Hooks(f(g(h())))`.
+func (c *TextureClient) Use(hooks ...Hook) {
+ c.hooks.Texture = append(c.hooks.Texture, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `texture.Intercept(f(g(h())))`.
+func (c *TextureClient) Intercept(interceptors ...Interceptor) {
+ c.inters.Texture = append(c.inters.Texture, interceptors...)
+}
+
+// Create returns a builder for creating a Texture entity.
+func (c *TextureClient) Create() *TextureCreate {
+ mutation := newTextureMutation(c.config, OpCreate)
+ return &TextureCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of Texture entities.
+func (c *TextureClient) CreateBulk(builders ...*TextureCreate) *TextureCreateBulk {
+ return &TextureCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for Texture.
+func (c *TextureClient) Update() *TextureUpdate {
+ mutation := newTextureMutation(c.config, OpUpdate)
+ return &TextureUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *TextureClient) UpdateOne(t *Texture) *TextureUpdateOne {
+ mutation := newTextureMutation(c.config, OpUpdateOne, withTexture(t))
+ return &TextureUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *TextureClient) UpdateOneID(id int) *TextureUpdateOne {
+ mutation := newTextureMutation(c.config, OpUpdateOne, withTextureID(id))
+ return &TextureUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for Texture.
+func (c *TextureClient) Delete() *TextureDelete {
+ mutation := newTextureMutation(c.config, OpDelete)
+ return &TextureDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *TextureClient) DeleteOne(t *Texture) *TextureDeleteOne {
+ return c.DeleteOneID(t.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *TextureClient) DeleteOneID(id int) *TextureDeleteOne {
+ builder := c.Delete().Where(texture.ID(id))
+ builder.mutation.id = &id
+ builder.mutation.op = OpDeleteOne
+ return &TextureDeleteOne{builder}
+}
+
+// Query returns a query builder for Texture.
+func (c *TextureClient) Query() *TextureQuery {
+ return &TextureQuery{
+ config: c.config,
+ ctx: &QueryContext{Type: TypeTexture},
+ inters: c.Interceptors(),
+ }
+}
+
+// Get returns a Texture entity by its id.
+func (c *TextureClient) Get(ctx context.Context, id int) (*Texture, error) {
+ return c.Query().Where(texture.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *TextureClient) GetX(ctx context.Context, id int) *Texture {
+ obj, err := c.Get(ctx, id)
+ if err != nil {
+ panic(err)
+ }
+ return obj
+}
+
+// QueryCreatedUser queries the created_user edge of a Texture.
+func (c *TextureClient) QueryCreatedUser(t *Texture) *UserQuery {
+ query := (&UserClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := t.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(texture.Table, texture.FieldID, id),
+ sqlgraph.To(user.Table, user.FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, texture.CreatedUserTable, texture.CreatedUserColumn),
+ )
+ fromV = sqlgraph.Neighbors(t.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// QueryUserProfile queries the user_profile edge of a Texture.
+func (c *TextureClient) QueryUserProfile(t *Texture) *UserProfileQuery {
+ query := (&UserProfileClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := t.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(texture.Table, texture.FieldID, id),
+ sqlgraph.To(userprofile.Table, userprofile.FieldID),
+ sqlgraph.Edge(sqlgraph.M2M, false, texture.UserProfileTable, texture.UserProfilePrimaryKey...),
+ )
+ fromV = sqlgraph.Neighbors(t.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// QueryUsertexture queries the usertexture edge of a Texture.
+func (c *TextureClient) QueryUsertexture(t *Texture) *UserTextureQuery {
+ query := (&UserTextureClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := t.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(texture.Table, texture.FieldID, id),
+ sqlgraph.To(usertexture.Table, usertexture.FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, texture.UsertextureTable, texture.UsertextureColumn),
+ )
+ fromV = sqlgraph.Neighbors(t.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// Hooks returns the client hooks.
+func (c *TextureClient) Hooks() []Hook {
+ return c.hooks.Texture
+}
+
+// Interceptors returns the client interceptors.
+func (c *TextureClient) Interceptors() []Interceptor {
+ return c.inters.Texture
+}
+
+func (c *TextureClient) mutate(ctx context.Context, m *TextureMutation) (Value, error) {
+ switch m.Op() {
+ case OpCreate:
+ return (&TextureCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpUpdate:
+ return (&TextureUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpUpdateOne:
+ return (&TextureUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpDelete, OpDeleteOne:
+ return (&TextureDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+ default:
+ return nil, fmt.Errorf("ent: unknown Texture mutation op: %q", m.Op())
+ }
+}
+
+// UserClient is a client for the User schema.
+type UserClient struct {
+ config
+}
+
+// NewUserClient returns a client for the User from the given config.
+func NewUserClient(c config) *UserClient {
+ return &UserClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `user.Hooks(f(g(h())))`.
+func (c *UserClient) Use(hooks ...Hook) {
+ c.hooks.User = append(c.hooks.User, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `user.Intercept(f(g(h())))`.
+func (c *UserClient) Intercept(interceptors ...Interceptor) {
+ c.inters.User = append(c.inters.User, interceptors...)
+}
+
+// Create returns a builder for creating a User entity.
+func (c *UserClient) Create() *UserCreate {
+ mutation := newUserMutation(c.config, OpCreate)
+ return &UserCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of User entities.
+func (c *UserClient) CreateBulk(builders ...*UserCreate) *UserCreateBulk {
+ return &UserCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for User.
+func (c *UserClient) Update() *UserUpdate {
+ mutation := newUserMutation(c.config, OpUpdate)
+ return &UserUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *UserClient) UpdateOne(u *User) *UserUpdateOne {
+ mutation := newUserMutation(c.config, OpUpdateOne, withUser(u))
+ return &UserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *UserClient) UpdateOneID(id int) *UserUpdateOne {
+ mutation := newUserMutation(c.config, OpUpdateOne, withUserID(id))
+ return &UserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for User.
+func (c *UserClient) Delete() *UserDelete {
+ mutation := newUserMutation(c.config, OpDelete)
+ return &UserDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *UserClient) DeleteOne(u *User) *UserDeleteOne {
+ return c.DeleteOneID(u.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *UserClient) DeleteOneID(id int) *UserDeleteOne {
+ builder := c.Delete().Where(user.ID(id))
+ builder.mutation.id = &id
+ builder.mutation.op = OpDeleteOne
+ return &UserDeleteOne{builder}
+}
+
+// Query returns a query builder for User.
+func (c *UserClient) Query() *UserQuery {
+ return &UserQuery{
+ config: c.config,
+ ctx: &QueryContext{Type: TypeUser},
+ inters: c.Interceptors(),
+ }
+}
+
+// Get returns a User entity by its id.
+func (c *UserClient) Get(ctx context.Context, id int) (*User, error) {
+ return c.Query().Where(user.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *UserClient) GetX(ctx context.Context, id int) *User {
+ obj, err := c.Get(ctx, id)
+ if err != nil {
+ panic(err)
+ }
+ return obj
+}
+
+// QueryCreatedTexture queries the created_texture edge of a User.
+func (c *UserClient) QueryCreatedTexture(u *User) *TextureQuery {
+ query := (&TextureClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := u.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(user.Table, user.FieldID, id),
+ sqlgraph.To(texture.Table, texture.FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, user.CreatedTextureTable, user.CreatedTextureColumn),
+ )
+ fromV = sqlgraph.Neighbors(u.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// QueryProfile queries the profile edge of a User.
+func (c *UserClient) QueryProfile(u *User) *UserProfileQuery {
+ query := (&UserProfileClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := u.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(user.Table, user.FieldID, id),
+ sqlgraph.To(userprofile.Table, userprofile.FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, false, user.ProfileTable, user.ProfileColumn),
+ )
+ fromV = sqlgraph.Neighbors(u.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// QueryToken queries the token edge of a User.
+func (c *UserClient) QueryToken(u *User) *UserTokenQuery {
+ query := (&UserTokenClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := u.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(user.Table, user.FieldID, id),
+ sqlgraph.To(usertoken.Table, usertoken.FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, false, user.TokenTable, user.TokenColumn),
+ )
+ fromV = sqlgraph.Neighbors(u.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// Hooks returns the client hooks.
+func (c *UserClient) Hooks() []Hook {
+ return c.hooks.User
+}
+
+// Interceptors returns the client interceptors.
+func (c *UserClient) Interceptors() []Interceptor {
+ return c.inters.User
+}
+
+func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error) {
+ switch m.Op() {
+ case OpCreate:
+ return (&UserCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpUpdate:
+ return (&UserUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpUpdateOne:
+ return (&UserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpDelete, OpDeleteOne:
+ return (&UserDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+ default:
+ return nil, fmt.Errorf("ent: unknown User mutation op: %q", m.Op())
+ }
+}
+
+// UserProfileClient is a client for the UserProfile schema.
+type UserProfileClient struct {
+ config
+}
+
+// NewUserProfileClient returns a client for the UserProfile from the given config.
+func NewUserProfileClient(c config) *UserProfileClient {
+ return &UserProfileClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `userprofile.Hooks(f(g(h())))`.
+func (c *UserProfileClient) Use(hooks ...Hook) {
+ c.hooks.UserProfile = append(c.hooks.UserProfile, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `userprofile.Intercept(f(g(h())))`.
+func (c *UserProfileClient) Intercept(interceptors ...Interceptor) {
+ c.inters.UserProfile = append(c.inters.UserProfile, interceptors...)
+}
+
+// Create returns a builder for creating a UserProfile entity.
+func (c *UserProfileClient) Create() *UserProfileCreate {
+ mutation := newUserProfileMutation(c.config, OpCreate)
+ return &UserProfileCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of UserProfile entities.
+func (c *UserProfileClient) CreateBulk(builders ...*UserProfileCreate) *UserProfileCreateBulk {
+ return &UserProfileCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for UserProfile.
+func (c *UserProfileClient) Update() *UserProfileUpdate {
+ mutation := newUserProfileMutation(c.config, OpUpdate)
+ return &UserProfileUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *UserProfileClient) UpdateOne(up *UserProfile) *UserProfileUpdateOne {
+ mutation := newUserProfileMutation(c.config, OpUpdateOne, withUserProfile(up))
+ return &UserProfileUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *UserProfileClient) UpdateOneID(id int) *UserProfileUpdateOne {
+ mutation := newUserProfileMutation(c.config, OpUpdateOne, withUserProfileID(id))
+ return &UserProfileUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for UserProfile.
+func (c *UserProfileClient) Delete() *UserProfileDelete {
+ mutation := newUserProfileMutation(c.config, OpDelete)
+ return &UserProfileDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *UserProfileClient) DeleteOne(up *UserProfile) *UserProfileDeleteOne {
+ return c.DeleteOneID(up.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *UserProfileClient) DeleteOneID(id int) *UserProfileDeleteOne {
+ builder := c.Delete().Where(userprofile.ID(id))
+ builder.mutation.id = &id
+ builder.mutation.op = OpDeleteOne
+ return &UserProfileDeleteOne{builder}
+}
+
+// Query returns a query builder for UserProfile.
+func (c *UserProfileClient) Query() *UserProfileQuery {
+ return &UserProfileQuery{
+ config: c.config,
+ ctx: &QueryContext{Type: TypeUserProfile},
+ inters: c.Interceptors(),
+ }
+}
+
+// Get returns a UserProfile entity by its id.
+func (c *UserProfileClient) Get(ctx context.Context, id int) (*UserProfile, error) {
+ return c.Query().Where(userprofile.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *UserProfileClient) GetX(ctx context.Context, id int) *UserProfile {
+ obj, err := c.Get(ctx, id)
+ if err != nil {
+ panic(err)
+ }
+ return obj
+}
+
+// QueryUser queries the user edge of a UserProfile.
+func (c *UserProfileClient) QueryUser(up *UserProfile) *UserQuery {
+ query := (&UserClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := up.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(userprofile.Table, userprofile.FieldID, id),
+ sqlgraph.To(user.Table, user.FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, true, userprofile.UserTable, userprofile.UserColumn),
+ )
+ fromV = sqlgraph.Neighbors(up.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// QueryTexture queries the texture edge of a UserProfile.
+func (c *UserProfileClient) QueryTexture(up *UserProfile) *TextureQuery {
+ query := (&TextureClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := up.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(userprofile.Table, userprofile.FieldID, id),
+ sqlgraph.To(texture.Table, texture.FieldID),
+ sqlgraph.Edge(sqlgraph.M2M, true, userprofile.TextureTable, userprofile.TexturePrimaryKey...),
+ )
+ fromV = sqlgraph.Neighbors(up.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// QueryUsertexture queries the usertexture edge of a UserProfile.
+func (c *UserProfileClient) QueryUsertexture(up *UserProfile) *UserTextureQuery {
+ query := (&UserTextureClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := up.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(userprofile.Table, userprofile.FieldID, id),
+ sqlgraph.To(usertexture.Table, usertexture.FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, userprofile.UsertextureTable, userprofile.UsertextureColumn),
+ )
+ fromV = sqlgraph.Neighbors(up.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// Hooks returns the client hooks.
+func (c *UserProfileClient) Hooks() []Hook {
+ return c.hooks.UserProfile
+}
+
+// Interceptors returns the client interceptors.
+func (c *UserProfileClient) Interceptors() []Interceptor {
+ return c.inters.UserProfile
+}
+
+func (c *UserProfileClient) mutate(ctx context.Context, m *UserProfileMutation) (Value, error) {
+ switch m.Op() {
+ case OpCreate:
+ return (&UserProfileCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpUpdate:
+ return (&UserProfileUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpUpdateOne:
+ return (&UserProfileUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpDelete, OpDeleteOne:
+ return (&UserProfileDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+ default:
+ return nil, fmt.Errorf("ent: unknown UserProfile mutation op: %q", m.Op())
+ }
+}
+
+// UserTextureClient is a client for the UserTexture schema.
+type UserTextureClient struct {
+ config
+}
+
+// NewUserTextureClient returns a client for the UserTexture from the given config.
+func NewUserTextureClient(c config) *UserTextureClient {
+ return &UserTextureClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `usertexture.Hooks(f(g(h())))`.
+func (c *UserTextureClient) Use(hooks ...Hook) {
+ c.hooks.UserTexture = append(c.hooks.UserTexture, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `usertexture.Intercept(f(g(h())))`.
+func (c *UserTextureClient) Intercept(interceptors ...Interceptor) {
+ c.inters.UserTexture = append(c.inters.UserTexture, interceptors...)
+}
+
+// Create returns a builder for creating a UserTexture entity.
+func (c *UserTextureClient) Create() *UserTextureCreate {
+ mutation := newUserTextureMutation(c.config, OpCreate)
+ return &UserTextureCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of UserTexture entities.
+func (c *UserTextureClient) CreateBulk(builders ...*UserTextureCreate) *UserTextureCreateBulk {
+ return &UserTextureCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for UserTexture.
+func (c *UserTextureClient) Update() *UserTextureUpdate {
+ mutation := newUserTextureMutation(c.config, OpUpdate)
+ return &UserTextureUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *UserTextureClient) UpdateOne(ut *UserTexture) *UserTextureUpdateOne {
+ mutation := newUserTextureMutation(c.config, OpUpdateOne, withUserTexture(ut))
+ return &UserTextureUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *UserTextureClient) UpdateOneID(id int) *UserTextureUpdateOne {
+ mutation := newUserTextureMutation(c.config, OpUpdateOne, withUserTextureID(id))
+ return &UserTextureUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for UserTexture.
+func (c *UserTextureClient) Delete() *UserTextureDelete {
+ mutation := newUserTextureMutation(c.config, OpDelete)
+ return &UserTextureDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *UserTextureClient) DeleteOne(ut *UserTexture) *UserTextureDeleteOne {
+ return c.DeleteOneID(ut.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *UserTextureClient) DeleteOneID(id int) *UserTextureDeleteOne {
+ builder := c.Delete().Where(usertexture.ID(id))
+ builder.mutation.id = &id
+ builder.mutation.op = OpDeleteOne
+ return &UserTextureDeleteOne{builder}
+}
+
+// Query returns a query builder for UserTexture.
+func (c *UserTextureClient) Query() *UserTextureQuery {
+ return &UserTextureQuery{
+ config: c.config,
+ ctx: &QueryContext{Type: TypeUserTexture},
+ inters: c.Interceptors(),
+ }
+}
+
+// Get returns a UserTexture entity by its id.
+func (c *UserTextureClient) Get(ctx context.Context, id int) (*UserTexture, error) {
+ return c.Query().Where(usertexture.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *UserTextureClient) GetX(ctx context.Context, id int) *UserTexture {
+ obj, err := c.Get(ctx, id)
+ if err != nil {
+ panic(err)
+ }
+ return obj
+}
+
+// QueryUserProfile queries the user_profile edge of a UserTexture.
+func (c *UserTextureClient) QueryUserProfile(ut *UserTexture) *UserProfileQuery {
+ query := (&UserProfileClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := ut.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(usertexture.Table, usertexture.FieldID, id),
+ sqlgraph.To(userprofile.Table, userprofile.FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, usertexture.UserProfileTable, usertexture.UserProfileColumn),
+ )
+ fromV = sqlgraph.Neighbors(ut.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// QueryTexture queries the texture edge of a UserTexture.
+func (c *UserTextureClient) QueryTexture(ut *UserTexture) *TextureQuery {
+ query := (&TextureClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := ut.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(usertexture.Table, usertexture.FieldID, id),
+ sqlgraph.To(texture.Table, texture.FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, usertexture.TextureTable, usertexture.TextureColumn),
+ )
+ fromV = sqlgraph.Neighbors(ut.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// Hooks returns the client hooks.
+func (c *UserTextureClient) Hooks() []Hook {
+ return c.hooks.UserTexture
+}
+
+// Interceptors returns the client interceptors.
+func (c *UserTextureClient) Interceptors() []Interceptor {
+ return c.inters.UserTexture
+}
+
+func (c *UserTextureClient) mutate(ctx context.Context, m *UserTextureMutation) (Value, error) {
+ switch m.Op() {
+ case OpCreate:
+ return (&UserTextureCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpUpdate:
+ return (&UserTextureUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpUpdateOne:
+ return (&UserTextureUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpDelete, OpDeleteOne:
+ return (&UserTextureDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+ default:
+ return nil, fmt.Errorf("ent: unknown UserTexture mutation op: %q", m.Op())
+ }
+}
+
+// UserTokenClient is a client for the UserToken schema.
+type UserTokenClient struct {
+ config
+}
+
+// NewUserTokenClient returns a client for the UserToken from the given config.
+func NewUserTokenClient(c config) *UserTokenClient {
+ return &UserTokenClient{config: c}
+}
+
+// Use adds a list of mutation hooks to the hooks stack.
+// A call to `Use(f, g, h)` equals to `usertoken.Hooks(f(g(h())))`.
+func (c *UserTokenClient) Use(hooks ...Hook) {
+ c.hooks.UserToken = append(c.hooks.UserToken, hooks...)
+}
+
+// Intercept adds a list of query interceptors to the interceptors stack.
+// A call to `Intercept(f, g, h)` equals to `usertoken.Intercept(f(g(h())))`.
+func (c *UserTokenClient) Intercept(interceptors ...Interceptor) {
+ c.inters.UserToken = append(c.inters.UserToken, interceptors...)
+}
+
+// Create returns a builder for creating a UserToken entity.
+func (c *UserTokenClient) Create() *UserTokenCreate {
+ mutation := newUserTokenMutation(c.config, OpCreate)
+ return &UserTokenCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// CreateBulk returns a builder for creating a bulk of UserToken entities.
+func (c *UserTokenClient) CreateBulk(builders ...*UserTokenCreate) *UserTokenCreateBulk {
+ return &UserTokenCreateBulk{config: c.config, builders: builders}
+}
+
+// Update returns an update builder for UserToken.
+func (c *UserTokenClient) Update() *UserTokenUpdate {
+ mutation := newUserTokenMutation(c.config, OpUpdate)
+ return &UserTokenUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOne returns an update builder for the given entity.
+func (c *UserTokenClient) UpdateOne(ut *UserToken) *UserTokenUpdateOne {
+ mutation := newUserTokenMutation(c.config, OpUpdateOne, withUserToken(ut))
+ return &UserTokenUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// UpdateOneID returns an update builder for the given id.
+func (c *UserTokenClient) UpdateOneID(id int) *UserTokenUpdateOne {
+ mutation := newUserTokenMutation(c.config, OpUpdateOne, withUserTokenID(id))
+ return &UserTokenUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// Delete returns a delete builder for UserToken.
+func (c *UserTokenClient) Delete() *UserTokenDelete {
+ mutation := newUserTokenMutation(c.config, OpDelete)
+ return &UserTokenDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
+}
+
+// DeleteOne returns a builder for deleting the given entity.
+func (c *UserTokenClient) DeleteOne(ut *UserToken) *UserTokenDeleteOne {
+ return c.DeleteOneID(ut.ID)
+}
+
+// DeleteOneID returns a builder for deleting the given entity by its id.
+func (c *UserTokenClient) DeleteOneID(id int) *UserTokenDeleteOne {
+ builder := c.Delete().Where(usertoken.ID(id))
+ builder.mutation.id = &id
+ builder.mutation.op = OpDeleteOne
+ return &UserTokenDeleteOne{builder}
+}
+
+// Query returns a query builder for UserToken.
+func (c *UserTokenClient) Query() *UserTokenQuery {
+ return &UserTokenQuery{
+ config: c.config,
+ ctx: &QueryContext{Type: TypeUserToken},
+ inters: c.Interceptors(),
+ }
+}
+
+// Get returns a UserToken entity by its id.
+func (c *UserTokenClient) Get(ctx context.Context, id int) (*UserToken, error) {
+ return c.Query().Where(usertoken.ID(id)).Only(ctx)
+}
+
+// GetX is like Get, but panics if an error occurs.
+func (c *UserTokenClient) GetX(ctx context.Context, id int) *UserToken {
+ obj, err := c.Get(ctx, id)
+ if err != nil {
+ panic(err)
+ }
+ return obj
+}
+
+// QueryUser queries the user edge of a UserToken.
+func (c *UserTokenClient) QueryUser(ut *UserToken) *UserQuery {
+ query := (&UserClient{config: c.config}).Query()
+ query.path = func(context.Context) (fromV *sql.Selector, _ error) {
+ id := ut.ID
+ step := sqlgraph.NewStep(
+ sqlgraph.From(usertoken.Table, usertoken.FieldID, id),
+ sqlgraph.To(user.Table, user.FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, true, usertoken.UserTable, usertoken.UserColumn),
+ )
+ fromV = sqlgraph.Neighbors(ut.driver.Dialect(), step)
+ return fromV, nil
+ }
+ return query
+}
+
+// Hooks returns the client hooks.
+func (c *UserTokenClient) Hooks() []Hook {
+ return c.hooks.UserToken
+}
+
+// Interceptors returns the client interceptors.
+func (c *UserTokenClient) Interceptors() []Interceptor {
+ return c.inters.UserToken
+}
+
+func (c *UserTokenClient) mutate(ctx context.Context, m *UserTokenMutation) (Value, error) {
+ switch m.Op() {
+ case OpCreate:
+ return (&UserTokenCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpUpdate:
+ return (&UserTokenUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpUpdateOne:
+ return (&UserTokenUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
+ case OpDelete, OpDeleteOne:
+ return (&UserTokenDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
+ default:
+ return nil, fmt.Errorf("ent: unknown UserToken mutation op: %q", m.Op())
+ }
+}
+
+// hooks and interceptors per client, for fast access.
+type (
+ hooks struct {
+ Texture, User, UserProfile, UserTexture, UserToken []ent.Hook
+ }
+ inters struct {
+ Texture, User, UserProfile, UserTexture, UserToken []ent.Interceptor
+ }
+)
diff --git a/db/ent/ent.go b/db/ent/ent.go
new file mode 100644
index 0000000..8ef748e
--- /dev/null
+++ b/db/ent/ent.go
@@ -0,0 +1,616 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "reflect"
+ "sync"
+
+ "entgo.io/ent"
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+// ent aliases to avoid import conflicts in user's code.
+type (
+ Op = ent.Op
+ Hook = ent.Hook
+ Value = ent.Value
+ Query = ent.Query
+ QueryContext = ent.QueryContext
+ Querier = ent.Querier
+ QuerierFunc = ent.QuerierFunc
+ Interceptor = ent.Interceptor
+ InterceptFunc = ent.InterceptFunc
+ Traverser = ent.Traverser
+ TraverseFunc = ent.TraverseFunc
+ Policy = ent.Policy
+ Mutator = ent.Mutator
+ Mutation = ent.Mutation
+ MutateFunc = ent.MutateFunc
+)
+
+type clientCtxKey struct{}
+
+// FromContext returns a Client stored inside a context, or nil if there isn't one.
+func FromContext(ctx context.Context) *Client {
+ c, _ := ctx.Value(clientCtxKey{}).(*Client)
+ return c
+}
+
+// NewContext returns a new context with the given Client attached.
+func NewContext(parent context.Context, c *Client) context.Context {
+ return context.WithValue(parent, clientCtxKey{}, c)
+}
+
+type txCtxKey struct{}
+
+// TxFromContext returns a Tx stored inside a context, or nil if there isn't one.
+func TxFromContext(ctx context.Context) *Tx {
+ tx, _ := ctx.Value(txCtxKey{}).(*Tx)
+ return tx
+}
+
+// NewTxContext returns a new context with the given Tx attached.
+func NewTxContext(parent context.Context, tx *Tx) context.Context {
+ return context.WithValue(parent, txCtxKey{}, tx)
+}
+
+// OrderFunc applies an ordering on the sql selector.
+// Deprecated: Use Asc/Desc functions or the package builders instead.
+type OrderFunc func(*sql.Selector)
+
+var (
+ initCheck sync.Once
+ columnCheck sql.ColumnCheck
+)
+
+// columnChecker checks if the column exists in the given table.
+func checkColumn(table, column string) error {
+ initCheck.Do(func() {
+ columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
+ texture.Table: texture.ValidColumn,
+ user.Table: user.ValidColumn,
+ userprofile.Table: userprofile.ValidColumn,
+ usertexture.Table: usertexture.ValidColumn,
+ usertoken.Table: usertoken.ValidColumn,
+ })
+ })
+ return columnCheck(table, column)
+}
+
+// Asc applies the given fields in ASC order.
+func Asc(fields ...string) func(*sql.Selector) {
+ return func(s *sql.Selector) {
+ for _, f := range fields {
+ if err := checkColumn(s.TableName(), f); err != nil {
+ s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)})
+ }
+ s.OrderBy(sql.Asc(s.C(f)))
+ }
+ }
+}
+
+// Desc applies the given fields in DESC order.
+func Desc(fields ...string) func(*sql.Selector) {
+ return func(s *sql.Selector) {
+ for _, f := range fields {
+ if err := checkColumn(s.TableName(), f); err != nil {
+ s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)})
+ }
+ s.OrderBy(sql.Desc(s.C(f)))
+ }
+ }
+}
+
+// AggregateFunc applies an aggregation step on the group-by traversal/selector.
+type AggregateFunc func(*sql.Selector) string
+
+// As is a pseudo aggregation function for renaming another other functions with custom names. For example:
+//
+// GroupBy(field1, field2).
+// Aggregate(ent.As(ent.Sum(field1), "sum_field1"), (ent.As(ent.Sum(field2), "sum_field2")).
+// Scan(ctx, &v)
+func As(fn AggregateFunc, end string) AggregateFunc {
+ return func(s *sql.Selector) string {
+ return sql.As(fn(s), end)
+ }
+}
+
+// Count applies the "count" aggregation function on each group.
+func Count() AggregateFunc {
+ return func(s *sql.Selector) string {
+ return sql.Count("*")
+ }
+}
+
+// Max applies the "max" aggregation function on the given field of each group.
+func Max(field string) AggregateFunc {
+ return func(s *sql.Selector) string {
+ if err := checkColumn(s.TableName(), field); err != nil {
+ s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
+ return ""
+ }
+ return sql.Max(s.C(field))
+ }
+}
+
+// Mean applies the "mean" aggregation function on the given field of each group.
+func Mean(field string) AggregateFunc {
+ return func(s *sql.Selector) string {
+ if err := checkColumn(s.TableName(), field); err != nil {
+ s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
+ return ""
+ }
+ return sql.Avg(s.C(field))
+ }
+}
+
+// Min applies the "min" aggregation function on the given field of each group.
+func Min(field string) AggregateFunc {
+ return func(s *sql.Selector) string {
+ if err := checkColumn(s.TableName(), field); err != nil {
+ s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
+ return ""
+ }
+ return sql.Min(s.C(field))
+ }
+}
+
+// Sum applies the "sum" aggregation function on the given field of each group.
+func Sum(field string) AggregateFunc {
+ return func(s *sql.Selector) string {
+ if err := checkColumn(s.TableName(), field); err != nil {
+ s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)})
+ return ""
+ }
+ return sql.Sum(s.C(field))
+ }
+}
+
+// ValidationError returns when validating a field or edge fails.
+type ValidationError struct {
+ Name string // Field or edge name.
+ err error
+}
+
+// Error implements the error interface.
+func (e *ValidationError) Error() string {
+ return e.err.Error()
+}
+
+// Unwrap implements the errors.Wrapper interface.
+func (e *ValidationError) Unwrap() error {
+ return e.err
+}
+
+// IsValidationError returns a boolean indicating whether the error is a validation error.
+func IsValidationError(err error) bool {
+ if err == nil {
+ return false
+ }
+ var e *ValidationError
+ return errors.As(err, &e)
+}
+
+// NotFoundError returns when trying to fetch a specific entity and it was not found in the database.
+type NotFoundError struct {
+ label string
+}
+
+// Error implements the error interface.
+func (e *NotFoundError) Error() string {
+ return "ent: " + e.label + " not found"
+}
+
+// IsNotFound returns a boolean indicating whether the error is a not found error.
+func IsNotFound(err error) bool {
+ if err == nil {
+ return false
+ }
+ var e *NotFoundError
+ return errors.As(err, &e)
+}
+
+// MaskNotFound masks not found error.
+func MaskNotFound(err error) error {
+ if IsNotFound(err) {
+ return nil
+ }
+ return err
+}
+
+// NotSingularError returns when trying to fetch a singular entity and more then one was found in the database.
+type NotSingularError struct {
+ label string
+}
+
+// Error implements the error interface.
+func (e *NotSingularError) Error() string {
+ return "ent: " + e.label + " not singular"
+}
+
+// IsNotSingular returns a boolean indicating whether the error is a not singular error.
+func IsNotSingular(err error) bool {
+ if err == nil {
+ return false
+ }
+ var e *NotSingularError
+ return errors.As(err, &e)
+}
+
+// NotLoadedError returns when trying to get a node that was not loaded by the query.
+type NotLoadedError struct {
+ edge string
+}
+
+// Error implements the error interface.
+func (e *NotLoadedError) Error() string {
+ return "ent: " + e.edge + " edge was not loaded"
+}
+
+// IsNotLoaded returns a boolean indicating whether the error is a not loaded error.
+func IsNotLoaded(err error) bool {
+ if err == nil {
+ return false
+ }
+ var e *NotLoadedError
+ return errors.As(err, &e)
+}
+
+// ConstraintError returns when trying to create/update one or more entities and
+// one or more of their constraints failed. For example, violation of edge or
+// field uniqueness.
+type ConstraintError struct {
+ msg string
+ wrap error
+}
+
+// Error implements the error interface.
+func (e ConstraintError) Error() string {
+ return "ent: constraint failed: " + e.msg
+}
+
+// Unwrap implements the errors.Wrapper interface.
+func (e *ConstraintError) Unwrap() error {
+ return e.wrap
+}
+
+// IsConstraintError returns a boolean indicating whether the error is a constraint failure.
+func IsConstraintError(err error) bool {
+ if err == nil {
+ return false
+ }
+ var e *ConstraintError
+ return errors.As(err, &e)
+}
+
+// selector embedded by the different Select/GroupBy builders.
+type selector struct {
+ label string
+ flds *[]string
+ fns []AggregateFunc
+ scan func(context.Context, any) error
+}
+
+// ScanX is like Scan, but panics if an error occurs.
+func (s *selector) ScanX(ctx context.Context, v any) {
+ if err := s.scan(ctx, v); err != nil {
+ panic(err)
+ }
+}
+
+// Strings returns list of strings from a selector. It is only allowed when selecting one field.
+func (s *selector) Strings(ctx context.Context) ([]string, error) {
+ if len(*s.flds) > 1 {
+ return nil, errors.New("ent: Strings is not achievable when selecting more than 1 field")
+ }
+ var v []string
+ if err := s.scan(ctx, &v); err != nil {
+ return nil, err
+ }
+ return v, nil
+}
+
+// StringsX is like Strings, but panics if an error occurs.
+func (s *selector) StringsX(ctx context.Context) []string {
+ v, err := s.Strings(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// String returns a single string from a selector. It is only allowed when selecting one field.
+func (s *selector) String(ctx context.Context) (_ string, err error) {
+ var v []string
+ if v, err = s.Strings(ctx); err != nil {
+ return
+ }
+ switch len(v) {
+ case 1:
+ return v[0], nil
+ case 0:
+ err = &NotFoundError{s.label}
+ default:
+ err = fmt.Errorf("ent: Strings returned %d results when one was expected", len(v))
+ }
+ return
+}
+
+// StringX is like String, but panics if an error occurs.
+func (s *selector) StringX(ctx context.Context) string {
+ v, err := s.String(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Ints returns list of ints from a selector. It is only allowed when selecting one field.
+func (s *selector) Ints(ctx context.Context) ([]int, error) {
+ if len(*s.flds) > 1 {
+ return nil, errors.New("ent: Ints is not achievable when selecting more than 1 field")
+ }
+ var v []int
+ if err := s.scan(ctx, &v); err != nil {
+ return nil, err
+ }
+ return v, nil
+}
+
+// IntsX is like Ints, but panics if an error occurs.
+func (s *selector) IntsX(ctx context.Context) []int {
+ v, err := s.Ints(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Int returns a single int from a selector. It is only allowed when selecting one field.
+func (s *selector) Int(ctx context.Context) (_ int, err error) {
+ var v []int
+ if v, err = s.Ints(ctx); err != nil {
+ return
+ }
+ switch len(v) {
+ case 1:
+ return v[0], nil
+ case 0:
+ err = &NotFoundError{s.label}
+ default:
+ err = fmt.Errorf("ent: Ints returned %d results when one was expected", len(v))
+ }
+ return
+}
+
+// IntX is like Int, but panics if an error occurs.
+func (s *selector) IntX(ctx context.Context) int {
+ v, err := s.Int(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Float64s returns list of float64s from a selector. It is only allowed when selecting one field.
+func (s *selector) Float64s(ctx context.Context) ([]float64, error) {
+ if len(*s.flds) > 1 {
+ return nil, errors.New("ent: Float64s is not achievable when selecting more than 1 field")
+ }
+ var v []float64
+ if err := s.scan(ctx, &v); err != nil {
+ return nil, err
+ }
+ return v, nil
+}
+
+// Float64sX is like Float64s, but panics if an error occurs.
+func (s *selector) Float64sX(ctx context.Context) []float64 {
+ v, err := s.Float64s(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Float64 returns a single float64 from a selector. It is only allowed when selecting one field.
+func (s *selector) Float64(ctx context.Context) (_ float64, err error) {
+ var v []float64
+ if v, err = s.Float64s(ctx); err != nil {
+ return
+ }
+ switch len(v) {
+ case 1:
+ return v[0], nil
+ case 0:
+ err = &NotFoundError{s.label}
+ default:
+ err = fmt.Errorf("ent: Float64s returned %d results when one was expected", len(v))
+ }
+ return
+}
+
+// Float64X is like Float64, but panics if an error occurs.
+func (s *selector) Float64X(ctx context.Context) float64 {
+ v, err := s.Float64(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Bools returns list of bools from a selector. It is only allowed when selecting one field.
+func (s *selector) Bools(ctx context.Context) ([]bool, error) {
+ if len(*s.flds) > 1 {
+ return nil, errors.New("ent: Bools is not achievable when selecting more than 1 field")
+ }
+ var v []bool
+ if err := s.scan(ctx, &v); err != nil {
+ return nil, err
+ }
+ return v, nil
+}
+
+// BoolsX is like Bools, but panics if an error occurs.
+func (s *selector) BoolsX(ctx context.Context) []bool {
+ v, err := s.Bools(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Bool returns a single bool from a selector. It is only allowed when selecting one field.
+func (s *selector) Bool(ctx context.Context) (_ bool, err error) {
+ var v []bool
+ if v, err = s.Bools(ctx); err != nil {
+ return
+ }
+ switch len(v) {
+ case 1:
+ return v[0], nil
+ case 0:
+ err = &NotFoundError{s.label}
+ default:
+ err = fmt.Errorf("ent: Bools returned %d results when one was expected", len(v))
+ }
+ return
+}
+
+// BoolX is like Bool, but panics if an error occurs.
+func (s *selector) BoolX(ctx context.Context) bool {
+ v, err := s.Bool(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// withHooks invokes the builder operation with the given hooks, if any.
+func withHooks[V Value, M any, PM interface {
+ *M
+ Mutation
+}](ctx context.Context, exec func(context.Context) (V, error), mutation PM, hooks []Hook) (value V, err error) {
+ if len(hooks) == 0 {
+ return exec(ctx)
+ }
+ var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+ mutationT, ok := any(m).(PM)
+ if !ok {
+ return nil, fmt.Errorf("unexpected mutation type %T", m)
+ }
+ // Set the mutation to the builder.
+ *mutation = *mutationT
+ return exec(ctx)
+ })
+ for i := len(hooks) - 1; i >= 0; i-- {
+ if hooks[i] == nil {
+ return value, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)")
+ }
+ mut = hooks[i](mut)
+ }
+ v, err := mut.Mutate(ctx, mutation)
+ if err != nil {
+ return value, err
+ }
+ nv, ok := v.(V)
+ if !ok {
+ return value, fmt.Errorf("unexpected node type %T returned from %T", v, mutation)
+ }
+ return nv, nil
+}
+
+// setContextOp returns a new context with the given QueryContext attached (including its op) in case it does not exist.
+func setContextOp(ctx context.Context, qc *QueryContext, op string) context.Context {
+ if ent.QueryFromContext(ctx) == nil {
+ qc.Op = op
+ ctx = ent.NewQueryContext(ctx, qc)
+ }
+ return ctx
+}
+
+func querierAll[V Value, Q interface {
+ sqlAll(context.Context, ...queryHook) (V, error)
+}]() Querier {
+ return QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
+ query, ok := q.(Q)
+ if !ok {
+ return nil, fmt.Errorf("unexpected query type %T", q)
+ }
+ return query.sqlAll(ctx)
+ })
+}
+
+func querierCount[Q interface {
+ sqlCount(context.Context) (int, error)
+}]() Querier {
+ return QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
+ query, ok := q.(Q)
+ if !ok {
+ return nil, fmt.Errorf("unexpected query type %T", q)
+ }
+ return query.sqlCount(ctx)
+ })
+}
+
+func withInterceptors[V Value](ctx context.Context, q Query, qr Querier, inters []Interceptor) (v V, err error) {
+ for i := len(inters) - 1; i >= 0; i-- {
+ qr = inters[i].Intercept(qr)
+ }
+ rv, err := qr.Query(ctx, q)
+ if err != nil {
+ return v, err
+ }
+ vt, ok := rv.(V)
+ if !ok {
+ return v, fmt.Errorf("unexpected type %T returned from %T. expected type: %T", vt, q, v)
+ }
+ return vt, nil
+}
+
+func scanWithInterceptors[Q1 ent.Query, Q2 interface {
+ sqlScan(context.Context, Q1, any) error
+}](ctx context.Context, rootQuery Q1, selectOrGroup Q2, inters []Interceptor, v any) error {
+ rv := reflect.ValueOf(v)
+ var qr Querier = QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
+ query, ok := q.(Q1)
+ if !ok {
+ return nil, fmt.Errorf("unexpected query type %T", q)
+ }
+ if err := selectOrGroup.sqlScan(ctx, query, v); err != nil {
+ return nil, err
+ }
+ if k := rv.Kind(); k == reflect.Pointer && rv.Elem().CanInterface() {
+ return rv.Elem().Interface(), nil
+ }
+ return v, nil
+ })
+ for i := len(inters) - 1; i >= 0; i-- {
+ qr = inters[i].Intercept(qr)
+ }
+ vv, err := qr.Query(ctx, rootQuery)
+ if err != nil {
+ return err
+ }
+ switch rv2 := reflect.ValueOf(vv); {
+ case rv.IsNil(), rv2.IsNil(), rv.Kind() != reflect.Pointer:
+ case rv.Type() == rv2.Type():
+ rv.Elem().Set(rv2.Elem())
+ case rv.Elem().Type() == rv2.Type():
+ rv.Elem().Set(rv2)
+ }
+ return nil
+}
+
+// queryHook describes an internal hook for the different sqlAll methods.
+type queryHook func(context.Context, *sqlgraph.QuerySpec)
diff --git a/db/ent/enttest/enttest.go b/db/ent/enttest/enttest.go
new file mode 100644
index 0000000..2cb4e57
--- /dev/null
+++ b/db/ent/enttest/enttest.go
@@ -0,0 +1,84 @@
+// Code generated by ent, DO NOT EDIT.
+
+package enttest
+
+import (
+ "context"
+
+ "github.com/xmdhs/authlib-skin/db/ent"
+ // required by schema hooks.
+ _ "github.com/xmdhs/authlib-skin/db/ent/runtime"
+
+ "entgo.io/ent/dialect/sql/schema"
+ "github.com/xmdhs/authlib-skin/db/ent/migrate"
+)
+
+type (
+ // TestingT is the interface that is shared between
+ // testing.T and testing.B and used by enttest.
+ TestingT interface {
+ FailNow()
+ Error(...any)
+ }
+
+ // Option configures client creation.
+ Option func(*options)
+
+ options struct {
+ opts []ent.Option
+ migrateOpts []schema.MigrateOption
+ }
+)
+
+// WithOptions forwards options to client creation.
+func WithOptions(opts ...ent.Option) Option {
+ return func(o *options) {
+ o.opts = append(o.opts, opts...)
+ }
+}
+
+// WithMigrateOptions forwards options to auto migration.
+func WithMigrateOptions(opts ...schema.MigrateOption) Option {
+ return func(o *options) {
+ o.migrateOpts = append(o.migrateOpts, opts...)
+ }
+}
+
+func newOptions(opts []Option) *options {
+ o := &options{}
+ for _, opt := range opts {
+ opt(o)
+ }
+ return o
+}
+
+// Open calls ent.Open and auto-run migration.
+func Open(t TestingT, driverName, dataSourceName string, opts ...Option) *ent.Client {
+ o := newOptions(opts)
+ c, err := ent.Open(driverName, dataSourceName, o.opts...)
+ if err != nil {
+ t.Error(err)
+ t.FailNow()
+ }
+ migrateSchema(t, c, o)
+ return c
+}
+
+// NewClient calls ent.NewClient and auto-run migration.
+func NewClient(t TestingT, opts ...Option) *ent.Client {
+ o := newOptions(opts)
+ c := ent.NewClient(o.opts...)
+ migrateSchema(t, c, o)
+ return c
+}
+func migrateSchema(t TestingT, c *ent.Client, o *options) {
+ tables, err := schema.CopyTables(migrate.Tables)
+ if err != nil {
+ t.Error(err)
+ t.FailNow()
+ }
+ if err := migrate.Create(context.Background(), c.Schema, tables, o.migrateOpts...); err != nil {
+ t.Error(err)
+ t.FailNow()
+ }
+}
diff --git a/db/ent/for_update.tmpl b/db/ent/for_update.tmpl
new file mode 100644
index 0000000..1507d0c
--- /dev/null
+++ b/db/ent/for_update.tmpl
@@ -0,0 +1,40 @@
+{{/*
+Copyright 2019-present Facebook Inc. All rights reserved.
+This source code is licensed under the Apache 2.0 license found
+in the LICENSE file in the root directory of this source tree.
+*/}}
+
+{{/* gotype: entgo.io/ent/entc/gen.Type */}}
+
+{{/* Templates used by the "sql/lock" feature-flag to add "SELECT ... FOR UPDATE/SHARE" capabilities. */}}
+
+{{ define "dialect/sql/query/additional/locking_sqlite" }}
+ {{ if $.FeatureEnabled "sql/lock" }}
+ {{ template "helper/sqlock_sqlite" $ }}
+ {{ end }}
+{{ end }}
+
+{{ define "helper/sqlock_sqlite" }}
+{{ $builder := pascal $.Scope.Builder }}
+{{ $receiver := receiver $builder }}
+
+// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
+// updated, deleted or "selected ... for update" by other sessions, until the transaction is
+// either committed or rolled-back.
+func ({{ $receiver }} *{{ $builder }}) ForUpdateA(opts ...sql.LockOption) *{{ $builder }} {
+ if {{ $receiver }}.driver.Dialect() == dialect.SQLite {
+ return {{ $receiver }}
+ }
+ return {{ $receiver }}.ForUpdate(opts...)
+}
+
+// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
+// on any rows that are read. Other sessions can read the rows, but cannot modify them
+// until your transaction commits.
+func ({{ $receiver }} *{{ $builder }}) ForShareA(opts ...sql.LockOption) *{{ $builder }} {
+ if {{ $receiver }}.driver.Dialect() == dialect.SQLite {
+ return {{ $receiver }}
+ }
+ return {{ $receiver }}.ForShare(opts...)
+}
+{{ end }}
\ No newline at end of file
diff --git a/db/ent/generate.go b/db/ent/generate.go
new file mode 100644
index 0000000..6dc7a9e
--- /dev/null
+++ b/db/ent/generate.go
@@ -0,0 +1,3 @@
+package ent
+
+//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/lock --template for_update.tmpl ./schema
diff --git a/db/ent/hook/hook.go b/db/ent/hook/hook.go
new file mode 100644
index 0000000..b19ae4a
--- /dev/null
+++ b/db/ent/hook/hook.go
@@ -0,0 +1,247 @@
+// Code generated by ent, DO NOT EDIT.
+
+package hook
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/xmdhs/authlib-skin/db/ent"
+)
+
+// The TextureFunc type is an adapter to allow the use of ordinary
+// function as Texture mutator.
+type TextureFunc func(context.Context, *ent.TextureMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f TextureFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+ if mv, ok := m.(*ent.TextureMutation); ok {
+ return f(ctx, mv)
+ }
+ return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.TextureMutation", m)
+}
+
+// The UserFunc type is an adapter to allow the use of ordinary
+// function as User mutator.
+type UserFunc func(context.Context, *ent.UserMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f UserFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+ if mv, ok := m.(*ent.UserMutation); ok {
+ return f(ctx, mv)
+ }
+ return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserMutation", m)
+}
+
+// The UserProfileFunc type is an adapter to allow the use of ordinary
+// function as UserProfile mutator.
+type UserProfileFunc func(context.Context, *ent.UserProfileMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f UserProfileFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+ if mv, ok := m.(*ent.UserProfileMutation); ok {
+ return f(ctx, mv)
+ }
+ return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserProfileMutation", m)
+}
+
+// The UserTextureFunc type is an adapter to allow the use of ordinary
+// function as UserTexture mutator.
+type UserTextureFunc func(context.Context, *ent.UserTextureMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f UserTextureFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+ if mv, ok := m.(*ent.UserTextureMutation); ok {
+ return f(ctx, mv)
+ }
+ return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserTextureMutation", m)
+}
+
+// The UserTokenFunc type is an adapter to allow the use of ordinary
+// function as UserToken mutator.
+type UserTokenFunc func(context.Context, *ent.UserTokenMutation) (ent.Value, error)
+
+// Mutate calls f(ctx, m).
+func (f UserTokenFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+ if mv, ok := m.(*ent.UserTokenMutation); ok {
+ return f(ctx, mv)
+ }
+ return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserTokenMutation", m)
+}
+
+// Condition is a hook condition function.
+type Condition func(context.Context, ent.Mutation) bool
+
+// And groups conditions with the AND operator.
+func And(first, second Condition, rest ...Condition) Condition {
+ return func(ctx context.Context, m ent.Mutation) bool {
+ if !first(ctx, m) || !second(ctx, m) {
+ return false
+ }
+ for _, cond := range rest {
+ if !cond(ctx, m) {
+ return false
+ }
+ }
+ return true
+ }
+}
+
+// Or groups conditions with the OR operator.
+func Or(first, second Condition, rest ...Condition) Condition {
+ return func(ctx context.Context, m ent.Mutation) bool {
+ if first(ctx, m) || second(ctx, m) {
+ return true
+ }
+ for _, cond := range rest {
+ if cond(ctx, m) {
+ return true
+ }
+ }
+ return false
+ }
+}
+
+// Not negates a given condition.
+func Not(cond Condition) Condition {
+ return func(ctx context.Context, m ent.Mutation) bool {
+ return !cond(ctx, m)
+ }
+}
+
+// HasOp is a condition testing mutation operation.
+func HasOp(op ent.Op) Condition {
+ return func(_ context.Context, m ent.Mutation) bool {
+ return m.Op().Is(op)
+ }
+}
+
+// HasAddedFields is a condition validating `.AddedField` on fields.
+func HasAddedFields(field string, fields ...string) Condition {
+ return func(_ context.Context, m ent.Mutation) bool {
+ if _, exists := m.AddedField(field); !exists {
+ return false
+ }
+ for _, field := range fields {
+ if _, exists := m.AddedField(field); !exists {
+ return false
+ }
+ }
+ return true
+ }
+}
+
+// HasClearedFields is a condition validating `.FieldCleared` on fields.
+func HasClearedFields(field string, fields ...string) Condition {
+ return func(_ context.Context, m ent.Mutation) bool {
+ if exists := m.FieldCleared(field); !exists {
+ return false
+ }
+ for _, field := range fields {
+ if exists := m.FieldCleared(field); !exists {
+ return false
+ }
+ }
+ return true
+ }
+}
+
+// HasFields is a condition validating `.Field` on fields.
+func HasFields(field string, fields ...string) Condition {
+ return func(_ context.Context, m ent.Mutation) bool {
+ if _, exists := m.Field(field); !exists {
+ return false
+ }
+ for _, field := range fields {
+ if _, exists := m.Field(field); !exists {
+ return false
+ }
+ }
+ return true
+ }
+}
+
+// If executes the given hook under condition.
+//
+// hook.If(ComputeAverage, And(HasFields(...), HasAddedFields(...)))
+func If(hk ent.Hook, cond Condition) ent.Hook {
+ return func(next ent.Mutator) ent.Mutator {
+ return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) {
+ if cond(ctx, m) {
+ return hk(next).Mutate(ctx, m)
+ }
+ return next.Mutate(ctx, m)
+ })
+ }
+}
+
+// On executes the given hook only for the given operation.
+//
+// hook.On(Log, ent.Delete|ent.Create)
+func On(hk ent.Hook, op ent.Op) ent.Hook {
+ return If(hk, HasOp(op))
+}
+
+// Unless skips the given hook only for the given operation.
+//
+// hook.Unless(Log, ent.Update|ent.UpdateOne)
+func Unless(hk ent.Hook, op ent.Op) ent.Hook {
+ return If(hk, Not(HasOp(op)))
+}
+
+// FixedError is a hook returning a fixed error.
+func FixedError(err error) ent.Hook {
+ return func(ent.Mutator) ent.Mutator {
+ return ent.MutateFunc(func(context.Context, ent.Mutation) (ent.Value, error) {
+ return nil, err
+ })
+ }
+}
+
+// Reject returns a hook that rejects all operations that match op.
+//
+// func (T) Hooks() []ent.Hook {
+// return []ent.Hook{
+// Reject(ent.Delete|ent.Update),
+// }
+// }
+func Reject(op ent.Op) ent.Hook {
+ hk := FixedError(fmt.Errorf("%s operation is not allowed", op))
+ return On(hk, op)
+}
+
+// Chain acts as a list of hooks and is effectively immutable.
+// Once created, it will always hold the same set of hooks in the same order.
+type Chain struct {
+ hooks []ent.Hook
+}
+
+// NewChain creates a new chain of hooks.
+func NewChain(hooks ...ent.Hook) Chain {
+ return Chain{append([]ent.Hook(nil), hooks...)}
+}
+
+// Hook chains the list of hooks and returns the final hook.
+func (c Chain) Hook() ent.Hook {
+ return func(mutator ent.Mutator) ent.Mutator {
+ for i := len(c.hooks) - 1; i >= 0; i-- {
+ mutator = c.hooks[i](mutator)
+ }
+ return mutator
+ }
+}
+
+// Append extends a chain, adding the specified hook
+// as the last ones in the mutation flow.
+func (c Chain) Append(hooks ...ent.Hook) Chain {
+ newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks))
+ newHooks = append(newHooks, c.hooks...)
+ newHooks = append(newHooks, hooks...)
+ return Chain{newHooks}
+}
+
+// Extend extends a chain, adding the specified chain
+// as the last ones in the mutation flow.
+func (c Chain) Extend(chain Chain) Chain {
+ return c.Append(chain.hooks...)
+}
diff --git a/db/ent/migrate/migrate.go b/db/ent/migrate/migrate.go
new file mode 100644
index 0000000..1956a6b
--- /dev/null
+++ b/db/ent/migrate/migrate.go
@@ -0,0 +1,64 @@
+// Code generated by ent, DO NOT EDIT.
+
+package migrate
+
+import (
+ "context"
+ "fmt"
+ "io"
+
+ "entgo.io/ent/dialect"
+ "entgo.io/ent/dialect/sql/schema"
+)
+
+var (
+ // WithGlobalUniqueID sets the universal ids options to the migration.
+ // If this option is enabled, ent migration will allocate a 1<<32 range
+ // for the ids of each entity (table).
+ // Note that this option cannot be applied on tables that already exist.
+ WithGlobalUniqueID = schema.WithGlobalUniqueID
+ // WithDropColumn sets the drop column option to the migration.
+ // If this option is enabled, ent migration will drop old columns
+ // that were used for both fields and edges. This defaults to false.
+ WithDropColumn = schema.WithDropColumn
+ // WithDropIndex sets the drop index option to the migration.
+ // If this option is enabled, ent migration will drop old indexes
+ // that were defined in the schema. This defaults to false.
+ // Note that unique constraints are defined using `UNIQUE INDEX`,
+ // and therefore, it's recommended to enable this option to get more
+ // flexibility in the schema changes.
+ WithDropIndex = schema.WithDropIndex
+ // WithForeignKeys enables creating foreign-key in schema DDL. This defaults to true.
+ WithForeignKeys = schema.WithForeignKeys
+)
+
+// Schema is the API for creating, migrating and dropping a schema.
+type Schema struct {
+ drv dialect.Driver
+}
+
+// NewSchema creates a new schema client.
+func NewSchema(drv dialect.Driver) *Schema { return &Schema{drv: drv} }
+
+// Create creates all schema resources.
+func (s *Schema) Create(ctx context.Context, opts ...schema.MigrateOption) error {
+ return Create(ctx, s, Tables, opts...)
+}
+
+// Create creates all table resources using the given schema driver.
+func Create(ctx context.Context, s *Schema, tables []*schema.Table, opts ...schema.MigrateOption) error {
+ migrate, err := schema.NewMigrate(s.drv, opts...)
+ if err != nil {
+ return fmt.Errorf("ent/migrate: %w", err)
+ }
+ return migrate.Create(ctx, tables...)
+}
+
+// WriteTo writes the schema changes to w instead of running them against the database.
+//
+// if err := client.Schema.WriteTo(context.Background(), os.Stdout); err != nil {
+// log.Fatal(err)
+// }
+func (s *Schema) WriteTo(ctx context.Context, w io.Writer, opts ...schema.MigrateOption) error {
+ return Create(ctx, &Schema{drv: &schema.WriteDriver{Writer: w, Driver: s.drv}}, Tables, opts...)
+}
diff --git a/db/ent/migrate/schema.go b/db/ent/migrate/schema.go
new file mode 100644
index 0000000..032788f
--- /dev/null
+++ b/db/ent/migrate/schema.go
@@ -0,0 +1,192 @@
+// Code generated by ent, DO NOT EDIT.
+
+package migrate
+
+import (
+ "entgo.io/ent/dialect/sql/schema"
+ "entgo.io/ent/schema/field"
+)
+
+var (
+ // TexturesColumns holds the columns for the "textures" table.
+ TexturesColumns = []*schema.Column{
+ {Name: "id", Type: field.TypeInt, Increment: true},
+ {Name: "texture_hash", Type: field.TypeString, SchemaType: map[string]string{"mysql": "VARCHAR(100)"}},
+ {Name: "texture_created_user", Type: field.TypeInt},
+ }
+ // TexturesTable holds the schema information for the "textures" table.
+ TexturesTable = &schema.Table{
+ Name: "textures",
+ Columns: TexturesColumns,
+ PrimaryKey: []*schema.Column{TexturesColumns[0]},
+ ForeignKeys: []*schema.ForeignKey{
+ {
+ Symbol: "textures_users_created_user",
+ Columns: []*schema.Column{TexturesColumns[2]},
+ RefColumns: []*schema.Column{UsersColumns[0]},
+ OnDelete: schema.NoAction,
+ },
+ },
+ Indexes: []*schema.Index{
+ {
+ Name: "texture_texture_hash",
+ Unique: true,
+ Columns: []*schema.Column{TexturesColumns[1]},
+ },
+ },
+ }
+ // UsersColumns holds the columns for the "users" table.
+ UsersColumns = []*schema.Column{
+ {Name: "id", Type: field.TypeInt, Increment: true},
+ {Name: "email", Type: field.TypeString, Unique: true, SchemaType: map[string]string{"mysql": "VARCHAR(30)"}},
+ {Name: "password", Type: field.TypeString, SchemaType: map[string]string{"mysql": "VARCHAR(80)"}},
+ {Name: "salt", Type: field.TypeString, SchemaType: map[string]string{"mysql": "VARCHAR(50)"}},
+ {Name: "reg_ip", Type: field.TypeString, SchemaType: map[string]string{"mysql": "VARCHAR(32)"}},
+ {Name: "state", Type: field.TypeInt},
+ {Name: "reg_time", Type: field.TypeInt64},
+ }
+ // UsersTable holds the schema information for the "users" table.
+ UsersTable = &schema.Table{
+ Name: "users",
+ Columns: UsersColumns,
+ PrimaryKey: []*schema.Column{UsersColumns[0]},
+ Indexes: []*schema.Index{
+ {
+ Name: "user_email",
+ Unique: true,
+ Columns: []*schema.Column{UsersColumns[1]},
+ },
+ {
+ Name: "user_reg_ip",
+ Unique: false,
+ Columns: []*schema.Column{UsersColumns[4]},
+ },
+ },
+ }
+ // UserProfilesColumns holds the columns for the "user_profiles" table.
+ UserProfilesColumns = []*schema.Column{
+ {Name: "id", Type: field.TypeInt, Increment: true},
+ {Name: "name", Type: field.TypeString, Unique: true, SchemaType: map[string]string{"mysql": "VARCHAR(20)"}},
+ {Name: "uuid", Type: field.TypeString, SchemaType: map[string]string{"mysql": "VARCHAR(32)"}},
+ {Name: "user_profile", Type: field.TypeInt, Unique: true},
+ }
+ // UserProfilesTable holds the schema information for the "user_profiles" table.
+ UserProfilesTable = &schema.Table{
+ Name: "user_profiles",
+ Columns: UserProfilesColumns,
+ PrimaryKey: []*schema.Column{UserProfilesColumns[0]},
+ ForeignKeys: []*schema.ForeignKey{
+ {
+ Symbol: "user_profiles_users_profile",
+ Columns: []*schema.Column{UserProfilesColumns[3]},
+ RefColumns: []*schema.Column{UsersColumns[0]},
+ OnDelete: schema.NoAction,
+ },
+ },
+ Indexes: []*schema.Index{
+ {
+ Name: "userprofile_user_profile",
+ Unique: false,
+ Columns: []*schema.Column{UserProfilesColumns[3]},
+ },
+ {
+ Name: "userprofile_name",
+ Unique: false,
+ Columns: []*schema.Column{UserProfilesColumns[1]},
+ },
+ {
+ Name: "userprofile_uuid",
+ Unique: false,
+ Columns: []*schema.Column{UserProfilesColumns[2]},
+ },
+ },
+ }
+ // UserTexturesColumns holds the columns for the "user_textures" table.
+ UserTexturesColumns = []*schema.Column{
+ {Name: "id", Type: field.TypeInt, Increment: true},
+ {Name: "type", Type: field.TypeString, SchemaType: map[string]string{"mysql": "VARCHAR(10)"}},
+ {Name: "variant", Type: field.TypeString, SchemaType: map[string]string{"mysql": "VARCHAR(10)"}},
+ {Name: "user_profile_id", Type: field.TypeInt},
+ {Name: "texture_id", Type: field.TypeInt},
+ }
+ // UserTexturesTable holds the schema information for the "user_textures" table.
+ UserTexturesTable = &schema.Table{
+ Name: "user_textures",
+ Columns: UserTexturesColumns,
+ PrimaryKey: []*schema.Column{UserTexturesColumns[0]},
+ ForeignKeys: []*schema.ForeignKey{
+ {
+ Symbol: "user_textures_user_profiles_user_profile",
+ Columns: []*schema.Column{UserTexturesColumns[3]},
+ RefColumns: []*schema.Column{UserProfilesColumns[0]},
+ OnDelete: schema.NoAction,
+ },
+ {
+ Symbol: "user_textures_textures_texture",
+ Columns: []*schema.Column{UserTexturesColumns[4]},
+ RefColumns: []*schema.Column{TexturesColumns[0]},
+ OnDelete: schema.NoAction,
+ },
+ },
+ Indexes: []*schema.Index{
+ {
+ Name: "usertexture_user_profile_id",
+ Unique: false,
+ Columns: []*schema.Column{UserTexturesColumns[3]},
+ },
+ {
+ Name: "usertexture_texture_id",
+ Unique: false,
+ Columns: []*schema.Column{UserTexturesColumns[4]},
+ },
+ {
+ Name: "usertexture_texture_id_user_profile_id",
+ Unique: true,
+ Columns: []*schema.Column{UserTexturesColumns[4], UserTexturesColumns[3]},
+ },
+ },
+ }
+ // UserTokensColumns holds the columns for the "user_tokens" table.
+ UserTokensColumns = []*schema.Column{
+ {Name: "id", Type: field.TypeInt, Increment: true},
+ {Name: "token_id", Type: field.TypeUint64},
+ {Name: "user_token", Type: field.TypeInt, Unique: true, Nullable: true},
+ }
+ // UserTokensTable holds the schema information for the "user_tokens" table.
+ UserTokensTable = &schema.Table{
+ Name: "user_tokens",
+ Columns: UserTokensColumns,
+ PrimaryKey: []*schema.Column{UserTokensColumns[0]},
+ ForeignKeys: []*schema.ForeignKey{
+ {
+ Symbol: "user_tokens_users_token",
+ Columns: []*schema.Column{UserTokensColumns[2]},
+ RefColumns: []*schema.Column{UsersColumns[0]},
+ OnDelete: schema.SetNull,
+ },
+ },
+ Indexes: []*schema.Index{
+ {
+ Name: "usertoken_user_token",
+ Unique: false,
+ Columns: []*schema.Column{UserTokensColumns[2]},
+ },
+ },
+ }
+ // Tables holds all the tables in the schema.
+ Tables = []*schema.Table{
+ TexturesTable,
+ UsersTable,
+ UserProfilesTable,
+ UserTexturesTable,
+ UserTokensTable,
+ }
+)
+
+func init() {
+ TexturesTable.ForeignKeys[0].RefTable = UsersTable
+ UserProfilesTable.ForeignKeys[0].RefTable = UsersTable
+ UserTexturesTable.ForeignKeys[0].RefTable = UserProfilesTable
+ UserTexturesTable.ForeignKeys[1].RefTable = TexturesTable
+ UserTokensTable.ForeignKeys[0].RefTable = UsersTable
+}
diff --git a/db/ent/mutation.go b/db/ent/mutation.go
new file mode 100644
index 0000000..5ca47ec
--- /dev/null
+++ b/db/ent/mutation.go
@@ -0,0 +1,3105 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "sync"
+
+ "entgo.io/ent"
+ "entgo.io/ent/dialect/sql"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+const (
+ // Operation types.
+ OpCreate = ent.OpCreate
+ OpDelete = ent.OpDelete
+ OpDeleteOne = ent.OpDeleteOne
+ OpUpdate = ent.OpUpdate
+ OpUpdateOne = ent.OpUpdateOne
+
+ // Node types.
+ TypeTexture = "Texture"
+ TypeUser = "User"
+ TypeUserProfile = "UserProfile"
+ TypeUserTexture = "UserTexture"
+ TypeUserToken = "UserToken"
+)
+
+// TextureMutation represents an operation that mutates the Texture nodes in the graph.
+type TextureMutation struct {
+ config
+ op Op
+ typ string
+ id *int
+ texture_hash *string
+ clearedFields map[string]struct{}
+ created_user *int
+ clearedcreated_user bool
+ user_profile map[int]struct{}
+ removeduser_profile map[int]struct{}
+ cleareduser_profile bool
+ usertexture map[int]struct{}
+ removedusertexture map[int]struct{}
+ clearedusertexture bool
+ done bool
+ oldValue func(context.Context) (*Texture, error)
+ predicates []predicate.Texture
+}
+
+var _ ent.Mutation = (*TextureMutation)(nil)
+
+// textureOption allows management of the mutation configuration using functional options.
+type textureOption func(*TextureMutation)
+
+// newTextureMutation creates new mutation for the Texture entity.
+func newTextureMutation(c config, op Op, opts ...textureOption) *TextureMutation {
+ m := &TextureMutation{
+ config: c,
+ op: op,
+ typ: TypeTexture,
+ clearedFields: make(map[string]struct{}),
+ }
+ for _, opt := range opts {
+ opt(m)
+ }
+ return m
+}
+
+// withTextureID sets the ID field of the mutation.
+func withTextureID(id int) textureOption {
+ return func(m *TextureMutation) {
+ var (
+ err error
+ once sync.Once
+ value *Texture
+ )
+ m.oldValue = func(ctx context.Context) (*Texture, error) {
+ once.Do(func() {
+ if m.done {
+ err = errors.New("querying old values post mutation is not allowed")
+ } else {
+ value, err = m.Client().Texture.Get(ctx, id)
+ }
+ })
+ return value, err
+ }
+ m.id = &id
+ }
+}
+
+// withTexture sets the old Texture of the mutation.
+func withTexture(node *Texture) textureOption {
+ return func(m *TextureMutation) {
+ m.oldValue = func(context.Context) (*Texture, error) {
+ return node, nil
+ }
+ m.id = &node.ID
+ }
+}
+
+// Client returns a new `ent.Client` from the mutation. If the mutation was
+// executed in a transaction (ent.Tx), a transactional client is returned.
+func (m TextureMutation) Client() *Client {
+ client := &Client{config: m.config}
+ client.init()
+ return client
+}
+
+// Tx returns an `ent.Tx` for mutations that were executed in transactions;
+// it returns an error otherwise.
+func (m TextureMutation) Tx() (*Tx, error) {
+ if _, ok := m.driver.(*txDriver); !ok {
+ return nil, errors.New("ent: mutation is not running in a transaction")
+ }
+ tx := &Tx{config: m.config}
+ tx.init()
+ return tx, nil
+}
+
+// ID returns the ID value in the mutation. Note that the ID is only available
+// if it was provided to the builder or after it was returned from the database.
+func (m *TextureMutation) ID() (id int, exists bool) {
+ if m.id == nil {
+ return
+ }
+ return *m.id, true
+}
+
+// IDs queries the database and returns the entity ids that match the mutation's predicate.
+// That means, if the mutation is applied within a transaction with an isolation level such
+// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
+// or updated by the mutation.
+func (m *TextureMutation) IDs(ctx context.Context) ([]int, error) {
+ switch {
+ case m.op.Is(OpUpdateOne | OpDeleteOne):
+ id, exists := m.ID()
+ if exists {
+ return []int{id}, nil
+ }
+ fallthrough
+ case m.op.Is(OpUpdate | OpDelete):
+ return m.Client().Texture.Query().Where(m.predicates...).IDs(ctx)
+ default:
+ return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
+ }
+}
+
+// SetTextureHash sets the "texture_hash" field.
+func (m *TextureMutation) SetTextureHash(s string) {
+ m.texture_hash = &s
+}
+
+// TextureHash returns the value of the "texture_hash" field in the mutation.
+func (m *TextureMutation) TextureHash() (r string, exists bool) {
+ v := m.texture_hash
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldTextureHash returns the old "texture_hash" field's value of the Texture entity.
+// If the Texture object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *TextureMutation) OldTextureHash(ctx context.Context) (v string, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldTextureHash is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldTextureHash requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldTextureHash: %w", err)
+ }
+ return oldValue.TextureHash, nil
+}
+
+// ResetTextureHash resets all changes to the "texture_hash" field.
+func (m *TextureMutation) ResetTextureHash() {
+ m.texture_hash = nil
+}
+
+// SetCreatedUserID sets the "created_user" edge to the User entity by id.
+func (m *TextureMutation) SetCreatedUserID(id int) {
+ m.created_user = &id
+}
+
+// ClearCreatedUser clears the "created_user" edge to the User entity.
+func (m *TextureMutation) ClearCreatedUser() {
+ m.clearedcreated_user = true
+}
+
+// CreatedUserCleared reports if the "created_user" edge to the User entity was cleared.
+func (m *TextureMutation) CreatedUserCleared() bool {
+ return m.clearedcreated_user
+}
+
+// CreatedUserID returns the "created_user" edge ID in the mutation.
+func (m *TextureMutation) CreatedUserID() (id int, exists bool) {
+ if m.created_user != nil {
+ return *m.created_user, true
+ }
+ return
+}
+
+// CreatedUserIDs returns the "created_user" edge IDs in the mutation.
+// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
+// CreatedUserID instead. It exists only for internal usage by the builders.
+func (m *TextureMutation) CreatedUserIDs() (ids []int) {
+ if id := m.created_user; id != nil {
+ ids = append(ids, *id)
+ }
+ return
+}
+
+// ResetCreatedUser resets all changes to the "created_user" edge.
+func (m *TextureMutation) ResetCreatedUser() {
+ m.created_user = nil
+ m.clearedcreated_user = false
+}
+
+// AddUserProfileIDs adds the "user_profile" edge to the UserProfile entity by ids.
+func (m *TextureMutation) AddUserProfileIDs(ids ...int) {
+ if m.user_profile == nil {
+ m.user_profile = make(map[int]struct{})
+ }
+ for i := range ids {
+ m.user_profile[ids[i]] = struct{}{}
+ }
+}
+
+// ClearUserProfile clears the "user_profile" edge to the UserProfile entity.
+func (m *TextureMutation) ClearUserProfile() {
+ m.cleareduser_profile = true
+}
+
+// UserProfileCleared reports if the "user_profile" edge to the UserProfile entity was cleared.
+func (m *TextureMutation) UserProfileCleared() bool {
+ return m.cleareduser_profile
+}
+
+// RemoveUserProfileIDs removes the "user_profile" edge to the UserProfile entity by IDs.
+func (m *TextureMutation) RemoveUserProfileIDs(ids ...int) {
+ if m.removeduser_profile == nil {
+ m.removeduser_profile = make(map[int]struct{})
+ }
+ for i := range ids {
+ delete(m.user_profile, ids[i])
+ m.removeduser_profile[ids[i]] = struct{}{}
+ }
+}
+
+// RemovedUserProfile returns the removed IDs of the "user_profile" edge to the UserProfile entity.
+func (m *TextureMutation) RemovedUserProfileIDs() (ids []int) {
+ for id := range m.removeduser_profile {
+ ids = append(ids, id)
+ }
+ return
+}
+
+// UserProfileIDs returns the "user_profile" edge IDs in the mutation.
+func (m *TextureMutation) UserProfileIDs() (ids []int) {
+ for id := range m.user_profile {
+ ids = append(ids, id)
+ }
+ return
+}
+
+// ResetUserProfile resets all changes to the "user_profile" edge.
+func (m *TextureMutation) ResetUserProfile() {
+ m.user_profile = nil
+ m.cleareduser_profile = false
+ m.removeduser_profile = nil
+}
+
+// AddUsertextureIDs adds the "usertexture" edge to the UserTexture entity by ids.
+func (m *TextureMutation) AddUsertextureIDs(ids ...int) {
+ if m.usertexture == nil {
+ m.usertexture = make(map[int]struct{})
+ }
+ for i := range ids {
+ m.usertexture[ids[i]] = struct{}{}
+ }
+}
+
+// ClearUsertexture clears the "usertexture" edge to the UserTexture entity.
+func (m *TextureMutation) ClearUsertexture() {
+ m.clearedusertexture = true
+}
+
+// UsertextureCleared reports if the "usertexture" edge to the UserTexture entity was cleared.
+func (m *TextureMutation) UsertextureCleared() bool {
+ return m.clearedusertexture
+}
+
+// RemoveUsertextureIDs removes the "usertexture" edge to the UserTexture entity by IDs.
+func (m *TextureMutation) RemoveUsertextureIDs(ids ...int) {
+ if m.removedusertexture == nil {
+ m.removedusertexture = make(map[int]struct{})
+ }
+ for i := range ids {
+ delete(m.usertexture, ids[i])
+ m.removedusertexture[ids[i]] = struct{}{}
+ }
+}
+
+// RemovedUsertexture returns the removed IDs of the "usertexture" edge to the UserTexture entity.
+func (m *TextureMutation) RemovedUsertextureIDs() (ids []int) {
+ for id := range m.removedusertexture {
+ ids = append(ids, id)
+ }
+ return
+}
+
+// UsertextureIDs returns the "usertexture" edge IDs in the mutation.
+func (m *TextureMutation) UsertextureIDs() (ids []int) {
+ for id := range m.usertexture {
+ ids = append(ids, id)
+ }
+ return
+}
+
+// ResetUsertexture resets all changes to the "usertexture" edge.
+func (m *TextureMutation) ResetUsertexture() {
+ m.usertexture = nil
+ m.clearedusertexture = false
+ m.removedusertexture = nil
+}
+
+// Where appends a list predicates to the TextureMutation builder.
+func (m *TextureMutation) Where(ps ...predicate.Texture) {
+ m.predicates = append(m.predicates, ps...)
+}
+
+// WhereP appends storage-level predicates to the TextureMutation builder. Using this method,
+// users can use type-assertion to append predicates that do not depend on any generated package.
+func (m *TextureMutation) WhereP(ps ...func(*sql.Selector)) {
+ p := make([]predicate.Texture, len(ps))
+ for i := range ps {
+ p[i] = ps[i]
+ }
+ m.Where(p...)
+}
+
+// Op returns the operation name.
+func (m *TextureMutation) Op() Op {
+ return m.op
+}
+
+// SetOp allows setting the mutation operation.
+func (m *TextureMutation) SetOp(op Op) {
+ m.op = op
+}
+
+// Type returns the node type of this mutation (Texture).
+func (m *TextureMutation) Type() string {
+ return m.typ
+}
+
+// Fields returns all fields that were changed during this mutation. Note that in
+// order to get all numeric fields that were incremented/decremented, call
+// AddedFields().
+func (m *TextureMutation) Fields() []string {
+ fields := make([]string, 0, 1)
+ if m.texture_hash != nil {
+ fields = append(fields, texture.FieldTextureHash)
+ }
+ return fields
+}
+
+// Field returns the value of a field with the given name. The second boolean
+// return value indicates that this field was not set, or was not defined in the
+// schema.
+func (m *TextureMutation) Field(name string) (ent.Value, bool) {
+ switch name {
+ case texture.FieldTextureHash:
+ return m.TextureHash()
+ }
+ return nil, false
+}
+
+// OldField returns the old value of the field from the database. An error is
+// returned if the mutation operation is not UpdateOne, or the query to the
+// database failed.
+func (m *TextureMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
+ switch name {
+ case texture.FieldTextureHash:
+ return m.OldTextureHash(ctx)
+ }
+ return nil, fmt.Errorf("unknown Texture field %s", name)
+}
+
+// SetField sets the value of a field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *TextureMutation) SetField(name string, value ent.Value) error {
+ switch name {
+ case texture.FieldTextureHash:
+ v, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetTextureHash(v)
+ return nil
+ }
+ return fmt.Errorf("unknown Texture field %s", name)
+}
+
+// AddedFields returns all numeric fields that were incremented/decremented during
+// this mutation.
+func (m *TextureMutation) AddedFields() []string {
+ return nil
+}
+
+// AddedField returns the numeric value that was incremented/decremented on a field
+// with the given name. The second boolean return value indicates that this field
+// was not set, or was not defined in the schema.
+func (m *TextureMutation) AddedField(name string) (ent.Value, bool) {
+ return nil, false
+}
+
+// AddField adds the value to the field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *TextureMutation) AddField(name string, value ent.Value) error {
+ switch name {
+ }
+ return fmt.Errorf("unknown Texture numeric field %s", name)
+}
+
+// ClearedFields returns all nullable fields that were cleared during this
+// mutation.
+func (m *TextureMutation) ClearedFields() []string {
+ return nil
+}
+
+// FieldCleared returns a boolean indicating if a field with the given name was
+// cleared in this mutation.
+func (m *TextureMutation) FieldCleared(name string) bool {
+ _, ok := m.clearedFields[name]
+ return ok
+}
+
+// ClearField clears the value of the field with the given name. It returns an
+// error if the field is not defined in the schema.
+func (m *TextureMutation) ClearField(name string) error {
+ return fmt.Errorf("unknown Texture nullable field %s", name)
+}
+
+// ResetField resets all changes in the mutation for the field with the given name.
+// It returns an error if the field is not defined in the schema.
+func (m *TextureMutation) ResetField(name string) error {
+ switch name {
+ case texture.FieldTextureHash:
+ m.ResetTextureHash()
+ return nil
+ }
+ return fmt.Errorf("unknown Texture field %s", name)
+}
+
+// AddedEdges returns all edge names that were set/added in this mutation.
+func (m *TextureMutation) AddedEdges() []string {
+ edges := make([]string, 0, 3)
+ if m.created_user != nil {
+ edges = append(edges, texture.EdgeCreatedUser)
+ }
+ if m.user_profile != nil {
+ edges = append(edges, texture.EdgeUserProfile)
+ }
+ if m.usertexture != nil {
+ edges = append(edges, texture.EdgeUsertexture)
+ }
+ return edges
+}
+
+// AddedIDs returns all IDs (to other nodes) that were added for the given edge
+// name in this mutation.
+func (m *TextureMutation) AddedIDs(name string) []ent.Value {
+ switch name {
+ case texture.EdgeCreatedUser:
+ if id := m.created_user; id != nil {
+ return []ent.Value{*id}
+ }
+ case texture.EdgeUserProfile:
+ ids := make([]ent.Value, 0, len(m.user_profile))
+ for id := range m.user_profile {
+ ids = append(ids, id)
+ }
+ return ids
+ case texture.EdgeUsertexture:
+ ids := make([]ent.Value, 0, len(m.usertexture))
+ for id := range m.usertexture {
+ ids = append(ids, id)
+ }
+ return ids
+ }
+ return nil
+}
+
+// RemovedEdges returns all edge names that were removed in this mutation.
+func (m *TextureMutation) RemovedEdges() []string {
+ edges := make([]string, 0, 3)
+ if m.removeduser_profile != nil {
+ edges = append(edges, texture.EdgeUserProfile)
+ }
+ if m.removedusertexture != nil {
+ edges = append(edges, texture.EdgeUsertexture)
+ }
+ return edges
+}
+
+// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
+// the given name in this mutation.
+func (m *TextureMutation) RemovedIDs(name string) []ent.Value {
+ switch name {
+ case texture.EdgeUserProfile:
+ ids := make([]ent.Value, 0, len(m.removeduser_profile))
+ for id := range m.removeduser_profile {
+ ids = append(ids, id)
+ }
+ return ids
+ case texture.EdgeUsertexture:
+ ids := make([]ent.Value, 0, len(m.removedusertexture))
+ for id := range m.removedusertexture {
+ ids = append(ids, id)
+ }
+ return ids
+ }
+ return nil
+}
+
+// ClearedEdges returns all edge names that were cleared in this mutation.
+func (m *TextureMutation) ClearedEdges() []string {
+ edges := make([]string, 0, 3)
+ if m.clearedcreated_user {
+ edges = append(edges, texture.EdgeCreatedUser)
+ }
+ if m.cleareduser_profile {
+ edges = append(edges, texture.EdgeUserProfile)
+ }
+ if m.clearedusertexture {
+ edges = append(edges, texture.EdgeUsertexture)
+ }
+ return edges
+}
+
+// EdgeCleared returns a boolean which indicates if the edge with the given name
+// was cleared in this mutation.
+func (m *TextureMutation) EdgeCleared(name string) bool {
+ switch name {
+ case texture.EdgeCreatedUser:
+ return m.clearedcreated_user
+ case texture.EdgeUserProfile:
+ return m.cleareduser_profile
+ case texture.EdgeUsertexture:
+ return m.clearedusertexture
+ }
+ return false
+}
+
+// ClearEdge clears the value of the edge with the given name. It returns an error
+// if that edge is not defined in the schema.
+func (m *TextureMutation) ClearEdge(name string) error {
+ switch name {
+ case texture.EdgeCreatedUser:
+ m.ClearCreatedUser()
+ return nil
+ }
+ return fmt.Errorf("unknown Texture unique edge %s", name)
+}
+
+// ResetEdge resets all changes to the edge with the given name in this mutation.
+// It returns an error if the edge is not defined in the schema.
+func (m *TextureMutation) ResetEdge(name string) error {
+ switch name {
+ case texture.EdgeCreatedUser:
+ m.ResetCreatedUser()
+ return nil
+ case texture.EdgeUserProfile:
+ m.ResetUserProfile()
+ return nil
+ case texture.EdgeUsertexture:
+ m.ResetUsertexture()
+ return nil
+ }
+ return fmt.Errorf("unknown Texture edge %s", name)
+}
+
+// UserMutation represents an operation that mutates the User nodes in the graph.
+type UserMutation struct {
+ config
+ op Op
+ typ string
+ id *int
+ email *string
+ password *string
+ salt *string
+ reg_ip *string
+ state *int
+ addstate *int
+ reg_time *int64
+ addreg_time *int64
+ clearedFields map[string]struct{}
+ created_texture map[int]struct{}
+ removedcreated_texture map[int]struct{}
+ clearedcreated_texture bool
+ profile *int
+ clearedprofile bool
+ token *int
+ clearedtoken bool
+ done bool
+ oldValue func(context.Context) (*User, error)
+ predicates []predicate.User
+}
+
+var _ ent.Mutation = (*UserMutation)(nil)
+
+// userOption allows management of the mutation configuration using functional options.
+type userOption func(*UserMutation)
+
+// newUserMutation creates new mutation for the User entity.
+func newUserMutation(c config, op Op, opts ...userOption) *UserMutation {
+ m := &UserMutation{
+ config: c,
+ op: op,
+ typ: TypeUser,
+ clearedFields: make(map[string]struct{}),
+ }
+ for _, opt := range opts {
+ opt(m)
+ }
+ return m
+}
+
+// withUserID sets the ID field of the mutation.
+func withUserID(id int) userOption {
+ return func(m *UserMutation) {
+ var (
+ err error
+ once sync.Once
+ value *User
+ )
+ m.oldValue = func(ctx context.Context) (*User, error) {
+ once.Do(func() {
+ if m.done {
+ err = errors.New("querying old values post mutation is not allowed")
+ } else {
+ value, err = m.Client().User.Get(ctx, id)
+ }
+ })
+ return value, err
+ }
+ m.id = &id
+ }
+}
+
+// withUser sets the old User of the mutation.
+func withUser(node *User) userOption {
+ return func(m *UserMutation) {
+ m.oldValue = func(context.Context) (*User, error) {
+ return node, nil
+ }
+ m.id = &node.ID
+ }
+}
+
+// Client returns a new `ent.Client` from the mutation. If the mutation was
+// executed in a transaction (ent.Tx), a transactional client is returned.
+func (m UserMutation) Client() *Client {
+ client := &Client{config: m.config}
+ client.init()
+ return client
+}
+
+// Tx returns an `ent.Tx` for mutations that were executed in transactions;
+// it returns an error otherwise.
+func (m UserMutation) Tx() (*Tx, error) {
+ if _, ok := m.driver.(*txDriver); !ok {
+ return nil, errors.New("ent: mutation is not running in a transaction")
+ }
+ tx := &Tx{config: m.config}
+ tx.init()
+ return tx, nil
+}
+
+// ID returns the ID value in the mutation. Note that the ID is only available
+// if it was provided to the builder or after it was returned from the database.
+func (m *UserMutation) ID() (id int, exists bool) {
+ if m.id == nil {
+ return
+ }
+ return *m.id, true
+}
+
+// IDs queries the database and returns the entity ids that match the mutation's predicate.
+// That means, if the mutation is applied within a transaction with an isolation level such
+// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
+// or updated by the mutation.
+func (m *UserMutation) IDs(ctx context.Context) ([]int, error) {
+ switch {
+ case m.op.Is(OpUpdateOne | OpDeleteOne):
+ id, exists := m.ID()
+ if exists {
+ return []int{id}, nil
+ }
+ fallthrough
+ case m.op.Is(OpUpdate | OpDelete):
+ return m.Client().User.Query().Where(m.predicates...).IDs(ctx)
+ default:
+ return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
+ }
+}
+
+// SetEmail sets the "email" field.
+func (m *UserMutation) SetEmail(s string) {
+ m.email = &s
+}
+
+// Email returns the value of the "email" field in the mutation.
+func (m *UserMutation) Email() (r string, exists bool) {
+ v := m.email
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldEmail returns the old "email" field's value of the User entity.
+// If the User object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserMutation) OldEmail(ctx context.Context) (v string, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldEmail is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldEmail requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldEmail: %w", err)
+ }
+ return oldValue.Email, nil
+}
+
+// ResetEmail resets all changes to the "email" field.
+func (m *UserMutation) ResetEmail() {
+ m.email = nil
+}
+
+// SetPassword sets the "password" field.
+func (m *UserMutation) SetPassword(s string) {
+ m.password = &s
+}
+
+// Password returns the value of the "password" field in the mutation.
+func (m *UserMutation) Password() (r string, exists bool) {
+ v := m.password
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldPassword returns the old "password" field's value of the User entity.
+// If the User object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserMutation) OldPassword(ctx context.Context) (v string, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldPassword is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldPassword requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldPassword: %w", err)
+ }
+ return oldValue.Password, nil
+}
+
+// ResetPassword resets all changes to the "password" field.
+func (m *UserMutation) ResetPassword() {
+ m.password = nil
+}
+
+// SetSalt sets the "salt" field.
+func (m *UserMutation) SetSalt(s string) {
+ m.salt = &s
+}
+
+// Salt returns the value of the "salt" field in the mutation.
+func (m *UserMutation) Salt() (r string, exists bool) {
+ v := m.salt
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldSalt returns the old "salt" field's value of the User entity.
+// If the User object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserMutation) OldSalt(ctx context.Context) (v string, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldSalt is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldSalt requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldSalt: %w", err)
+ }
+ return oldValue.Salt, nil
+}
+
+// ResetSalt resets all changes to the "salt" field.
+func (m *UserMutation) ResetSalt() {
+ m.salt = nil
+}
+
+// SetRegIP sets the "reg_ip" field.
+func (m *UserMutation) SetRegIP(s string) {
+ m.reg_ip = &s
+}
+
+// RegIP returns the value of the "reg_ip" field in the mutation.
+func (m *UserMutation) RegIP() (r string, exists bool) {
+ v := m.reg_ip
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldRegIP returns the old "reg_ip" field's value of the User entity.
+// If the User object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserMutation) OldRegIP(ctx context.Context) (v string, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldRegIP is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldRegIP requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldRegIP: %w", err)
+ }
+ return oldValue.RegIP, nil
+}
+
+// ResetRegIP resets all changes to the "reg_ip" field.
+func (m *UserMutation) ResetRegIP() {
+ m.reg_ip = nil
+}
+
+// SetState sets the "state" field.
+func (m *UserMutation) SetState(i int) {
+ m.state = &i
+ m.addstate = nil
+}
+
+// State returns the value of the "state" field in the mutation.
+func (m *UserMutation) State() (r int, exists bool) {
+ v := m.state
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldState returns the old "state" field's value of the User entity.
+// If the User object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserMutation) OldState(ctx context.Context) (v int, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldState is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldState requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldState: %w", err)
+ }
+ return oldValue.State, nil
+}
+
+// AddState adds i to the "state" field.
+func (m *UserMutation) AddState(i int) {
+ if m.addstate != nil {
+ *m.addstate += i
+ } else {
+ m.addstate = &i
+ }
+}
+
+// AddedState returns the value that was added to the "state" field in this mutation.
+func (m *UserMutation) AddedState() (r int, exists bool) {
+ v := m.addstate
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// ResetState resets all changes to the "state" field.
+func (m *UserMutation) ResetState() {
+ m.state = nil
+ m.addstate = nil
+}
+
+// SetRegTime sets the "reg_time" field.
+func (m *UserMutation) SetRegTime(i int64) {
+ m.reg_time = &i
+ m.addreg_time = nil
+}
+
+// RegTime returns the value of the "reg_time" field in the mutation.
+func (m *UserMutation) RegTime() (r int64, exists bool) {
+ v := m.reg_time
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldRegTime returns the old "reg_time" field's value of the User entity.
+// If the User object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserMutation) OldRegTime(ctx context.Context) (v int64, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldRegTime is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldRegTime requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldRegTime: %w", err)
+ }
+ return oldValue.RegTime, nil
+}
+
+// AddRegTime adds i to the "reg_time" field.
+func (m *UserMutation) AddRegTime(i int64) {
+ if m.addreg_time != nil {
+ *m.addreg_time += i
+ } else {
+ m.addreg_time = &i
+ }
+}
+
+// AddedRegTime returns the value that was added to the "reg_time" field in this mutation.
+func (m *UserMutation) AddedRegTime() (r int64, exists bool) {
+ v := m.addreg_time
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// ResetRegTime resets all changes to the "reg_time" field.
+func (m *UserMutation) ResetRegTime() {
+ m.reg_time = nil
+ m.addreg_time = nil
+}
+
+// AddCreatedTextureIDs adds the "created_texture" edge to the Texture entity by ids.
+func (m *UserMutation) AddCreatedTextureIDs(ids ...int) {
+ if m.created_texture == nil {
+ m.created_texture = make(map[int]struct{})
+ }
+ for i := range ids {
+ m.created_texture[ids[i]] = struct{}{}
+ }
+}
+
+// ClearCreatedTexture clears the "created_texture" edge to the Texture entity.
+func (m *UserMutation) ClearCreatedTexture() {
+ m.clearedcreated_texture = true
+}
+
+// CreatedTextureCleared reports if the "created_texture" edge to the Texture entity was cleared.
+func (m *UserMutation) CreatedTextureCleared() bool {
+ return m.clearedcreated_texture
+}
+
+// RemoveCreatedTextureIDs removes the "created_texture" edge to the Texture entity by IDs.
+func (m *UserMutation) RemoveCreatedTextureIDs(ids ...int) {
+ if m.removedcreated_texture == nil {
+ m.removedcreated_texture = make(map[int]struct{})
+ }
+ for i := range ids {
+ delete(m.created_texture, ids[i])
+ m.removedcreated_texture[ids[i]] = struct{}{}
+ }
+}
+
+// RemovedCreatedTexture returns the removed IDs of the "created_texture" edge to the Texture entity.
+func (m *UserMutation) RemovedCreatedTextureIDs() (ids []int) {
+ for id := range m.removedcreated_texture {
+ ids = append(ids, id)
+ }
+ return
+}
+
+// CreatedTextureIDs returns the "created_texture" edge IDs in the mutation.
+func (m *UserMutation) CreatedTextureIDs() (ids []int) {
+ for id := range m.created_texture {
+ ids = append(ids, id)
+ }
+ return
+}
+
+// ResetCreatedTexture resets all changes to the "created_texture" edge.
+func (m *UserMutation) ResetCreatedTexture() {
+ m.created_texture = nil
+ m.clearedcreated_texture = false
+ m.removedcreated_texture = nil
+}
+
+// SetProfileID sets the "profile" edge to the UserProfile entity by id.
+func (m *UserMutation) SetProfileID(id int) {
+ m.profile = &id
+}
+
+// ClearProfile clears the "profile" edge to the UserProfile entity.
+func (m *UserMutation) ClearProfile() {
+ m.clearedprofile = true
+}
+
+// ProfileCleared reports if the "profile" edge to the UserProfile entity was cleared.
+func (m *UserMutation) ProfileCleared() bool {
+ return m.clearedprofile
+}
+
+// ProfileID returns the "profile" edge ID in the mutation.
+func (m *UserMutation) ProfileID() (id int, exists bool) {
+ if m.profile != nil {
+ return *m.profile, true
+ }
+ return
+}
+
+// ProfileIDs returns the "profile" edge IDs in the mutation.
+// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
+// ProfileID instead. It exists only for internal usage by the builders.
+func (m *UserMutation) ProfileIDs() (ids []int) {
+ if id := m.profile; id != nil {
+ ids = append(ids, *id)
+ }
+ return
+}
+
+// ResetProfile resets all changes to the "profile" edge.
+func (m *UserMutation) ResetProfile() {
+ m.profile = nil
+ m.clearedprofile = false
+}
+
+// SetTokenID sets the "token" edge to the UserToken entity by id.
+func (m *UserMutation) SetTokenID(id int) {
+ m.token = &id
+}
+
+// ClearToken clears the "token" edge to the UserToken entity.
+func (m *UserMutation) ClearToken() {
+ m.clearedtoken = true
+}
+
+// TokenCleared reports if the "token" edge to the UserToken entity was cleared.
+func (m *UserMutation) TokenCleared() bool {
+ return m.clearedtoken
+}
+
+// TokenID returns the "token" edge ID in the mutation.
+func (m *UserMutation) TokenID() (id int, exists bool) {
+ if m.token != nil {
+ return *m.token, true
+ }
+ return
+}
+
+// TokenIDs returns the "token" edge IDs in the mutation.
+// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
+// TokenID instead. It exists only for internal usage by the builders.
+func (m *UserMutation) TokenIDs() (ids []int) {
+ if id := m.token; id != nil {
+ ids = append(ids, *id)
+ }
+ return
+}
+
+// ResetToken resets all changes to the "token" edge.
+func (m *UserMutation) ResetToken() {
+ m.token = nil
+ m.clearedtoken = false
+}
+
+// Where appends a list predicates to the UserMutation builder.
+func (m *UserMutation) Where(ps ...predicate.User) {
+ m.predicates = append(m.predicates, ps...)
+}
+
+// WhereP appends storage-level predicates to the UserMutation builder. Using this method,
+// users can use type-assertion to append predicates that do not depend on any generated package.
+func (m *UserMutation) WhereP(ps ...func(*sql.Selector)) {
+ p := make([]predicate.User, len(ps))
+ for i := range ps {
+ p[i] = ps[i]
+ }
+ m.Where(p...)
+}
+
+// Op returns the operation name.
+func (m *UserMutation) Op() Op {
+ return m.op
+}
+
+// SetOp allows setting the mutation operation.
+func (m *UserMutation) SetOp(op Op) {
+ m.op = op
+}
+
+// Type returns the node type of this mutation (User).
+func (m *UserMutation) Type() string {
+ return m.typ
+}
+
+// Fields returns all fields that were changed during this mutation. Note that in
+// order to get all numeric fields that were incremented/decremented, call
+// AddedFields().
+func (m *UserMutation) Fields() []string {
+ fields := make([]string, 0, 6)
+ if m.email != nil {
+ fields = append(fields, user.FieldEmail)
+ }
+ if m.password != nil {
+ fields = append(fields, user.FieldPassword)
+ }
+ if m.salt != nil {
+ fields = append(fields, user.FieldSalt)
+ }
+ if m.reg_ip != nil {
+ fields = append(fields, user.FieldRegIP)
+ }
+ if m.state != nil {
+ fields = append(fields, user.FieldState)
+ }
+ if m.reg_time != nil {
+ fields = append(fields, user.FieldRegTime)
+ }
+ return fields
+}
+
+// Field returns the value of a field with the given name. The second boolean
+// return value indicates that this field was not set, or was not defined in the
+// schema.
+func (m *UserMutation) Field(name string) (ent.Value, bool) {
+ switch name {
+ case user.FieldEmail:
+ return m.Email()
+ case user.FieldPassword:
+ return m.Password()
+ case user.FieldSalt:
+ return m.Salt()
+ case user.FieldRegIP:
+ return m.RegIP()
+ case user.FieldState:
+ return m.State()
+ case user.FieldRegTime:
+ return m.RegTime()
+ }
+ return nil, false
+}
+
+// OldField returns the old value of the field from the database. An error is
+// returned if the mutation operation is not UpdateOne, or the query to the
+// database failed.
+func (m *UserMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
+ switch name {
+ case user.FieldEmail:
+ return m.OldEmail(ctx)
+ case user.FieldPassword:
+ return m.OldPassword(ctx)
+ case user.FieldSalt:
+ return m.OldSalt(ctx)
+ case user.FieldRegIP:
+ return m.OldRegIP(ctx)
+ case user.FieldState:
+ return m.OldState(ctx)
+ case user.FieldRegTime:
+ return m.OldRegTime(ctx)
+ }
+ return nil, fmt.Errorf("unknown User field %s", name)
+}
+
+// SetField sets the value of a field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *UserMutation) SetField(name string, value ent.Value) error {
+ switch name {
+ case user.FieldEmail:
+ v, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetEmail(v)
+ return nil
+ case user.FieldPassword:
+ v, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetPassword(v)
+ return nil
+ case user.FieldSalt:
+ v, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetSalt(v)
+ return nil
+ case user.FieldRegIP:
+ v, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetRegIP(v)
+ return nil
+ case user.FieldState:
+ v, ok := value.(int)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetState(v)
+ return nil
+ case user.FieldRegTime:
+ v, ok := value.(int64)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetRegTime(v)
+ return nil
+ }
+ return fmt.Errorf("unknown User field %s", name)
+}
+
+// AddedFields returns all numeric fields that were incremented/decremented during
+// this mutation.
+func (m *UserMutation) AddedFields() []string {
+ var fields []string
+ if m.addstate != nil {
+ fields = append(fields, user.FieldState)
+ }
+ if m.addreg_time != nil {
+ fields = append(fields, user.FieldRegTime)
+ }
+ return fields
+}
+
+// AddedField returns the numeric value that was incremented/decremented on a field
+// with the given name. The second boolean return value indicates that this field
+// was not set, or was not defined in the schema.
+func (m *UserMutation) AddedField(name string) (ent.Value, bool) {
+ switch name {
+ case user.FieldState:
+ return m.AddedState()
+ case user.FieldRegTime:
+ return m.AddedRegTime()
+ }
+ return nil, false
+}
+
+// AddField adds the value to the field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *UserMutation) AddField(name string, value ent.Value) error {
+ switch name {
+ case user.FieldState:
+ v, ok := value.(int)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.AddState(v)
+ return nil
+ case user.FieldRegTime:
+ v, ok := value.(int64)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.AddRegTime(v)
+ return nil
+ }
+ return fmt.Errorf("unknown User numeric field %s", name)
+}
+
+// ClearedFields returns all nullable fields that were cleared during this
+// mutation.
+func (m *UserMutation) ClearedFields() []string {
+ return nil
+}
+
+// FieldCleared returns a boolean indicating if a field with the given name was
+// cleared in this mutation.
+func (m *UserMutation) FieldCleared(name string) bool {
+ _, ok := m.clearedFields[name]
+ return ok
+}
+
+// ClearField clears the value of the field with the given name. It returns an
+// error if the field is not defined in the schema.
+func (m *UserMutation) ClearField(name string) error {
+ return fmt.Errorf("unknown User nullable field %s", name)
+}
+
+// ResetField resets all changes in the mutation for the field with the given name.
+// It returns an error if the field is not defined in the schema.
+func (m *UserMutation) ResetField(name string) error {
+ switch name {
+ case user.FieldEmail:
+ m.ResetEmail()
+ return nil
+ case user.FieldPassword:
+ m.ResetPassword()
+ return nil
+ case user.FieldSalt:
+ m.ResetSalt()
+ return nil
+ case user.FieldRegIP:
+ m.ResetRegIP()
+ return nil
+ case user.FieldState:
+ m.ResetState()
+ return nil
+ case user.FieldRegTime:
+ m.ResetRegTime()
+ return nil
+ }
+ return fmt.Errorf("unknown User field %s", name)
+}
+
+// AddedEdges returns all edge names that were set/added in this mutation.
+func (m *UserMutation) AddedEdges() []string {
+ edges := make([]string, 0, 3)
+ if m.created_texture != nil {
+ edges = append(edges, user.EdgeCreatedTexture)
+ }
+ if m.profile != nil {
+ edges = append(edges, user.EdgeProfile)
+ }
+ if m.token != nil {
+ edges = append(edges, user.EdgeToken)
+ }
+ return edges
+}
+
+// AddedIDs returns all IDs (to other nodes) that were added for the given edge
+// name in this mutation.
+func (m *UserMutation) AddedIDs(name string) []ent.Value {
+ switch name {
+ case user.EdgeCreatedTexture:
+ ids := make([]ent.Value, 0, len(m.created_texture))
+ for id := range m.created_texture {
+ ids = append(ids, id)
+ }
+ return ids
+ case user.EdgeProfile:
+ if id := m.profile; id != nil {
+ return []ent.Value{*id}
+ }
+ case user.EdgeToken:
+ if id := m.token; id != nil {
+ return []ent.Value{*id}
+ }
+ }
+ return nil
+}
+
+// RemovedEdges returns all edge names that were removed in this mutation.
+func (m *UserMutation) RemovedEdges() []string {
+ edges := make([]string, 0, 3)
+ if m.removedcreated_texture != nil {
+ edges = append(edges, user.EdgeCreatedTexture)
+ }
+ return edges
+}
+
+// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
+// the given name in this mutation.
+func (m *UserMutation) RemovedIDs(name string) []ent.Value {
+ switch name {
+ case user.EdgeCreatedTexture:
+ ids := make([]ent.Value, 0, len(m.removedcreated_texture))
+ for id := range m.removedcreated_texture {
+ ids = append(ids, id)
+ }
+ return ids
+ }
+ return nil
+}
+
+// ClearedEdges returns all edge names that were cleared in this mutation.
+func (m *UserMutation) ClearedEdges() []string {
+ edges := make([]string, 0, 3)
+ if m.clearedcreated_texture {
+ edges = append(edges, user.EdgeCreatedTexture)
+ }
+ if m.clearedprofile {
+ edges = append(edges, user.EdgeProfile)
+ }
+ if m.clearedtoken {
+ edges = append(edges, user.EdgeToken)
+ }
+ return edges
+}
+
+// EdgeCleared returns a boolean which indicates if the edge with the given name
+// was cleared in this mutation.
+func (m *UserMutation) EdgeCleared(name string) bool {
+ switch name {
+ case user.EdgeCreatedTexture:
+ return m.clearedcreated_texture
+ case user.EdgeProfile:
+ return m.clearedprofile
+ case user.EdgeToken:
+ return m.clearedtoken
+ }
+ return false
+}
+
+// ClearEdge clears the value of the edge with the given name. It returns an error
+// if that edge is not defined in the schema.
+func (m *UserMutation) ClearEdge(name string) error {
+ switch name {
+ case user.EdgeProfile:
+ m.ClearProfile()
+ return nil
+ case user.EdgeToken:
+ m.ClearToken()
+ return nil
+ }
+ return fmt.Errorf("unknown User unique edge %s", name)
+}
+
+// ResetEdge resets all changes to the edge with the given name in this mutation.
+// It returns an error if the edge is not defined in the schema.
+func (m *UserMutation) ResetEdge(name string) error {
+ switch name {
+ case user.EdgeCreatedTexture:
+ m.ResetCreatedTexture()
+ return nil
+ case user.EdgeProfile:
+ m.ResetProfile()
+ return nil
+ case user.EdgeToken:
+ m.ResetToken()
+ return nil
+ }
+ return fmt.Errorf("unknown User edge %s", name)
+}
+
+// UserProfileMutation represents an operation that mutates the UserProfile nodes in the graph.
+type UserProfileMutation struct {
+ config
+ op Op
+ typ string
+ id *int
+ name *string
+ uuid *string
+ clearedFields map[string]struct{}
+ user *int
+ cleareduser bool
+ texture map[int]struct{}
+ removedtexture map[int]struct{}
+ clearedtexture bool
+ usertexture map[int]struct{}
+ removedusertexture map[int]struct{}
+ clearedusertexture bool
+ done bool
+ oldValue func(context.Context) (*UserProfile, error)
+ predicates []predicate.UserProfile
+}
+
+var _ ent.Mutation = (*UserProfileMutation)(nil)
+
+// userprofileOption allows management of the mutation configuration using functional options.
+type userprofileOption func(*UserProfileMutation)
+
+// newUserProfileMutation creates new mutation for the UserProfile entity.
+func newUserProfileMutation(c config, op Op, opts ...userprofileOption) *UserProfileMutation {
+ m := &UserProfileMutation{
+ config: c,
+ op: op,
+ typ: TypeUserProfile,
+ clearedFields: make(map[string]struct{}),
+ }
+ for _, opt := range opts {
+ opt(m)
+ }
+ return m
+}
+
+// withUserProfileID sets the ID field of the mutation.
+func withUserProfileID(id int) userprofileOption {
+ return func(m *UserProfileMutation) {
+ var (
+ err error
+ once sync.Once
+ value *UserProfile
+ )
+ m.oldValue = func(ctx context.Context) (*UserProfile, error) {
+ once.Do(func() {
+ if m.done {
+ err = errors.New("querying old values post mutation is not allowed")
+ } else {
+ value, err = m.Client().UserProfile.Get(ctx, id)
+ }
+ })
+ return value, err
+ }
+ m.id = &id
+ }
+}
+
+// withUserProfile sets the old UserProfile of the mutation.
+func withUserProfile(node *UserProfile) userprofileOption {
+ return func(m *UserProfileMutation) {
+ m.oldValue = func(context.Context) (*UserProfile, error) {
+ return node, nil
+ }
+ m.id = &node.ID
+ }
+}
+
+// Client returns a new `ent.Client` from the mutation. If the mutation was
+// executed in a transaction (ent.Tx), a transactional client is returned.
+func (m UserProfileMutation) Client() *Client {
+ client := &Client{config: m.config}
+ client.init()
+ return client
+}
+
+// Tx returns an `ent.Tx` for mutations that were executed in transactions;
+// it returns an error otherwise.
+func (m UserProfileMutation) Tx() (*Tx, error) {
+ if _, ok := m.driver.(*txDriver); !ok {
+ return nil, errors.New("ent: mutation is not running in a transaction")
+ }
+ tx := &Tx{config: m.config}
+ tx.init()
+ return tx, nil
+}
+
+// ID returns the ID value in the mutation. Note that the ID is only available
+// if it was provided to the builder or after it was returned from the database.
+func (m *UserProfileMutation) ID() (id int, exists bool) {
+ if m.id == nil {
+ return
+ }
+ return *m.id, true
+}
+
+// IDs queries the database and returns the entity ids that match the mutation's predicate.
+// That means, if the mutation is applied within a transaction with an isolation level such
+// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
+// or updated by the mutation.
+func (m *UserProfileMutation) IDs(ctx context.Context) ([]int, error) {
+ switch {
+ case m.op.Is(OpUpdateOne | OpDeleteOne):
+ id, exists := m.ID()
+ if exists {
+ return []int{id}, nil
+ }
+ fallthrough
+ case m.op.Is(OpUpdate | OpDelete):
+ return m.Client().UserProfile.Query().Where(m.predicates...).IDs(ctx)
+ default:
+ return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
+ }
+}
+
+// SetName sets the "name" field.
+func (m *UserProfileMutation) SetName(s string) {
+ m.name = &s
+}
+
+// Name returns the value of the "name" field in the mutation.
+func (m *UserProfileMutation) Name() (r string, exists bool) {
+ v := m.name
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldName returns the old "name" field's value of the UserProfile entity.
+// If the UserProfile object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserProfileMutation) OldName(ctx context.Context) (v string, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldName is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldName requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldName: %w", err)
+ }
+ return oldValue.Name, nil
+}
+
+// ResetName resets all changes to the "name" field.
+func (m *UserProfileMutation) ResetName() {
+ m.name = nil
+}
+
+// SetUUID sets the "uuid" field.
+func (m *UserProfileMutation) SetUUID(s string) {
+ m.uuid = &s
+}
+
+// UUID returns the value of the "uuid" field in the mutation.
+func (m *UserProfileMutation) UUID() (r string, exists bool) {
+ v := m.uuid
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldUUID returns the old "uuid" field's value of the UserProfile entity.
+// If the UserProfile object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserProfileMutation) OldUUID(ctx context.Context) (v string, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldUUID is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldUUID requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldUUID: %w", err)
+ }
+ return oldValue.UUID, nil
+}
+
+// ResetUUID resets all changes to the "uuid" field.
+func (m *UserProfileMutation) ResetUUID() {
+ m.uuid = nil
+}
+
+// SetUserID sets the "user" edge to the User entity by id.
+func (m *UserProfileMutation) SetUserID(id int) {
+ m.user = &id
+}
+
+// ClearUser clears the "user" edge to the User entity.
+func (m *UserProfileMutation) ClearUser() {
+ m.cleareduser = true
+}
+
+// UserCleared reports if the "user" edge to the User entity was cleared.
+func (m *UserProfileMutation) UserCleared() bool {
+ return m.cleareduser
+}
+
+// UserID returns the "user" edge ID in the mutation.
+func (m *UserProfileMutation) UserID() (id int, exists bool) {
+ if m.user != nil {
+ return *m.user, true
+ }
+ return
+}
+
+// UserIDs returns the "user" edge IDs in the mutation.
+// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
+// UserID instead. It exists only for internal usage by the builders.
+func (m *UserProfileMutation) UserIDs() (ids []int) {
+ if id := m.user; id != nil {
+ ids = append(ids, *id)
+ }
+ return
+}
+
+// ResetUser resets all changes to the "user" edge.
+func (m *UserProfileMutation) ResetUser() {
+ m.user = nil
+ m.cleareduser = false
+}
+
+// AddTextureIDs adds the "texture" edge to the Texture entity by ids.
+func (m *UserProfileMutation) AddTextureIDs(ids ...int) {
+ if m.texture == nil {
+ m.texture = make(map[int]struct{})
+ }
+ for i := range ids {
+ m.texture[ids[i]] = struct{}{}
+ }
+}
+
+// ClearTexture clears the "texture" edge to the Texture entity.
+func (m *UserProfileMutation) ClearTexture() {
+ m.clearedtexture = true
+}
+
+// TextureCleared reports if the "texture" edge to the Texture entity was cleared.
+func (m *UserProfileMutation) TextureCleared() bool {
+ return m.clearedtexture
+}
+
+// RemoveTextureIDs removes the "texture" edge to the Texture entity by IDs.
+func (m *UserProfileMutation) RemoveTextureIDs(ids ...int) {
+ if m.removedtexture == nil {
+ m.removedtexture = make(map[int]struct{})
+ }
+ for i := range ids {
+ delete(m.texture, ids[i])
+ m.removedtexture[ids[i]] = struct{}{}
+ }
+}
+
+// RemovedTexture returns the removed IDs of the "texture" edge to the Texture entity.
+func (m *UserProfileMutation) RemovedTextureIDs() (ids []int) {
+ for id := range m.removedtexture {
+ ids = append(ids, id)
+ }
+ return
+}
+
+// TextureIDs returns the "texture" edge IDs in the mutation.
+func (m *UserProfileMutation) TextureIDs() (ids []int) {
+ for id := range m.texture {
+ ids = append(ids, id)
+ }
+ return
+}
+
+// ResetTexture resets all changes to the "texture" edge.
+func (m *UserProfileMutation) ResetTexture() {
+ m.texture = nil
+ m.clearedtexture = false
+ m.removedtexture = nil
+}
+
+// AddUsertextureIDs adds the "usertexture" edge to the UserTexture entity by ids.
+func (m *UserProfileMutation) AddUsertextureIDs(ids ...int) {
+ if m.usertexture == nil {
+ m.usertexture = make(map[int]struct{})
+ }
+ for i := range ids {
+ m.usertexture[ids[i]] = struct{}{}
+ }
+}
+
+// ClearUsertexture clears the "usertexture" edge to the UserTexture entity.
+func (m *UserProfileMutation) ClearUsertexture() {
+ m.clearedusertexture = true
+}
+
+// UsertextureCleared reports if the "usertexture" edge to the UserTexture entity was cleared.
+func (m *UserProfileMutation) UsertextureCleared() bool {
+ return m.clearedusertexture
+}
+
+// RemoveUsertextureIDs removes the "usertexture" edge to the UserTexture entity by IDs.
+func (m *UserProfileMutation) RemoveUsertextureIDs(ids ...int) {
+ if m.removedusertexture == nil {
+ m.removedusertexture = make(map[int]struct{})
+ }
+ for i := range ids {
+ delete(m.usertexture, ids[i])
+ m.removedusertexture[ids[i]] = struct{}{}
+ }
+}
+
+// RemovedUsertexture returns the removed IDs of the "usertexture" edge to the UserTexture entity.
+func (m *UserProfileMutation) RemovedUsertextureIDs() (ids []int) {
+ for id := range m.removedusertexture {
+ ids = append(ids, id)
+ }
+ return
+}
+
+// UsertextureIDs returns the "usertexture" edge IDs in the mutation.
+func (m *UserProfileMutation) UsertextureIDs() (ids []int) {
+ for id := range m.usertexture {
+ ids = append(ids, id)
+ }
+ return
+}
+
+// ResetUsertexture resets all changes to the "usertexture" edge.
+func (m *UserProfileMutation) ResetUsertexture() {
+ m.usertexture = nil
+ m.clearedusertexture = false
+ m.removedusertexture = nil
+}
+
+// Where appends a list predicates to the UserProfileMutation builder.
+func (m *UserProfileMutation) Where(ps ...predicate.UserProfile) {
+ m.predicates = append(m.predicates, ps...)
+}
+
+// WhereP appends storage-level predicates to the UserProfileMutation builder. Using this method,
+// users can use type-assertion to append predicates that do not depend on any generated package.
+func (m *UserProfileMutation) WhereP(ps ...func(*sql.Selector)) {
+ p := make([]predicate.UserProfile, len(ps))
+ for i := range ps {
+ p[i] = ps[i]
+ }
+ m.Where(p...)
+}
+
+// Op returns the operation name.
+func (m *UserProfileMutation) Op() Op {
+ return m.op
+}
+
+// SetOp allows setting the mutation operation.
+func (m *UserProfileMutation) SetOp(op Op) {
+ m.op = op
+}
+
+// Type returns the node type of this mutation (UserProfile).
+func (m *UserProfileMutation) Type() string {
+ return m.typ
+}
+
+// Fields returns all fields that were changed during this mutation. Note that in
+// order to get all numeric fields that were incremented/decremented, call
+// AddedFields().
+func (m *UserProfileMutation) Fields() []string {
+ fields := make([]string, 0, 2)
+ if m.name != nil {
+ fields = append(fields, userprofile.FieldName)
+ }
+ if m.uuid != nil {
+ fields = append(fields, userprofile.FieldUUID)
+ }
+ return fields
+}
+
+// Field returns the value of a field with the given name. The second boolean
+// return value indicates that this field was not set, or was not defined in the
+// schema.
+func (m *UserProfileMutation) Field(name string) (ent.Value, bool) {
+ switch name {
+ case userprofile.FieldName:
+ return m.Name()
+ case userprofile.FieldUUID:
+ return m.UUID()
+ }
+ return nil, false
+}
+
+// OldField returns the old value of the field from the database. An error is
+// returned if the mutation operation is not UpdateOne, or the query to the
+// database failed.
+func (m *UserProfileMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
+ switch name {
+ case userprofile.FieldName:
+ return m.OldName(ctx)
+ case userprofile.FieldUUID:
+ return m.OldUUID(ctx)
+ }
+ return nil, fmt.Errorf("unknown UserProfile field %s", name)
+}
+
+// SetField sets the value of a field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *UserProfileMutation) SetField(name string, value ent.Value) error {
+ switch name {
+ case userprofile.FieldName:
+ v, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetName(v)
+ return nil
+ case userprofile.FieldUUID:
+ v, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetUUID(v)
+ return nil
+ }
+ return fmt.Errorf("unknown UserProfile field %s", name)
+}
+
+// AddedFields returns all numeric fields that were incremented/decremented during
+// this mutation.
+func (m *UserProfileMutation) AddedFields() []string {
+ return nil
+}
+
+// AddedField returns the numeric value that was incremented/decremented on a field
+// with the given name. The second boolean return value indicates that this field
+// was not set, or was not defined in the schema.
+func (m *UserProfileMutation) AddedField(name string) (ent.Value, bool) {
+ return nil, false
+}
+
+// AddField adds the value to the field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *UserProfileMutation) AddField(name string, value ent.Value) error {
+ switch name {
+ }
+ return fmt.Errorf("unknown UserProfile numeric field %s", name)
+}
+
+// ClearedFields returns all nullable fields that were cleared during this
+// mutation.
+func (m *UserProfileMutation) ClearedFields() []string {
+ return nil
+}
+
+// FieldCleared returns a boolean indicating if a field with the given name was
+// cleared in this mutation.
+func (m *UserProfileMutation) FieldCleared(name string) bool {
+ _, ok := m.clearedFields[name]
+ return ok
+}
+
+// ClearField clears the value of the field with the given name. It returns an
+// error if the field is not defined in the schema.
+func (m *UserProfileMutation) ClearField(name string) error {
+ return fmt.Errorf("unknown UserProfile nullable field %s", name)
+}
+
+// ResetField resets all changes in the mutation for the field with the given name.
+// It returns an error if the field is not defined in the schema.
+func (m *UserProfileMutation) ResetField(name string) error {
+ switch name {
+ case userprofile.FieldName:
+ m.ResetName()
+ return nil
+ case userprofile.FieldUUID:
+ m.ResetUUID()
+ return nil
+ }
+ return fmt.Errorf("unknown UserProfile field %s", name)
+}
+
+// AddedEdges returns all edge names that were set/added in this mutation.
+func (m *UserProfileMutation) AddedEdges() []string {
+ edges := make([]string, 0, 3)
+ if m.user != nil {
+ edges = append(edges, userprofile.EdgeUser)
+ }
+ if m.texture != nil {
+ edges = append(edges, userprofile.EdgeTexture)
+ }
+ if m.usertexture != nil {
+ edges = append(edges, userprofile.EdgeUsertexture)
+ }
+ return edges
+}
+
+// AddedIDs returns all IDs (to other nodes) that were added for the given edge
+// name in this mutation.
+func (m *UserProfileMutation) AddedIDs(name string) []ent.Value {
+ switch name {
+ case userprofile.EdgeUser:
+ if id := m.user; id != nil {
+ return []ent.Value{*id}
+ }
+ case userprofile.EdgeTexture:
+ ids := make([]ent.Value, 0, len(m.texture))
+ for id := range m.texture {
+ ids = append(ids, id)
+ }
+ return ids
+ case userprofile.EdgeUsertexture:
+ ids := make([]ent.Value, 0, len(m.usertexture))
+ for id := range m.usertexture {
+ ids = append(ids, id)
+ }
+ return ids
+ }
+ return nil
+}
+
+// RemovedEdges returns all edge names that were removed in this mutation.
+func (m *UserProfileMutation) RemovedEdges() []string {
+ edges := make([]string, 0, 3)
+ if m.removedtexture != nil {
+ edges = append(edges, userprofile.EdgeTexture)
+ }
+ if m.removedusertexture != nil {
+ edges = append(edges, userprofile.EdgeUsertexture)
+ }
+ return edges
+}
+
+// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
+// the given name in this mutation.
+func (m *UserProfileMutation) RemovedIDs(name string) []ent.Value {
+ switch name {
+ case userprofile.EdgeTexture:
+ ids := make([]ent.Value, 0, len(m.removedtexture))
+ for id := range m.removedtexture {
+ ids = append(ids, id)
+ }
+ return ids
+ case userprofile.EdgeUsertexture:
+ ids := make([]ent.Value, 0, len(m.removedusertexture))
+ for id := range m.removedusertexture {
+ ids = append(ids, id)
+ }
+ return ids
+ }
+ return nil
+}
+
+// ClearedEdges returns all edge names that were cleared in this mutation.
+func (m *UserProfileMutation) ClearedEdges() []string {
+ edges := make([]string, 0, 3)
+ if m.cleareduser {
+ edges = append(edges, userprofile.EdgeUser)
+ }
+ if m.clearedtexture {
+ edges = append(edges, userprofile.EdgeTexture)
+ }
+ if m.clearedusertexture {
+ edges = append(edges, userprofile.EdgeUsertexture)
+ }
+ return edges
+}
+
+// EdgeCleared returns a boolean which indicates if the edge with the given name
+// was cleared in this mutation.
+func (m *UserProfileMutation) EdgeCleared(name string) bool {
+ switch name {
+ case userprofile.EdgeUser:
+ return m.cleareduser
+ case userprofile.EdgeTexture:
+ return m.clearedtexture
+ case userprofile.EdgeUsertexture:
+ return m.clearedusertexture
+ }
+ return false
+}
+
+// ClearEdge clears the value of the edge with the given name. It returns an error
+// if that edge is not defined in the schema.
+func (m *UserProfileMutation) ClearEdge(name string) error {
+ switch name {
+ case userprofile.EdgeUser:
+ m.ClearUser()
+ return nil
+ }
+ return fmt.Errorf("unknown UserProfile unique edge %s", name)
+}
+
+// ResetEdge resets all changes to the edge with the given name in this mutation.
+// It returns an error if the edge is not defined in the schema.
+func (m *UserProfileMutation) ResetEdge(name string) error {
+ switch name {
+ case userprofile.EdgeUser:
+ m.ResetUser()
+ return nil
+ case userprofile.EdgeTexture:
+ m.ResetTexture()
+ return nil
+ case userprofile.EdgeUsertexture:
+ m.ResetUsertexture()
+ return nil
+ }
+ return fmt.Errorf("unknown UserProfile edge %s", name)
+}
+
+// UserTextureMutation represents an operation that mutates the UserTexture nodes in the graph.
+type UserTextureMutation struct {
+ config
+ op Op
+ typ string
+ id *int
+ _type *string
+ variant *string
+ clearedFields map[string]struct{}
+ user_profile *int
+ cleareduser_profile bool
+ texture *int
+ clearedtexture bool
+ done bool
+ oldValue func(context.Context) (*UserTexture, error)
+ predicates []predicate.UserTexture
+}
+
+var _ ent.Mutation = (*UserTextureMutation)(nil)
+
+// usertextureOption allows management of the mutation configuration using functional options.
+type usertextureOption func(*UserTextureMutation)
+
+// newUserTextureMutation creates new mutation for the UserTexture entity.
+func newUserTextureMutation(c config, op Op, opts ...usertextureOption) *UserTextureMutation {
+ m := &UserTextureMutation{
+ config: c,
+ op: op,
+ typ: TypeUserTexture,
+ clearedFields: make(map[string]struct{}),
+ }
+ for _, opt := range opts {
+ opt(m)
+ }
+ return m
+}
+
+// withUserTextureID sets the ID field of the mutation.
+func withUserTextureID(id int) usertextureOption {
+ return func(m *UserTextureMutation) {
+ var (
+ err error
+ once sync.Once
+ value *UserTexture
+ )
+ m.oldValue = func(ctx context.Context) (*UserTexture, error) {
+ once.Do(func() {
+ if m.done {
+ err = errors.New("querying old values post mutation is not allowed")
+ } else {
+ value, err = m.Client().UserTexture.Get(ctx, id)
+ }
+ })
+ return value, err
+ }
+ m.id = &id
+ }
+}
+
+// withUserTexture sets the old UserTexture of the mutation.
+func withUserTexture(node *UserTexture) usertextureOption {
+ return func(m *UserTextureMutation) {
+ m.oldValue = func(context.Context) (*UserTexture, error) {
+ return node, nil
+ }
+ m.id = &node.ID
+ }
+}
+
+// Client returns a new `ent.Client` from the mutation. If the mutation was
+// executed in a transaction (ent.Tx), a transactional client is returned.
+func (m UserTextureMutation) Client() *Client {
+ client := &Client{config: m.config}
+ client.init()
+ return client
+}
+
+// Tx returns an `ent.Tx` for mutations that were executed in transactions;
+// it returns an error otherwise.
+func (m UserTextureMutation) Tx() (*Tx, error) {
+ if _, ok := m.driver.(*txDriver); !ok {
+ return nil, errors.New("ent: mutation is not running in a transaction")
+ }
+ tx := &Tx{config: m.config}
+ tx.init()
+ return tx, nil
+}
+
+// ID returns the ID value in the mutation. Note that the ID is only available
+// if it was provided to the builder or after it was returned from the database.
+func (m *UserTextureMutation) ID() (id int, exists bool) {
+ if m.id == nil {
+ return
+ }
+ return *m.id, true
+}
+
+// IDs queries the database and returns the entity ids that match the mutation's predicate.
+// That means, if the mutation is applied within a transaction with an isolation level such
+// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
+// or updated by the mutation.
+func (m *UserTextureMutation) IDs(ctx context.Context) ([]int, error) {
+ switch {
+ case m.op.Is(OpUpdateOne | OpDeleteOne):
+ id, exists := m.ID()
+ if exists {
+ return []int{id}, nil
+ }
+ fallthrough
+ case m.op.Is(OpUpdate | OpDelete):
+ return m.Client().UserTexture.Query().Where(m.predicates...).IDs(ctx)
+ default:
+ return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
+ }
+}
+
+// SetUserProfileID sets the "user_profile_id" field.
+func (m *UserTextureMutation) SetUserProfileID(i int) {
+ m.user_profile = &i
+}
+
+// UserProfileID returns the value of the "user_profile_id" field in the mutation.
+func (m *UserTextureMutation) UserProfileID() (r int, exists bool) {
+ v := m.user_profile
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldUserProfileID returns the old "user_profile_id" field's value of the UserTexture entity.
+// If the UserTexture object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserTextureMutation) OldUserProfileID(ctx context.Context) (v int, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldUserProfileID is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldUserProfileID requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldUserProfileID: %w", err)
+ }
+ return oldValue.UserProfileID, nil
+}
+
+// ResetUserProfileID resets all changes to the "user_profile_id" field.
+func (m *UserTextureMutation) ResetUserProfileID() {
+ m.user_profile = nil
+}
+
+// SetTextureID sets the "texture_id" field.
+func (m *UserTextureMutation) SetTextureID(i int) {
+ m.texture = &i
+}
+
+// TextureID returns the value of the "texture_id" field in the mutation.
+func (m *UserTextureMutation) TextureID() (r int, exists bool) {
+ v := m.texture
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldTextureID returns the old "texture_id" field's value of the UserTexture entity.
+// If the UserTexture object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserTextureMutation) OldTextureID(ctx context.Context) (v int, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldTextureID is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldTextureID requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldTextureID: %w", err)
+ }
+ return oldValue.TextureID, nil
+}
+
+// ResetTextureID resets all changes to the "texture_id" field.
+func (m *UserTextureMutation) ResetTextureID() {
+ m.texture = nil
+}
+
+// SetType sets the "type" field.
+func (m *UserTextureMutation) SetType(s string) {
+ m._type = &s
+}
+
+// GetType returns the value of the "type" field in the mutation.
+func (m *UserTextureMutation) GetType() (r string, exists bool) {
+ v := m._type
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldType returns the old "type" field's value of the UserTexture entity.
+// If the UserTexture object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserTextureMutation) OldType(ctx context.Context) (v string, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldType is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldType requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldType: %w", err)
+ }
+ return oldValue.Type, nil
+}
+
+// ResetType resets all changes to the "type" field.
+func (m *UserTextureMutation) ResetType() {
+ m._type = nil
+}
+
+// SetVariant sets the "variant" field.
+func (m *UserTextureMutation) SetVariant(s string) {
+ m.variant = &s
+}
+
+// Variant returns the value of the "variant" field in the mutation.
+func (m *UserTextureMutation) Variant() (r string, exists bool) {
+ v := m.variant
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldVariant returns the old "variant" field's value of the UserTexture entity.
+// If the UserTexture object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserTextureMutation) OldVariant(ctx context.Context) (v string, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldVariant is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldVariant requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldVariant: %w", err)
+ }
+ return oldValue.Variant, nil
+}
+
+// ResetVariant resets all changes to the "variant" field.
+func (m *UserTextureMutation) ResetVariant() {
+ m.variant = nil
+}
+
+// ClearUserProfile clears the "user_profile" edge to the UserProfile entity.
+func (m *UserTextureMutation) ClearUserProfile() {
+ m.cleareduser_profile = true
+}
+
+// UserProfileCleared reports if the "user_profile" edge to the UserProfile entity was cleared.
+func (m *UserTextureMutation) UserProfileCleared() bool {
+ return m.cleareduser_profile
+}
+
+// UserProfileIDs returns the "user_profile" edge IDs in the mutation.
+// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
+// UserProfileID instead. It exists only for internal usage by the builders.
+func (m *UserTextureMutation) UserProfileIDs() (ids []int) {
+ if id := m.user_profile; id != nil {
+ ids = append(ids, *id)
+ }
+ return
+}
+
+// ResetUserProfile resets all changes to the "user_profile" edge.
+func (m *UserTextureMutation) ResetUserProfile() {
+ m.user_profile = nil
+ m.cleareduser_profile = false
+}
+
+// ClearTexture clears the "texture" edge to the Texture entity.
+func (m *UserTextureMutation) ClearTexture() {
+ m.clearedtexture = true
+}
+
+// TextureCleared reports if the "texture" edge to the Texture entity was cleared.
+func (m *UserTextureMutation) TextureCleared() bool {
+ return m.clearedtexture
+}
+
+// TextureIDs returns the "texture" edge IDs in the mutation.
+// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
+// TextureID instead. It exists only for internal usage by the builders.
+func (m *UserTextureMutation) TextureIDs() (ids []int) {
+ if id := m.texture; id != nil {
+ ids = append(ids, *id)
+ }
+ return
+}
+
+// ResetTexture resets all changes to the "texture" edge.
+func (m *UserTextureMutation) ResetTexture() {
+ m.texture = nil
+ m.clearedtexture = false
+}
+
+// Where appends a list predicates to the UserTextureMutation builder.
+func (m *UserTextureMutation) Where(ps ...predicate.UserTexture) {
+ m.predicates = append(m.predicates, ps...)
+}
+
+// WhereP appends storage-level predicates to the UserTextureMutation builder. Using this method,
+// users can use type-assertion to append predicates that do not depend on any generated package.
+func (m *UserTextureMutation) WhereP(ps ...func(*sql.Selector)) {
+ p := make([]predicate.UserTexture, len(ps))
+ for i := range ps {
+ p[i] = ps[i]
+ }
+ m.Where(p...)
+}
+
+// Op returns the operation name.
+func (m *UserTextureMutation) Op() Op {
+ return m.op
+}
+
+// SetOp allows setting the mutation operation.
+func (m *UserTextureMutation) SetOp(op Op) {
+ m.op = op
+}
+
+// Type returns the node type of this mutation (UserTexture).
+func (m *UserTextureMutation) Type() string {
+ return m.typ
+}
+
+// Fields returns all fields that were changed during this mutation. Note that in
+// order to get all numeric fields that were incremented/decremented, call
+// AddedFields().
+func (m *UserTextureMutation) Fields() []string {
+ fields := make([]string, 0, 4)
+ if m.user_profile != nil {
+ fields = append(fields, usertexture.FieldUserProfileID)
+ }
+ if m.texture != nil {
+ fields = append(fields, usertexture.FieldTextureID)
+ }
+ if m._type != nil {
+ fields = append(fields, usertexture.FieldType)
+ }
+ if m.variant != nil {
+ fields = append(fields, usertexture.FieldVariant)
+ }
+ return fields
+}
+
+// Field returns the value of a field with the given name. The second boolean
+// return value indicates that this field was not set, or was not defined in the
+// schema.
+func (m *UserTextureMutation) Field(name string) (ent.Value, bool) {
+ switch name {
+ case usertexture.FieldUserProfileID:
+ return m.UserProfileID()
+ case usertexture.FieldTextureID:
+ return m.TextureID()
+ case usertexture.FieldType:
+ return m.GetType()
+ case usertexture.FieldVariant:
+ return m.Variant()
+ }
+ return nil, false
+}
+
+// OldField returns the old value of the field from the database. An error is
+// returned if the mutation operation is not UpdateOne, or the query to the
+// database failed.
+func (m *UserTextureMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
+ switch name {
+ case usertexture.FieldUserProfileID:
+ return m.OldUserProfileID(ctx)
+ case usertexture.FieldTextureID:
+ return m.OldTextureID(ctx)
+ case usertexture.FieldType:
+ return m.OldType(ctx)
+ case usertexture.FieldVariant:
+ return m.OldVariant(ctx)
+ }
+ return nil, fmt.Errorf("unknown UserTexture field %s", name)
+}
+
+// SetField sets the value of a field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *UserTextureMutation) SetField(name string, value ent.Value) error {
+ switch name {
+ case usertexture.FieldUserProfileID:
+ v, ok := value.(int)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetUserProfileID(v)
+ return nil
+ case usertexture.FieldTextureID:
+ v, ok := value.(int)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetTextureID(v)
+ return nil
+ case usertexture.FieldType:
+ v, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetType(v)
+ return nil
+ case usertexture.FieldVariant:
+ v, ok := value.(string)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetVariant(v)
+ return nil
+ }
+ return fmt.Errorf("unknown UserTexture field %s", name)
+}
+
+// AddedFields returns all numeric fields that were incremented/decremented during
+// this mutation.
+func (m *UserTextureMutation) AddedFields() []string {
+ var fields []string
+ return fields
+}
+
+// AddedField returns the numeric value that was incremented/decremented on a field
+// with the given name. The second boolean return value indicates that this field
+// was not set, or was not defined in the schema.
+func (m *UserTextureMutation) AddedField(name string) (ent.Value, bool) {
+ switch name {
+ }
+ return nil, false
+}
+
+// AddField adds the value to the field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *UserTextureMutation) AddField(name string, value ent.Value) error {
+ switch name {
+ }
+ return fmt.Errorf("unknown UserTexture numeric field %s", name)
+}
+
+// ClearedFields returns all nullable fields that were cleared during this
+// mutation.
+func (m *UserTextureMutation) ClearedFields() []string {
+ return nil
+}
+
+// FieldCleared returns a boolean indicating if a field with the given name was
+// cleared in this mutation.
+func (m *UserTextureMutation) FieldCleared(name string) bool {
+ _, ok := m.clearedFields[name]
+ return ok
+}
+
+// ClearField clears the value of the field with the given name. It returns an
+// error if the field is not defined in the schema.
+func (m *UserTextureMutation) ClearField(name string) error {
+ return fmt.Errorf("unknown UserTexture nullable field %s", name)
+}
+
+// ResetField resets all changes in the mutation for the field with the given name.
+// It returns an error if the field is not defined in the schema.
+func (m *UserTextureMutation) ResetField(name string) error {
+ switch name {
+ case usertexture.FieldUserProfileID:
+ m.ResetUserProfileID()
+ return nil
+ case usertexture.FieldTextureID:
+ m.ResetTextureID()
+ return nil
+ case usertexture.FieldType:
+ m.ResetType()
+ return nil
+ case usertexture.FieldVariant:
+ m.ResetVariant()
+ return nil
+ }
+ return fmt.Errorf("unknown UserTexture field %s", name)
+}
+
+// AddedEdges returns all edge names that were set/added in this mutation.
+func (m *UserTextureMutation) AddedEdges() []string {
+ edges := make([]string, 0, 2)
+ if m.user_profile != nil {
+ edges = append(edges, usertexture.EdgeUserProfile)
+ }
+ if m.texture != nil {
+ edges = append(edges, usertexture.EdgeTexture)
+ }
+ return edges
+}
+
+// AddedIDs returns all IDs (to other nodes) that were added for the given edge
+// name in this mutation.
+func (m *UserTextureMutation) AddedIDs(name string) []ent.Value {
+ switch name {
+ case usertexture.EdgeUserProfile:
+ if id := m.user_profile; id != nil {
+ return []ent.Value{*id}
+ }
+ case usertexture.EdgeTexture:
+ if id := m.texture; id != nil {
+ return []ent.Value{*id}
+ }
+ }
+ return nil
+}
+
+// RemovedEdges returns all edge names that were removed in this mutation.
+func (m *UserTextureMutation) RemovedEdges() []string {
+ edges := make([]string, 0, 2)
+ return edges
+}
+
+// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
+// the given name in this mutation.
+func (m *UserTextureMutation) RemovedIDs(name string) []ent.Value {
+ return nil
+}
+
+// ClearedEdges returns all edge names that were cleared in this mutation.
+func (m *UserTextureMutation) ClearedEdges() []string {
+ edges := make([]string, 0, 2)
+ if m.cleareduser_profile {
+ edges = append(edges, usertexture.EdgeUserProfile)
+ }
+ if m.clearedtexture {
+ edges = append(edges, usertexture.EdgeTexture)
+ }
+ return edges
+}
+
+// EdgeCleared returns a boolean which indicates if the edge with the given name
+// was cleared in this mutation.
+func (m *UserTextureMutation) EdgeCleared(name string) bool {
+ switch name {
+ case usertexture.EdgeUserProfile:
+ return m.cleareduser_profile
+ case usertexture.EdgeTexture:
+ return m.clearedtexture
+ }
+ return false
+}
+
+// ClearEdge clears the value of the edge with the given name. It returns an error
+// if that edge is not defined in the schema.
+func (m *UserTextureMutation) ClearEdge(name string) error {
+ switch name {
+ case usertexture.EdgeUserProfile:
+ m.ClearUserProfile()
+ return nil
+ case usertexture.EdgeTexture:
+ m.ClearTexture()
+ return nil
+ }
+ return fmt.Errorf("unknown UserTexture unique edge %s", name)
+}
+
+// ResetEdge resets all changes to the edge with the given name in this mutation.
+// It returns an error if the edge is not defined in the schema.
+func (m *UserTextureMutation) ResetEdge(name string) error {
+ switch name {
+ case usertexture.EdgeUserProfile:
+ m.ResetUserProfile()
+ return nil
+ case usertexture.EdgeTexture:
+ m.ResetTexture()
+ return nil
+ }
+ return fmt.Errorf("unknown UserTexture edge %s", name)
+}
+
+// UserTokenMutation represents an operation that mutates the UserToken nodes in the graph.
+type UserTokenMutation struct {
+ config
+ op Op
+ typ string
+ id *int
+ token_id *uint64
+ addtoken_id *int64
+ clearedFields map[string]struct{}
+ user *int
+ cleareduser bool
+ done bool
+ oldValue func(context.Context) (*UserToken, error)
+ predicates []predicate.UserToken
+}
+
+var _ ent.Mutation = (*UserTokenMutation)(nil)
+
+// usertokenOption allows management of the mutation configuration using functional options.
+type usertokenOption func(*UserTokenMutation)
+
+// newUserTokenMutation creates new mutation for the UserToken entity.
+func newUserTokenMutation(c config, op Op, opts ...usertokenOption) *UserTokenMutation {
+ m := &UserTokenMutation{
+ config: c,
+ op: op,
+ typ: TypeUserToken,
+ clearedFields: make(map[string]struct{}),
+ }
+ for _, opt := range opts {
+ opt(m)
+ }
+ return m
+}
+
+// withUserTokenID sets the ID field of the mutation.
+func withUserTokenID(id int) usertokenOption {
+ return func(m *UserTokenMutation) {
+ var (
+ err error
+ once sync.Once
+ value *UserToken
+ )
+ m.oldValue = func(ctx context.Context) (*UserToken, error) {
+ once.Do(func() {
+ if m.done {
+ err = errors.New("querying old values post mutation is not allowed")
+ } else {
+ value, err = m.Client().UserToken.Get(ctx, id)
+ }
+ })
+ return value, err
+ }
+ m.id = &id
+ }
+}
+
+// withUserToken sets the old UserToken of the mutation.
+func withUserToken(node *UserToken) usertokenOption {
+ return func(m *UserTokenMutation) {
+ m.oldValue = func(context.Context) (*UserToken, error) {
+ return node, nil
+ }
+ m.id = &node.ID
+ }
+}
+
+// Client returns a new `ent.Client` from the mutation. If the mutation was
+// executed in a transaction (ent.Tx), a transactional client is returned.
+func (m UserTokenMutation) Client() *Client {
+ client := &Client{config: m.config}
+ client.init()
+ return client
+}
+
+// Tx returns an `ent.Tx` for mutations that were executed in transactions;
+// it returns an error otherwise.
+func (m UserTokenMutation) Tx() (*Tx, error) {
+ if _, ok := m.driver.(*txDriver); !ok {
+ return nil, errors.New("ent: mutation is not running in a transaction")
+ }
+ tx := &Tx{config: m.config}
+ tx.init()
+ return tx, nil
+}
+
+// ID returns the ID value in the mutation. Note that the ID is only available
+// if it was provided to the builder or after it was returned from the database.
+func (m *UserTokenMutation) ID() (id int, exists bool) {
+ if m.id == nil {
+ return
+ }
+ return *m.id, true
+}
+
+// IDs queries the database and returns the entity ids that match the mutation's predicate.
+// That means, if the mutation is applied within a transaction with an isolation level such
+// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
+// or updated by the mutation.
+func (m *UserTokenMutation) IDs(ctx context.Context) ([]int, error) {
+ switch {
+ case m.op.Is(OpUpdateOne | OpDeleteOne):
+ id, exists := m.ID()
+ if exists {
+ return []int{id}, nil
+ }
+ fallthrough
+ case m.op.Is(OpUpdate | OpDelete):
+ return m.Client().UserToken.Query().Where(m.predicates...).IDs(ctx)
+ default:
+ return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
+ }
+}
+
+// SetTokenID sets the "token_id" field.
+func (m *UserTokenMutation) SetTokenID(u uint64) {
+ m.token_id = &u
+ m.addtoken_id = nil
+}
+
+// TokenID returns the value of the "token_id" field in the mutation.
+func (m *UserTokenMutation) TokenID() (r uint64, exists bool) {
+ v := m.token_id
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// OldTokenID returns the old "token_id" field's value of the UserToken entity.
+// If the UserToken object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *UserTokenMutation) OldTokenID(ctx context.Context) (v uint64, err error) {
+ if !m.op.Is(OpUpdateOne) {
+ return v, errors.New("OldTokenID is only allowed on UpdateOne operations")
+ }
+ if m.id == nil || m.oldValue == nil {
+ return v, errors.New("OldTokenID requires an ID field in the mutation")
+ }
+ oldValue, err := m.oldValue(ctx)
+ if err != nil {
+ return v, fmt.Errorf("querying old value for OldTokenID: %w", err)
+ }
+ return oldValue.TokenID, nil
+}
+
+// AddTokenID adds u to the "token_id" field.
+func (m *UserTokenMutation) AddTokenID(u int64) {
+ if m.addtoken_id != nil {
+ *m.addtoken_id += u
+ } else {
+ m.addtoken_id = &u
+ }
+}
+
+// AddedTokenID returns the value that was added to the "token_id" field in this mutation.
+func (m *UserTokenMutation) AddedTokenID() (r int64, exists bool) {
+ v := m.addtoken_id
+ if v == nil {
+ return
+ }
+ return *v, true
+}
+
+// ResetTokenID resets all changes to the "token_id" field.
+func (m *UserTokenMutation) ResetTokenID() {
+ m.token_id = nil
+ m.addtoken_id = nil
+}
+
+// SetUserID sets the "user" edge to the User entity by id.
+func (m *UserTokenMutation) SetUserID(id int) {
+ m.user = &id
+}
+
+// ClearUser clears the "user" edge to the User entity.
+func (m *UserTokenMutation) ClearUser() {
+ m.cleareduser = true
+}
+
+// UserCleared reports if the "user" edge to the User entity was cleared.
+func (m *UserTokenMutation) UserCleared() bool {
+ return m.cleareduser
+}
+
+// UserID returns the "user" edge ID in the mutation.
+func (m *UserTokenMutation) UserID() (id int, exists bool) {
+ if m.user != nil {
+ return *m.user, true
+ }
+ return
+}
+
+// UserIDs returns the "user" edge IDs in the mutation.
+// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use
+// UserID instead. It exists only for internal usage by the builders.
+func (m *UserTokenMutation) UserIDs() (ids []int) {
+ if id := m.user; id != nil {
+ ids = append(ids, *id)
+ }
+ return
+}
+
+// ResetUser resets all changes to the "user" edge.
+func (m *UserTokenMutation) ResetUser() {
+ m.user = nil
+ m.cleareduser = false
+}
+
+// Where appends a list predicates to the UserTokenMutation builder.
+func (m *UserTokenMutation) Where(ps ...predicate.UserToken) {
+ m.predicates = append(m.predicates, ps...)
+}
+
+// WhereP appends storage-level predicates to the UserTokenMutation builder. Using this method,
+// users can use type-assertion to append predicates that do not depend on any generated package.
+func (m *UserTokenMutation) WhereP(ps ...func(*sql.Selector)) {
+ p := make([]predicate.UserToken, len(ps))
+ for i := range ps {
+ p[i] = ps[i]
+ }
+ m.Where(p...)
+}
+
+// Op returns the operation name.
+func (m *UserTokenMutation) Op() Op {
+ return m.op
+}
+
+// SetOp allows setting the mutation operation.
+func (m *UserTokenMutation) SetOp(op Op) {
+ m.op = op
+}
+
+// Type returns the node type of this mutation (UserToken).
+func (m *UserTokenMutation) Type() string {
+ return m.typ
+}
+
+// Fields returns all fields that were changed during this mutation. Note that in
+// order to get all numeric fields that were incremented/decremented, call
+// AddedFields().
+func (m *UserTokenMutation) Fields() []string {
+ fields := make([]string, 0, 1)
+ if m.token_id != nil {
+ fields = append(fields, usertoken.FieldTokenID)
+ }
+ return fields
+}
+
+// Field returns the value of a field with the given name. The second boolean
+// return value indicates that this field was not set, or was not defined in the
+// schema.
+func (m *UserTokenMutation) Field(name string) (ent.Value, bool) {
+ switch name {
+ case usertoken.FieldTokenID:
+ return m.TokenID()
+ }
+ return nil, false
+}
+
+// OldField returns the old value of the field from the database. An error is
+// returned if the mutation operation is not UpdateOne, or the query to the
+// database failed.
+func (m *UserTokenMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
+ switch name {
+ case usertoken.FieldTokenID:
+ return m.OldTokenID(ctx)
+ }
+ return nil, fmt.Errorf("unknown UserToken field %s", name)
+}
+
+// SetField sets the value of a field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *UserTokenMutation) SetField(name string, value ent.Value) error {
+ switch name {
+ case usertoken.FieldTokenID:
+ v, ok := value.(uint64)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.SetTokenID(v)
+ return nil
+ }
+ return fmt.Errorf("unknown UserToken field %s", name)
+}
+
+// AddedFields returns all numeric fields that were incremented/decremented during
+// this mutation.
+func (m *UserTokenMutation) AddedFields() []string {
+ var fields []string
+ if m.addtoken_id != nil {
+ fields = append(fields, usertoken.FieldTokenID)
+ }
+ return fields
+}
+
+// AddedField returns the numeric value that was incremented/decremented on a field
+// with the given name. The second boolean return value indicates that this field
+// was not set, or was not defined in the schema.
+func (m *UserTokenMutation) AddedField(name string) (ent.Value, bool) {
+ switch name {
+ case usertoken.FieldTokenID:
+ return m.AddedTokenID()
+ }
+ return nil, false
+}
+
+// AddField adds the value to the field with the given name. It returns an error if
+// the field is not defined in the schema, or if the type mismatched the field
+// type.
+func (m *UserTokenMutation) AddField(name string, value ent.Value) error {
+ switch name {
+ case usertoken.FieldTokenID:
+ v, ok := value.(int64)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field %s", value, name)
+ }
+ m.AddTokenID(v)
+ return nil
+ }
+ return fmt.Errorf("unknown UserToken numeric field %s", name)
+}
+
+// ClearedFields returns all nullable fields that were cleared during this
+// mutation.
+func (m *UserTokenMutation) ClearedFields() []string {
+ return nil
+}
+
+// FieldCleared returns a boolean indicating if a field with the given name was
+// cleared in this mutation.
+func (m *UserTokenMutation) FieldCleared(name string) bool {
+ _, ok := m.clearedFields[name]
+ return ok
+}
+
+// ClearField clears the value of the field with the given name. It returns an
+// error if the field is not defined in the schema.
+func (m *UserTokenMutation) ClearField(name string) error {
+ return fmt.Errorf("unknown UserToken nullable field %s", name)
+}
+
+// ResetField resets all changes in the mutation for the field with the given name.
+// It returns an error if the field is not defined in the schema.
+func (m *UserTokenMutation) ResetField(name string) error {
+ switch name {
+ case usertoken.FieldTokenID:
+ m.ResetTokenID()
+ return nil
+ }
+ return fmt.Errorf("unknown UserToken field %s", name)
+}
+
+// AddedEdges returns all edge names that were set/added in this mutation.
+func (m *UserTokenMutation) AddedEdges() []string {
+ edges := make([]string, 0, 1)
+ if m.user != nil {
+ edges = append(edges, usertoken.EdgeUser)
+ }
+ return edges
+}
+
+// AddedIDs returns all IDs (to other nodes) that were added for the given edge
+// name in this mutation.
+func (m *UserTokenMutation) AddedIDs(name string) []ent.Value {
+ switch name {
+ case usertoken.EdgeUser:
+ if id := m.user; id != nil {
+ return []ent.Value{*id}
+ }
+ }
+ return nil
+}
+
+// RemovedEdges returns all edge names that were removed in this mutation.
+func (m *UserTokenMutation) RemovedEdges() []string {
+ edges := make([]string, 0, 1)
+ return edges
+}
+
+// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
+// the given name in this mutation.
+func (m *UserTokenMutation) RemovedIDs(name string) []ent.Value {
+ return nil
+}
+
+// ClearedEdges returns all edge names that were cleared in this mutation.
+func (m *UserTokenMutation) ClearedEdges() []string {
+ edges := make([]string, 0, 1)
+ if m.cleareduser {
+ edges = append(edges, usertoken.EdgeUser)
+ }
+ return edges
+}
+
+// EdgeCleared returns a boolean which indicates if the edge with the given name
+// was cleared in this mutation.
+func (m *UserTokenMutation) EdgeCleared(name string) bool {
+ switch name {
+ case usertoken.EdgeUser:
+ return m.cleareduser
+ }
+ return false
+}
+
+// ClearEdge clears the value of the edge with the given name. It returns an error
+// if that edge is not defined in the schema.
+func (m *UserTokenMutation) ClearEdge(name string) error {
+ switch name {
+ case usertoken.EdgeUser:
+ m.ClearUser()
+ return nil
+ }
+ return fmt.Errorf("unknown UserToken unique edge %s", name)
+}
+
+// ResetEdge resets all changes to the edge with the given name in this mutation.
+// It returns an error if the edge is not defined in the schema.
+func (m *UserTokenMutation) ResetEdge(name string) error {
+ switch name {
+ case usertoken.EdgeUser:
+ m.ResetUser()
+ return nil
+ }
+ return fmt.Errorf("unknown UserToken edge %s", name)
+}
diff --git a/db/ent/predicate/predicate.go b/db/ent/predicate/predicate.go
new file mode 100644
index 0000000..d18131d
--- /dev/null
+++ b/db/ent/predicate/predicate.go
@@ -0,0 +1,22 @@
+// Code generated by ent, DO NOT EDIT.
+
+package predicate
+
+import (
+ "entgo.io/ent/dialect/sql"
+)
+
+// Texture is the predicate function for texture builders.
+type Texture func(*sql.Selector)
+
+// User is the predicate function for user builders.
+type User func(*sql.Selector)
+
+// UserProfile is the predicate function for userprofile builders.
+type UserProfile func(*sql.Selector)
+
+// UserTexture is the predicate function for usertexture builders.
+type UserTexture func(*sql.Selector)
+
+// UserToken is the predicate function for usertoken builders.
+type UserToken func(*sql.Selector)
diff --git a/db/ent/runtime.go b/db/ent/runtime.go
new file mode 100644
index 0000000..793d053
--- /dev/null
+++ b/db/ent/runtime.go
@@ -0,0 +1,9 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+// The init function reads all schema descriptors with runtime code
+// (default values, validators, hooks and policies) and stitches it
+// to their package variables.
+func init() {
+}
diff --git a/db/ent/runtime/runtime.go b/db/ent/runtime/runtime.go
new file mode 100644
index 0000000..eff54c3
--- /dev/null
+++ b/db/ent/runtime/runtime.go
@@ -0,0 +1,9 @@
+// Code generated by ent, DO NOT EDIT.
+
+package runtime
+
+// The schema-stitching logic is generated in github.com/xmdhs/authlib-skin/db/ent/runtime.go
+
+const (
+ Version = "(devel)" // Version of ent codegen.
+)
diff --git a/db/ent/schema/texture.go b/db/ent/schema/texture.go
new file mode 100644
index 0000000..e6b5a01
--- /dev/null
+++ b/db/ent/schema/texture.go
@@ -0,0 +1,37 @@
+package schema
+
+import (
+ "entgo.io/ent"
+ "entgo.io/ent/dialect"
+ "entgo.io/ent/schema/edge"
+ "entgo.io/ent/schema/field"
+ "entgo.io/ent/schema/index"
+)
+
+// Texture holds the schema definition for the Texture entity.
+type Texture struct {
+ ent.Schema
+}
+
+// Fields of the Texture.
+func (Texture) Fields() []ent.Field {
+ return []ent.Field{
+ field.String("texture_hash").SchemaType(map[string]string{
+ dialect.MySQL: "VARCHAR(100)",
+ }),
+ }
+}
+
+// Edges of the Texture.
+func (Texture) Edges() []ent.Edge {
+ return []ent.Edge{
+ edge.To("created_user", User.Type).Unique().Required(),
+ edge.To("user_profile", UserProfile.Type).Through("usertexture", UserTexture.Type),
+ }
+}
+
+func (Texture) Indexes() []ent.Index {
+ return []ent.Index{
+ index.Fields("texture_hash").Unique(),
+ }
+}
diff --git a/db/ent/schema/user.go b/db/ent/schema/user.go
new file mode 100644
index 0000000..b7b304f
--- /dev/null
+++ b/db/ent/schema/user.go
@@ -0,0 +1,52 @@
+package schema
+
+import (
+ "entgo.io/ent"
+ "entgo.io/ent/dialect"
+ "entgo.io/ent/schema/edge"
+ "entgo.io/ent/schema/field"
+ "entgo.io/ent/schema/index"
+)
+
+// User holds the schema definition for the User entity.
+type User struct {
+ ent.Schema
+}
+
+// Fields of the User.
+func (User) Fields() []ent.Field {
+ return []ent.Field{
+ field.String("email").Unique().SchemaType(map[string]string{
+ dialect.MySQL: "VARCHAR(30)",
+ }),
+ field.String("password").SchemaType(map[string]string{
+ dialect.MySQL: "VARCHAR(80)",
+ }),
+ field.String("salt").SchemaType(map[string]string{
+ dialect.MySQL: "VARCHAR(50)",
+ }),
+ field.String("reg_ip").SchemaType(map[string]string{
+ dialect.MySQL: "VARCHAR(32)",
+ }),
+ // 二进制状态位
+ // 第一位为 1 则是 admin
+ field.Int("state"),
+ field.Int64("reg_time"),
+ }
+}
+
+// Edges of the User.
+func (User) Edges() []ent.Edge {
+ return []ent.Edge{
+ edge.From("created_texture", Texture.Type).Ref("created_user"),
+ edge.To("profile", UserProfile.Type).Unique(),
+ edge.To("token", UserToken.Type).Unique(),
+ }
+}
+
+func (User) Indexes() []ent.Index {
+ return []ent.Index{
+ index.Fields("email").Unique(),
+ index.Fields("reg_ip"),
+ }
+}
diff --git a/db/ent/schema/userprofile.go b/db/ent/schema/userprofile.go
new file mode 100644
index 0000000..da9869d
--- /dev/null
+++ b/db/ent/schema/userprofile.go
@@ -0,0 +1,42 @@
+package schema
+
+import (
+ "entgo.io/ent"
+ "entgo.io/ent/dialect"
+ "entgo.io/ent/schema/edge"
+ "entgo.io/ent/schema/field"
+ "entgo.io/ent/schema/index"
+)
+
+// UserProfile holds the schema definition for the UserProfile entity.
+type UserProfile struct {
+ ent.Schema
+}
+
+// Fields of the UserProfile.
+func (UserProfile) Fields() []ent.Field {
+ return []ent.Field{
+ field.String("name").Unique().SchemaType(map[string]string{
+ dialect.MySQL: "VARCHAR(20)",
+ }),
+ field.String("uuid").SchemaType(map[string]string{
+ dialect.MySQL: "VARCHAR(32)",
+ }),
+ }
+}
+
+// Edges of the UserProfile.
+func (UserProfile) Edges() []ent.Edge {
+ return []ent.Edge{
+ edge.From("user", User.Type).Ref("profile").Required().Unique(),
+ edge.From("texture", Texture.Type).Ref("user_profile").Through("usertexture", UserTexture.Type),
+ }
+}
+
+func (UserProfile) Indexes() []ent.Index {
+ return []ent.Index{
+ index.Edges("user"),
+ index.Fields("name"),
+ index.Fields("uuid"),
+ }
+}
diff --git a/db/ent/schema/usertexture.go b/db/ent/schema/usertexture.go
new file mode 100644
index 0000000..4ee5c07
--- /dev/null
+++ b/db/ent/schema/usertexture.go
@@ -0,0 +1,51 @@
+package schema
+
+import (
+ "entgo.io/ent"
+ "entgo.io/ent/dialect"
+ "entgo.io/ent/schema/edge"
+ "entgo.io/ent/schema/field"
+ "entgo.io/ent/schema/index"
+)
+
+// UserTexture holds the schema definition for the UserTexture entity.
+type UserTexture struct {
+ ent.Schema
+}
+
+// Fields of the UserTexture.
+func (UserTexture) Fields() []ent.Field {
+ return []ent.Field{
+ field.Int("user_profile_id"),
+ field.Int("texture_id"),
+ // skin or cape
+ field.String("type").SchemaType(map[string]string{
+ dialect.MySQL: "VARCHAR(10)",
+ }),
+ // slim or ""
+ field.String("variant").SchemaType(map[string]string{
+ dialect.MySQL: "VARCHAR(10)",
+ }),
+ }
+}
+
+// Edges of the UserTexture.
+func (UserTexture) Edges() []ent.Edge {
+ return []ent.Edge{
+ edge.To("user_profile", UserProfile.Type).
+ Unique().
+ Required().
+ Field("user_profile_id"),
+ edge.To("texture", Texture.Type).
+ Unique().
+ Required().
+ Field("texture_id"),
+ }
+}
+
+func (UserTexture) Indexes() []ent.Index {
+ return []ent.Index{
+ index.Edges("user_profile"),
+ index.Edges("texture"),
+ }
+}
diff --git a/db/ent/schema/usertoken.go b/db/ent/schema/usertoken.go
new file mode 100644
index 0000000..637df5f
--- /dev/null
+++ b/db/ent/schema/usertoken.go
@@ -0,0 +1,34 @@
+package schema
+
+import (
+ "entgo.io/ent"
+ "entgo.io/ent/schema/edge"
+ "entgo.io/ent/schema/field"
+ "entgo.io/ent/schema/index"
+)
+
+// UserToken holds the schema definition for the UserToken entity.
+type UserToken struct {
+ ent.Schema
+}
+
+// Fields of the UserToken.
+func (UserToken) Fields() []ent.Field {
+ return []ent.Field{
+ // 用于验证 jwt token 是否被注销,若相同则有效
+ field.Uint64("token_id"),
+ }
+}
+
+// Edges of the UserToken.
+func (UserToken) Edges() []ent.Edge {
+ return []ent.Edge{
+ edge.From("user", User.Type).Ref("token").Unique(),
+ }
+}
+
+func (UserToken) Indexes() []ent.Index {
+ return []ent.Index{
+ index.Edges("user"),
+ }
+}
diff --git a/db/ent/texture.go b/db/ent/texture.go
new file mode 100644
index 0000000..e29d734
--- /dev/null
+++ b/db/ent/texture.go
@@ -0,0 +1,176 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "fmt"
+ "strings"
+
+ "entgo.io/ent"
+ "entgo.io/ent/dialect/sql"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+)
+
+// Texture is the model entity for the Texture schema.
+type Texture struct {
+ config `json:"-"`
+ // ID of the ent.
+ ID int `json:"id,omitempty"`
+ // TextureHash holds the value of the "texture_hash" field.
+ TextureHash string `json:"texture_hash,omitempty"`
+ // Edges holds the relations/edges for other nodes in the graph.
+ // The values are being populated by the TextureQuery when eager-loading is set.
+ Edges TextureEdges `json:"edges"`
+ texture_created_user *int
+ selectValues sql.SelectValues
+}
+
+// TextureEdges holds the relations/edges for other nodes in the graph.
+type TextureEdges struct {
+ // CreatedUser holds the value of the created_user edge.
+ CreatedUser *User `json:"created_user,omitempty"`
+ // UserProfile holds the value of the user_profile edge.
+ UserProfile []*UserProfile `json:"user_profile,omitempty"`
+ // Usertexture holds the value of the usertexture edge.
+ Usertexture []*UserTexture `json:"usertexture,omitempty"`
+ // loadedTypes holds the information for reporting if a
+ // type was loaded (or requested) in eager-loading or not.
+ loadedTypes [3]bool
+}
+
+// CreatedUserOrErr returns the CreatedUser value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e TextureEdges) CreatedUserOrErr() (*User, error) {
+ if e.loadedTypes[0] {
+ if e.CreatedUser == nil {
+ // Edge was loaded but was not found.
+ return nil, &NotFoundError{label: user.Label}
+ }
+ return e.CreatedUser, nil
+ }
+ return nil, &NotLoadedError{edge: "created_user"}
+}
+
+// UserProfileOrErr returns the UserProfile value or an error if the edge
+// was not loaded in eager-loading.
+func (e TextureEdges) UserProfileOrErr() ([]*UserProfile, error) {
+ if e.loadedTypes[1] {
+ return e.UserProfile, nil
+ }
+ return nil, &NotLoadedError{edge: "user_profile"}
+}
+
+// UsertextureOrErr returns the Usertexture value or an error if the edge
+// was not loaded in eager-loading.
+func (e TextureEdges) UsertextureOrErr() ([]*UserTexture, error) {
+ if e.loadedTypes[2] {
+ return e.Usertexture, nil
+ }
+ return nil, &NotLoadedError{edge: "usertexture"}
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*Texture) scanValues(columns []string) ([]any, error) {
+ values := make([]any, len(columns))
+ for i := range columns {
+ switch columns[i] {
+ case texture.FieldID:
+ values[i] = new(sql.NullInt64)
+ case texture.FieldTextureHash:
+ values[i] = new(sql.NullString)
+ case texture.ForeignKeys[0]: // texture_created_user
+ values[i] = new(sql.NullInt64)
+ default:
+ values[i] = new(sql.UnknownType)
+ }
+ }
+ return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the Texture fields.
+func (t *Texture) assignValues(columns []string, values []any) error {
+ if m, n := len(values), len(columns); m < n {
+ return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+ }
+ for i := range columns {
+ switch columns[i] {
+ case texture.FieldID:
+ value, ok := values[i].(*sql.NullInt64)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field id", value)
+ }
+ t.ID = int(value.Int64)
+ case texture.FieldTextureHash:
+ if value, ok := values[i].(*sql.NullString); !ok {
+ return fmt.Errorf("unexpected type %T for field texture_hash", values[i])
+ } else if value.Valid {
+ t.TextureHash = value.String
+ }
+ case texture.ForeignKeys[0]:
+ if value, ok := values[i].(*sql.NullInt64); !ok {
+ return fmt.Errorf("unexpected type %T for edge-field texture_created_user", value)
+ } else if value.Valid {
+ t.texture_created_user = new(int)
+ *t.texture_created_user = int(value.Int64)
+ }
+ default:
+ t.selectValues.Set(columns[i], values[i])
+ }
+ }
+ return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the Texture.
+// This includes values selected through modifiers, order, etc.
+func (t *Texture) Value(name string) (ent.Value, error) {
+ return t.selectValues.Get(name)
+}
+
+// QueryCreatedUser queries the "created_user" edge of the Texture entity.
+func (t *Texture) QueryCreatedUser() *UserQuery {
+ return NewTextureClient(t.config).QueryCreatedUser(t)
+}
+
+// QueryUserProfile queries the "user_profile" edge of the Texture entity.
+func (t *Texture) QueryUserProfile() *UserProfileQuery {
+ return NewTextureClient(t.config).QueryUserProfile(t)
+}
+
+// QueryUsertexture queries the "usertexture" edge of the Texture entity.
+func (t *Texture) QueryUsertexture() *UserTextureQuery {
+ return NewTextureClient(t.config).QueryUsertexture(t)
+}
+
+// Update returns a builder for updating this Texture.
+// Note that you need to call Texture.Unwrap() before calling this method if this Texture
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (t *Texture) Update() *TextureUpdateOne {
+ return NewTextureClient(t.config).UpdateOne(t)
+}
+
+// Unwrap unwraps the Texture entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (t *Texture) Unwrap() *Texture {
+ _tx, ok := t.config.driver.(*txDriver)
+ if !ok {
+ panic("ent: Texture is not a transactional entity")
+ }
+ t.config.driver = _tx.drv
+ return t
+}
+
+// String implements the fmt.Stringer.
+func (t *Texture) String() string {
+ var builder strings.Builder
+ builder.WriteString("Texture(")
+ builder.WriteString(fmt.Sprintf("id=%v, ", t.ID))
+ builder.WriteString("texture_hash=")
+ builder.WriteString(t.TextureHash)
+ builder.WriteByte(')')
+ return builder.String()
+}
+
+// Textures is a parsable slice of Texture.
+type Textures []*Texture
diff --git a/db/ent/texture/texture.go b/db/ent/texture/texture.go
new file mode 100644
index 0000000..2e4f0bf
--- /dev/null
+++ b/db/ent/texture/texture.go
@@ -0,0 +1,146 @@
+// Code generated by ent, DO NOT EDIT.
+
+package texture
+
+import (
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+const (
+ // Label holds the string label denoting the texture type in the database.
+ Label = "texture"
+ // FieldID holds the string denoting the id field in the database.
+ FieldID = "id"
+ // FieldTextureHash holds the string denoting the texture_hash field in the database.
+ FieldTextureHash = "texture_hash"
+ // EdgeCreatedUser holds the string denoting the created_user edge name in mutations.
+ EdgeCreatedUser = "created_user"
+ // EdgeUserProfile holds the string denoting the user_profile edge name in mutations.
+ EdgeUserProfile = "user_profile"
+ // EdgeUsertexture holds the string denoting the usertexture edge name in mutations.
+ EdgeUsertexture = "usertexture"
+ // Table holds the table name of the texture in the database.
+ Table = "textures"
+ // CreatedUserTable is the table that holds the created_user relation/edge.
+ CreatedUserTable = "textures"
+ // CreatedUserInverseTable is the table name for the User entity.
+ // It exists in this package in order to avoid circular dependency with the "user" package.
+ CreatedUserInverseTable = "users"
+ // CreatedUserColumn is the table column denoting the created_user relation/edge.
+ CreatedUserColumn = "texture_created_user"
+ // UserProfileTable is the table that holds the user_profile relation/edge. The primary key declared below.
+ UserProfileTable = "user_textures"
+ // UserProfileInverseTable is the table name for the UserProfile entity.
+ // It exists in this package in order to avoid circular dependency with the "userprofile" package.
+ UserProfileInverseTable = "user_profiles"
+ // UsertextureTable is the table that holds the usertexture relation/edge.
+ UsertextureTable = "user_textures"
+ // UsertextureInverseTable is the table name for the UserTexture entity.
+ // It exists in this package in order to avoid circular dependency with the "usertexture" package.
+ UsertextureInverseTable = "user_textures"
+ // UsertextureColumn is the table column denoting the usertexture relation/edge.
+ UsertextureColumn = "texture_id"
+)
+
+// Columns holds all SQL columns for texture fields.
+var Columns = []string{
+ FieldID,
+ FieldTextureHash,
+}
+
+// ForeignKeys holds the SQL foreign-keys that are owned by the "textures"
+// table and are not defined as standalone fields in the schema.
+var ForeignKeys = []string{
+ "texture_created_user",
+}
+
+var (
+ // UserProfilePrimaryKey and UserProfileColumn2 are the table columns denoting the
+ // primary key for the user_profile relation (M2M).
+ UserProfilePrimaryKey = []string{"texture_id", "user_profile_id"}
+)
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+ for i := range Columns {
+ if column == Columns[i] {
+ return true
+ }
+ }
+ for i := range ForeignKeys {
+ if column == ForeignKeys[i] {
+ return true
+ }
+ }
+ return false
+}
+
+// OrderOption defines the ordering options for the Texture queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByTextureHash orders the results by the texture_hash field.
+func ByTextureHash(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldTextureHash, opts...).ToFunc()
+}
+
+// ByCreatedUserField orders the results by created_user field.
+func ByCreatedUserField(field string, opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newCreatedUserStep(), sql.OrderByField(field, opts...))
+ }
+}
+
+// ByUserProfileCount orders the results by user_profile count.
+func ByUserProfileCount(opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborsCount(s, newUserProfileStep(), opts...)
+ }
+}
+
+// ByUserProfile orders the results by user_profile terms.
+func ByUserProfile(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newUserProfileStep(), append([]sql.OrderTerm{term}, terms...)...)
+ }
+}
+
+// ByUsertextureCount orders the results by usertexture count.
+func ByUsertextureCount(opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborsCount(s, newUsertextureStep(), opts...)
+ }
+}
+
+// ByUsertexture orders the results by usertexture terms.
+func ByUsertexture(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newUsertextureStep(), append([]sql.OrderTerm{term}, terms...)...)
+ }
+}
+func newCreatedUserStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(CreatedUserInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, CreatedUserTable, CreatedUserColumn),
+ )
+}
+func newUserProfileStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(UserProfileInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.M2M, false, UserProfileTable, UserProfilePrimaryKey...),
+ )
+}
+func newUsertextureStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(UsertextureInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, UsertextureTable, UsertextureColumn),
+ )
+}
diff --git a/db/ent/texture/where.go b/db/ent/texture/where.go
new file mode 100644
index 0000000..16eb75b
--- /dev/null
+++ b/db/ent/texture/where.go
@@ -0,0 +1,225 @@
+// Code generated by ent, DO NOT EDIT.
+
+package texture
+
+import (
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id int) predicate.Texture {
+ return predicate.Texture(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id int) predicate.Texture {
+ return predicate.Texture(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id int) predicate.Texture {
+ return predicate.Texture(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...int) predicate.Texture {
+ return predicate.Texture(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...int) predicate.Texture {
+ return predicate.Texture(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id int) predicate.Texture {
+ return predicate.Texture(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id int) predicate.Texture {
+ return predicate.Texture(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id int) predicate.Texture {
+ return predicate.Texture(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id int) predicate.Texture {
+ return predicate.Texture(sql.FieldLTE(FieldID, id))
+}
+
+// TextureHash applies equality check predicate on the "texture_hash" field. It's identical to TextureHashEQ.
+func TextureHash(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldEQ(FieldTextureHash, v))
+}
+
+// TextureHashEQ applies the EQ predicate on the "texture_hash" field.
+func TextureHashEQ(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldEQ(FieldTextureHash, v))
+}
+
+// TextureHashNEQ applies the NEQ predicate on the "texture_hash" field.
+func TextureHashNEQ(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldNEQ(FieldTextureHash, v))
+}
+
+// TextureHashIn applies the In predicate on the "texture_hash" field.
+func TextureHashIn(vs ...string) predicate.Texture {
+ return predicate.Texture(sql.FieldIn(FieldTextureHash, vs...))
+}
+
+// TextureHashNotIn applies the NotIn predicate on the "texture_hash" field.
+func TextureHashNotIn(vs ...string) predicate.Texture {
+ return predicate.Texture(sql.FieldNotIn(FieldTextureHash, vs...))
+}
+
+// TextureHashGT applies the GT predicate on the "texture_hash" field.
+func TextureHashGT(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldGT(FieldTextureHash, v))
+}
+
+// TextureHashGTE applies the GTE predicate on the "texture_hash" field.
+func TextureHashGTE(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldGTE(FieldTextureHash, v))
+}
+
+// TextureHashLT applies the LT predicate on the "texture_hash" field.
+func TextureHashLT(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldLT(FieldTextureHash, v))
+}
+
+// TextureHashLTE applies the LTE predicate on the "texture_hash" field.
+func TextureHashLTE(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldLTE(FieldTextureHash, v))
+}
+
+// TextureHashContains applies the Contains predicate on the "texture_hash" field.
+func TextureHashContains(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldContains(FieldTextureHash, v))
+}
+
+// TextureHashHasPrefix applies the HasPrefix predicate on the "texture_hash" field.
+func TextureHashHasPrefix(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldHasPrefix(FieldTextureHash, v))
+}
+
+// TextureHashHasSuffix applies the HasSuffix predicate on the "texture_hash" field.
+func TextureHashHasSuffix(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldHasSuffix(FieldTextureHash, v))
+}
+
+// TextureHashEqualFold applies the EqualFold predicate on the "texture_hash" field.
+func TextureHashEqualFold(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldEqualFold(FieldTextureHash, v))
+}
+
+// TextureHashContainsFold applies the ContainsFold predicate on the "texture_hash" field.
+func TextureHashContainsFold(v string) predicate.Texture {
+ return predicate.Texture(sql.FieldContainsFold(FieldTextureHash, v))
+}
+
+// HasCreatedUser applies the HasEdge predicate on the "created_user" edge.
+func HasCreatedUser() predicate.Texture {
+ return predicate.Texture(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, CreatedUserTable, CreatedUserColumn),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasCreatedUserWith applies the HasEdge predicate on the "created_user" edge with a given conditions (other predicates).
+func HasCreatedUserWith(preds ...predicate.User) predicate.Texture {
+ return predicate.Texture(func(s *sql.Selector) {
+ step := newCreatedUserStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// HasUserProfile applies the HasEdge predicate on the "user_profile" edge.
+func HasUserProfile() predicate.Texture {
+ return predicate.Texture(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.M2M, false, UserProfileTable, UserProfilePrimaryKey...),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasUserProfileWith applies the HasEdge predicate on the "user_profile" edge with a given conditions (other predicates).
+func HasUserProfileWith(preds ...predicate.UserProfile) predicate.Texture {
+ return predicate.Texture(func(s *sql.Selector) {
+ step := newUserProfileStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// HasUsertexture applies the HasEdge predicate on the "usertexture" edge.
+func HasUsertexture() predicate.Texture {
+ return predicate.Texture(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, UsertextureTable, UsertextureColumn),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasUsertextureWith applies the HasEdge predicate on the "usertexture" edge with a given conditions (other predicates).
+func HasUsertextureWith(preds ...predicate.UserTexture) predicate.Texture {
+ return predicate.Texture(func(s *sql.Selector) {
+ step := newUsertextureStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.Texture) predicate.Texture {
+ return predicate.Texture(func(s *sql.Selector) {
+ s1 := s.Clone().SetP(nil)
+ for _, p := range predicates {
+ p(s1)
+ }
+ s.Where(s1.P())
+ })
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.Texture) predicate.Texture {
+ return predicate.Texture(func(s *sql.Selector) {
+ s1 := s.Clone().SetP(nil)
+ for i, p := range predicates {
+ if i > 0 {
+ s1.Or()
+ }
+ p(s1)
+ }
+ s.Where(s1.P())
+ })
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.Texture) predicate.Texture {
+ return predicate.Texture(func(s *sql.Selector) {
+ p(s.Not())
+ })
+}
diff --git a/db/ent/texture_create.go b/db/ent/texture_create.go
new file mode 100644
index 0000000..3cd045c
--- /dev/null
+++ b/db/ent/texture_create.go
@@ -0,0 +1,275 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+)
+
+// TextureCreate is the builder for creating a Texture entity.
+type TextureCreate struct {
+ config
+ mutation *TextureMutation
+ hooks []Hook
+}
+
+// SetTextureHash sets the "texture_hash" field.
+func (tc *TextureCreate) SetTextureHash(s string) *TextureCreate {
+ tc.mutation.SetTextureHash(s)
+ return tc
+}
+
+// SetCreatedUserID sets the "created_user" edge to the User entity by ID.
+func (tc *TextureCreate) SetCreatedUserID(id int) *TextureCreate {
+ tc.mutation.SetCreatedUserID(id)
+ return tc
+}
+
+// SetCreatedUser sets the "created_user" edge to the User entity.
+func (tc *TextureCreate) SetCreatedUser(u *User) *TextureCreate {
+ return tc.SetCreatedUserID(u.ID)
+}
+
+// AddUserProfileIDs adds the "user_profile" edge to the UserProfile entity by IDs.
+func (tc *TextureCreate) AddUserProfileIDs(ids ...int) *TextureCreate {
+ tc.mutation.AddUserProfileIDs(ids...)
+ return tc
+}
+
+// AddUserProfile adds the "user_profile" edges to the UserProfile entity.
+func (tc *TextureCreate) AddUserProfile(u ...*UserProfile) *TextureCreate {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return tc.AddUserProfileIDs(ids...)
+}
+
+// AddUsertextureIDs adds the "usertexture" edge to the UserTexture entity by IDs.
+func (tc *TextureCreate) AddUsertextureIDs(ids ...int) *TextureCreate {
+ tc.mutation.AddUsertextureIDs(ids...)
+ return tc
+}
+
+// AddUsertexture adds the "usertexture" edges to the UserTexture entity.
+func (tc *TextureCreate) AddUsertexture(u ...*UserTexture) *TextureCreate {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return tc.AddUsertextureIDs(ids...)
+}
+
+// Mutation returns the TextureMutation object of the builder.
+func (tc *TextureCreate) Mutation() *TextureMutation {
+ return tc.mutation
+}
+
+// Save creates the Texture in the database.
+func (tc *TextureCreate) Save(ctx context.Context) (*Texture, error) {
+ return withHooks(ctx, tc.sqlSave, tc.mutation, tc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (tc *TextureCreate) SaveX(ctx context.Context) *Texture {
+ v, err := tc.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Exec executes the query.
+func (tc *TextureCreate) Exec(ctx context.Context) error {
+ _, err := tc.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (tc *TextureCreate) ExecX(ctx context.Context) {
+ if err := tc.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (tc *TextureCreate) check() error {
+ if _, ok := tc.mutation.TextureHash(); !ok {
+ return &ValidationError{Name: "texture_hash", err: errors.New(`ent: missing required field "Texture.texture_hash"`)}
+ }
+ if _, ok := tc.mutation.CreatedUserID(); !ok {
+ return &ValidationError{Name: "created_user", err: errors.New(`ent: missing required edge "Texture.created_user"`)}
+ }
+ return nil
+}
+
+func (tc *TextureCreate) sqlSave(ctx context.Context) (*Texture, error) {
+ if err := tc.check(); err != nil {
+ return nil, err
+ }
+ _node, _spec := tc.createSpec()
+ if err := sqlgraph.CreateNode(ctx, tc.driver, _spec); err != nil {
+ if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return nil, err
+ }
+ id := _spec.ID.Value.(int64)
+ _node.ID = int(id)
+ tc.mutation.id = &_node.ID
+ tc.mutation.done = true
+ return _node, nil
+}
+
+func (tc *TextureCreate) createSpec() (*Texture, *sqlgraph.CreateSpec) {
+ var (
+ _node = &Texture{config: tc.config}
+ _spec = sqlgraph.NewCreateSpec(texture.Table, sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt))
+ )
+ if value, ok := tc.mutation.TextureHash(); ok {
+ _spec.SetField(texture.FieldTextureHash, field.TypeString, value)
+ _node.TextureHash = value
+ }
+ if nodes := tc.mutation.CreatedUserIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: texture.CreatedUserTable,
+ Columns: []string{texture.CreatedUserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _node.texture_created_user = &nodes[0]
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ if nodes := tc.mutation.UserProfileIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: false,
+ Table: texture.UserProfileTable,
+ Columns: texture.UserProfilePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ if nodes := tc.mutation.UsertextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: texture.UsertextureTable,
+ Columns: []string{texture.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ return _node, _spec
+}
+
+// TextureCreateBulk is the builder for creating many Texture entities in bulk.
+type TextureCreateBulk struct {
+ config
+ builders []*TextureCreate
+}
+
+// Save creates the Texture entities in the database.
+func (tcb *TextureCreateBulk) Save(ctx context.Context) ([]*Texture, error) {
+ specs := make([]*sqlgraph.CreateSpec, len(tcb.builders))
+ nodes := make([]*Texture, len(tcb.builders))
+ mutators := make([]Mutator, len(tcb.builders))
+ for i := range tcb.builders {
+ func(i int, root context.Context) {
+ builder := tcb.builders[i]
+ var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+ mutation, ok := m.(*TextureMutation)
+ if !ok {
+ return nil, fmt.Errorf("unexpected mutation type %T", m)
+ }
+ if err := builder.check(); err != nil {
+ return nil, err
+ }
+ builder.mutation = mutation
+ var err error
+ nodes[i], specs[i] = builder.createSpec()
+ if i < len(mutators)-1 {
+ _, err = mutators[i+1].Mutate(root, tcb.builders[i+1].mutation)
+ } else {
+ spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+ // Invoke the actual operation on the latest mutation in the chain.
+ if err = sqlgraph.BatchCreate(ctx, tcb.driver, spec); err != nil {
+ if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ mutation.id = &nodes[i].ID
+ if specs[i].ID.Value != nil {
+ id := specs[i].ID.Value.(int64)
+ nodes[i].ID = int(id)
+ }
+ mutation.done = true
+ return nodes[i], nil
+ })
+ for i := len(builder.hooks) - 1; i >= 0; i-- {
+ mut = builder.hooks[i](mut)
+ }
+ mutators[i] = mut
+ }(i, ctx)
+ }
+ if len(mutators) > 0 {
+ if _, err := mutators[0].Mutate(ctx, tcb.builders[0].mutation); err != nil {
+ return nil, err
+ }
+ }
+ return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (tcb *TextureCreateBulk) SaveX(ctx context.Context) []*Texture {
+ v, err := tcb.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Exec executes the query.
+func (tcb *TextureCreateBulk) Exec(ctx context.Context) error {
+ _, err := tcb.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (tcb *TextureCreateBulk) ExecX(ctx context.Context) {
+ if err := tcb.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
diff --git a/db/ent/texture_delete.go b/db/ent/texture_delete.go
new file mode 100644
index 0000000..fcdf8c7
--- /dev/null
+++ b/db/ent/texture_delete.go
@@ -0,0 +1,88 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+)
+
+// TextureDelete is the builder for deleting a Texture entity.
+type TextureDelete struct {
+ config
+ hooks []Hook
+ mutation *TextureMutation
+}
+
+// Where appends a list predicates to the TextureDelete builder.
+func (td *TextureDelete) Where(ps ...predicate.Texture) *TextureDelete {
+ td.mutation.Where(ps...)
+ return td
+}
+
+// Exec executes the deletion query and returns how many vertices were deleted.
+func (td *TextureDelete) Exec(ctx context.Context) (int, error) {
+ return withHooks(ctx, td.sqlExec, td.mutation, td.hooks)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (td *TextureDelete) ExecX(ctx context.Context) int {
+ n, err := td.Exec(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return n
+}
+
+func (td *TextureDelete) sqlExec(ctx context.Context) (int, error) {
+ _spec := sqlgraph.NewDeleteSpec(texture.Table, sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt))
+ if ps := td.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ affected, err := sqlgraph.DeleteNodes(ctx, td.driver, _spec)
+ if err != nil && sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ td.mutation.done = true
+ return affected, err
+}
+
+// TextureDeleteOne is the builder for deleting a single Texture entity.
+type TextureDeleteOne struct {
+ td *TextureDelete
+}
+
+// Where appends a list predicates to the TextureDelete builder.
+func (tdo *TextureDeleteOne) Where(ps ...predicate.Texture) *TextureDeleteOne {
+ tdo.td.mutation.Where(ps...)
+ return tdo
+}
+
+// Exec executes the deletion query.
+func (tdo *TextureDeleteOne) Exec(ctx context.Context) error {
+ n, err := tdo.td.Exec(ctx)
+ switch {
+ case err != nil:
+ return err
+ case n == 0:
+ return &NotFoundError{texture.Label}
+ default:
+ return nil
+ }
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (tdo *TextureDeleteOne) ExecX(ctx context.Context) {
+ if err := tdo.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
diff --git a/db/ent/texture_query.go b/db/ent/texture_query.go
new file mode 100644
index 0000000..cf8b3eb
--- /dev/null
+++ b/db/ent/texture_query.go
@@ -0,0 +1,850 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "database/sql/driver"
+ "fmt"
+ "math"
+
+ "entgo.io/ent/dialect"
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+)
+
+// TextureQuery is the builder for querying Texture entities.
+type TextureQuery struct {
+ config
+ ctx *QueryContext
+ order []texture.OrderOption
+ inters []Interceptor
+ predicates []predicate.Texture
+ withCreatedUser *UserQuery
+ withUserProfile *UserProfileQuery
+ withUsertexture *UserTextureQuery
+ withFKs bool
+ modifiers []func(*sql.Selector)
+ // intermediate query (i.e. traversal path).
+ sql *sql.Selector
+ path func(context.Context) (*sql.Selector, error)
+}
+
+// Where adds a new predicate for the TextureQuery builder.
+func (tq *TextureQuery) Where(ps ...predicate.Texture) *TextureQuery {
+ tq.predicates = append(tq.predicates, ps...)
+ return tq
+}
+
+// Limit the number of records to be returned by this query.
+func (tq *TextureQuery) Limit(limit int) *TextureQuery {
+ tq.ctx.Limit = &limit
+ return tq
+}
+
+// Offset to start from.
+func (tq *TextureQuery) Offset(offset int) *TextureQuery {
+ tq.ctx.Offset = &offset
+ return tq
+}
+
+// Unique configures the query builder to filter duplicate records on query.
+// By default, unique is set to true, and can be disabled using this method.
+func (tq *TextureQuery) Unique(unique bool) *TextureQuery {
+ tq.ctx.Unique = &unique
+ return tq
+}
+
+// Order specifies how the records should be ordered.
+func (tq *TextureQuery) Order(o ...texture.OrderOption) *TextureQuery {
+ tq.order = append(tq.order, o...)
+ return tq
+}
+
+// QueryCreatedUser chains the current query on the "created_user" edge.
+func (tq *TextureQuery) QueryCreatedUser() *UserQuery {
+ query := (&UserClient{config: tq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := tq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := tq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(texture.Table, texture.FieldID, selector),
+ sqlgraph.To(user.Table, user.FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, texture.CreatedUserTable, texture.CreatedUserColumn),
+ )
+ fromU = sqlgraph.SetNeighbors(tq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// QueryUserProfile chains the current query on the "user_profile" edge.
+func (tq *TextureQuery) QueryUserProfile() *UserProfileQuery {
+ query := (&UserProfileClient{config: tq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := tq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := tq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(texture.Table, texture.FieldID, selector),
+ sqlgraph.To(userprofile.Table, userprofile.FieldID),
+ sqlgraph.Edge(sqlgraph.M2M, false, texture.UserProfileTable, texture.UserProfilePrimaryKey...),
+ )
+ fromU = sqlgraph.SetNeighbors(tq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// QueryUsertexture chains the current query on the "usertexture" edge.
+func (tq *TextureQuery) QueryUsertexture() *UserTextureQuery {
+ query := (&UserTextureClient{config: tq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := tq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := tq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(texture.Table, texture.FieldID, selector),
+ sqlgraph.To(usertexture.Table, usertexture.FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, texture.UsertextureTable, texture.UsertextureColumn),
+ )
+ fromU = sqlgraph.SetNeighbors(tq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// First returns the first Texture entity from the query.
+// Returns a *NotFoundError when no Texture was found.
+func (tq *TextureQuery) First(ctx context.Context) (*Texture, error) {
+ nodes, err := tq.Limit(1).All(setContextOp(ctx, tq.ctx, "First"))
+ if err != nil {
+ return nil, err
+ }
+ if len(nodes) == 0 {
+ return nil, &NotFoundError{texture.Label}
+ }
+ return nodes[0], nil
+}
+
+// FirstX is like First, but panics if an error occurs.
+func (tq *TextureQuery) FirstX(ctx context.Context) *Texture {
+ node, err := tq.First(ctx)
+ if err != nil && !IsNotFound(err) {
+ panic(err)
+ }
+ return node
+}
+
+// FirstID returns the first Texture ID from the query.
+// Returns a *NotFoundError when no Texture ID was found.
+func (tq *TextureQuery) FirstID(ctx context.Context) (id int, err error) {
+ var ids []int
+ if ids, err = tq.Limit(1).IDs(setContextOp(ctx, tq.ctx, "FirstID")); err != nil {
+ return
+ }
+ if len(ids) == 0 {
+ err = &NotFoundError{texture.Label}
+ return
+ }
+ return ids[0], nil
+}
+
+// FirstIDX is like FirstID, but panics if an error occurs.
+func (tq *TextureQuery) FirstIDX(ctx context.Context) int {
+ id, err := tq.FirstID(ctx)
+ if err != nil && !IsNotFound(err) {
+ panic(err)
+ }
+ return id
+}
+
+// Only returns a single Texture entity found by the query, ensuring it only returns one.
+// Returns a *NotSingularError when more than one Texture entity is found.
+// Returns a *NotFoundError when no Texture entities are found.
+func (tq *TextureQuery) Only(ctx context.Context) (*Texture, error) {
+ nodes, err := tq.Limit(2).All(setContextOp(ctx, tq.ctx, "Only"))
+ if err != nil {
+ return nil, err
+ }
+ switch len(nodes) {
+ case 1:
+ return nodes[0], nil
+ case 0:
+ return nil, &NotFoundError{texture.Label}
+ default:
+ return nil, &NotSingularError{texture.Label}
+ }
+}
+
+// OnlyX is like Only, but panics if an error occurs.
+func (tq *TextureQuery) OnlyX(ctx context.Context) *Texture {
+ node, err := tq.Only(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return node
+}
+
+// OnlyID is like Only, but returns the only Texture ID in the query.
+// Returns a *NotSingularError when more than one Texture ID is found.
+// Returns a *NotFoundError when no entities are found.
+func (tq *TextureQuery) OnlyID(ctx context.Context) (id int, err error) {
+ var ids []int
+ if ids, err = tq.Limit(2).IDs(setContextOp(ctx, tq.ctx, "OnlyID")); err != nil {
+ return
+ }
+ switch len(ids) {
+ case 1:
+ id = ids[0]
+ case 0:
+ err = &NotFoundError{texture.Label}
+ default:
+ err = &NotSingularError{texture.Label}
+ }
+ return
+}
+
+// OnlyIDX is like OnlyID, but panics if an error occurs.
+func (tq *TextureQuery) OnlyIDX(ctx context.Context) int {
+ id, err := tq.OnlyID(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
+// All executes the query and returns a list of Textures.
+func (tq *TextureQuery) All(ctx context.Context) ([]*Texture, error) {
+ ctx = setContextOp(ctx, tq.ctx, "All")
+ if err := tq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ qr := querierAll[[]*Texture, *TextureQuery]()
+ return withInterceptors[[]*Texture](ctx, tq, qr, tq.inters)
+}
+
+// AllX is like All, but panics if an error occurs.
+func (tq *TextureQuery) AllX(ctx context.Context) []*Texture {
+ nodes, err := tq.All(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return nodes
+}
+
+// IDs executes the query and returns a list of Texture IDs.
+func (tq *TextureQuery) IDs(ctx context.Context) (ids []int, err error) {
+ if tq.ctx.Unique == nil && tq.path != nil {
+ tq.Unique(true)
+ }
+ ctx = setContextOp(ctx, tq.ctx, "IDs")
+ if err = tq.Select(texture.FieldID).Scan(ctx, &ids); err != nil {
+ return nil, err
+ }
+ return ids, nil
+}
+
+// IDsX is like IDs, but panics if an error occurs.
+func (tq *TextureQuery) IDsX(ctx context.Context) []int {
+ ids, err := tq.IDs(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return ids
+}
+
+// Count returns the count of the given query.
+func (tq *TextureQuery) Count(ctx context.Context) (int, error) {
+ ctx = setContextOp(ctx, tq.ctx, "Count")
+ if err := tq.prepareQuery(ctx); err != nil {
+ return 0, err
+ }
+ return withInterceptors[int](ctx, tq, querierCount[*TextureQuery](), tq.inters)
+}
+
+// CountX is like Count, but panics if an error occurs.
+func (tq *TextureQuery) CountX(ctx context.Context) int {
+ count, err := tq.Count(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return count
+}
+
+// Exist returns true if the query has elements in the graph.
+func (tq *TextureQuery) Exist(ctx context.Context) (bool, error) {
+ ctx = setContextOp(ctx, tq.ctx, "Exist")
+ switch _, err := tq.FirstID(ctx); {
+ case IsNotFound(err):
+ return false, nil
+ case err != nil:
+ return false, fmt.Errorf("ent: check existence: %w", err)
+ default:
+ return true, nil
+ }
+}
+
+// ExistX is like Exist, but panics if an error occurs.
+func (tq *TextureQuery) ExistX(ctx context.Context) bool {
+ exist, err := tq.Exist(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return exist
+}
+
+// Clone returns a duplicate of the TextureQuery builder, including all associated steps. It can be
+// used to prepare common query builders and use them differently after the clone is made.
+func (tq *TextureQuery) Clone() *TextureQuery {
+ if tq == nil {
+ return nil
+ }
+ return &TextureQuery{
+ config: tq.config,
+ ctx: tq.ctx.Clone(),
+ order: append([]texture.OrderOption{}, tq.order...),
+ inters: append([]Interceptor{}, tq.inters...),
+ predicates: append([]predicate.Texture{}, tq.predicates...),
+ withCreatedUser: tq.withCreatedUser.Clone(),
+ withUserProfile: tq.withUserProfile.Clone(),
+ withUsertexture: tq.withUsertexture.Clone(),
+ // clone intermediate query.
+ sql: tq.sql.Clone(),
+ path: tq.path,
+ }
+}
+
+// WithCreatedUser tells the query-builder to eager-load the nodes that are connected to
+// the "created_user" edge. The optional arguments are used to configure the query builder of the edge.
+func (tq *TextureQuery) WithCreatedUser(opts ...func(*UserQuery)) *TextureQuery {
+ query := (&UserClient{config: tq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ tq.withCreatedUser = query
+ return tq
+}
+
+// WithUserProfile tells the query-builder to eager-load the nodes that are connected to
+// the "user_profile" edge. The optional arguments are used to configure the query builder of the edge.
+func (tq *TextureQuery) WithUserProfile(opts ...func(*UserProfileQuery)) *TextureQuery {
+ query := (&UserProfileClient{config: tq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ tq.withUserProfile = query
+ return tq
+}
+
+// WithUsertexture tells the query-builder to eager-load the nodes that are connected to
+// the "usertexture" edge. The optional arguments are used to configure the query builder of the edge.
+func (tq *TextureQuery) WithUsertexture(opts ...func(*UserTextureQuery)) *TextureQuery {
+ query := (&UserTextureClient{config: tq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ tq.withUsertexture = query
+ return tq
+}
+
+// GroupBy is used to group vertices by one or more fields/columns.
+// It is often used with aggregate functions, like: count, max, mean, min, sum.
+//
+// Example:
+//
+// var v []struct {
+// TextureHash string `json:"texture_hash,omitempty"`
+// Count int `json:"count,omitempty"`
+// }
+//
+// client.Texture.Query().
+// GroupBy(texture.FieldTextureHash).
+// Aggregate(ent.Count()).
+// Scan(ctx, &v)
+func (tq *TextureQuery) GroupBy(field string, fields ...string) *TextureGroupBy {
+ tq.ctx.Fields = append([]string{field}, fields...)
+ grbuild := &TextureGroupBy{build: tq}
+ grbuild.flds = &tq.ctx.Fields
+ grbuild.label = texture.Label
+ grbuild.scan = grbuild.Scan
+ return grbuild
+}
+
+// Select allows the selection one or more fields/columns for the given query,
+// instead of selecting all fields in the entity.
+//
+// Example:
+//
+// var v []struct {
+// TextureHash string `json:"texture_hash,omitempty"`
+// }
+//
+// client.Texture.Query().
+// Select(texture.FieldTextureHash).
+// Scan(ctx, &v)
+func (tq *TextureQuery) Select(fields ...string) *TextureSelect {
+ tq.ctx.Fields = append(tq.ctx.Fields, fields...)
+ sbuild := &TextureSelect{TextureQuery: tq}
+ sbuild.label = texture.Label
+ sbuild.flds, sbuild.scan = &tq.ctx.Fields, sbuild.Scan
+ return sbuild
+}
+
+// Aggregate returns a TextureSelect configured with the given aggregations.
+func (tq *TextureQuery) Aggregate(fns ...AggregateFunc) *TextureSelect {
+ return tq.Select().Aggregate(fns...)
+}
+
+func (tq *TextureQuery) prepareQuery(ctx context.Context) error {
+ for _, inter := range tq.inters {
+ if inter == nil {
+ return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
+ }
+ if trv, ok := inter.(Traverser); ok {
+ if err := trv.Traverse(ctx, tq); err != nil {
+ return err
+ }
+ }
+ }
+ for _, f := range tq.ctx.Fields {
+ if !texture.ValidColumn(f) {
+ return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+ }
+ }
+ if tq.path != nil {
+ prev, err := tq.path(ctx)
+ if err != nil {
+ return err
+ }
+ tq.sql = prev
+ }
+ return nil
+}
+
+func (tq *TextureQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Texture, error) {
+ var (
+ nodes = []*Texture{}
+ withFKs = tq.withFKs
+ _spec = tq.querySpec()
+ loadedTypes = [3]bool{
+ tq.withCreatedUser != nil,
+ tq.withUserProfile != nil,
+ tq.withUsertexture != nil,
+ }
+ )
+ if tq.withCreatedUser != nil {
+ withFKs = true
+ }
+ if withFKs {
+ _spec.Node.Columns = append(_spec.Node.Columns, texture.ForeignKeys...)
+ }
+ _spec.ScanValues = func(columns []string) ([]any, error) {
+ return (*Texture).scanValues(nil, columns)
+ }
+ _spec.Assign = func(columns []string, values []any) error {
+ node := &Texture{config: tq.config}
+ nodes = append(nodes, node)
+ node.Edges.loadedTypes = loadedTypes
+ return node.assignValues(columns, values)
+ }
+ if len(tq.modifiers) > 0 {
+ _spec.Modifiers = tq.modifiers
+ }
+ for i := range hooks {
+ hooks[i](ctx, _spec)
+ }
+ if err := sqlgraph.QueryNodes(ctx, tq.driver, _spec); err != nil {
+ return nil, err
+ }
+ if len(nodes) == 0 {
+ return nodes, nil
+ }
+ if query := tq.withCreatedUser; query != nil {
+ if err := tq.loadCreatedUser(ctx, query, nodes, nil,
+ func(n *Texture, e *User) { n.Edges.CreatedUser = e }); err != nil {
+ return nil, err
+ }
+ }
+ if query := tq.withUserProfile; query != nil {
+ if err := tq.loadUserProfile(ctx, query, nodes,
+ func(n *Texture) { n.Edges.UserProfile = []*UserProfile{} },
+ func(n *Texture, e *UserProfile) { n.Edges.UserProfile = append(n.Edges.UserProfile, e) }); err != nil {
+ return nil, err
+ }
+ }
+ if query := tq.withUsertexture; query != nil {
+ if err := tq.loadUsertexture(ctx, query, nodes,
+ func(n *Texture) { n.Edges.Usertexture = []*UserTexture{} },
+ func(n *Texture, e *UserTexture) { n.Edges.Usertexture = append(n.Edges.Usertexture, e) }); err != nil {
+ return nil, err
+ }
+ }
+ return nodes, nil
+}
+
+func (tq *TextureQuery) loadCreatedUser(ctx context.Context, query *UserQuery, nodes []*Texture, init func(*Texture), assign func(*Texture, *User)) error {
+ ids := make([]int, 0, len(nodes))
+ nodeids := make(map[int][]*Texture)
+ for i := range nodes {
+ if nodes[i].texture_created_user == nil {
+ continue
+ }
+ fk := *nodes[i].texture_created_user
+ if _, ok := nodeids[fk]; !ok {
+ ids = append(ids, fk)
+ }
+ nodeids[fk] = append(nodeids[fk], nodes[i])
+ }
+ if len(ids) == 0 {
+ return nil
+ }
+ query.Where(user.IDIn(ids...))
+ neighbors, err := query.All(ctx)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ nodes, ok := nodeids[n.ID]
+ if !ok {
+ return fmt.Errorf(`unexpected foreign-key "texture_created_user" returned %v`, n.ID)
+ }
+ for i := range nodes {
+ assign(nodes[i], n)
+ }
+ }
+ return nil
+}
+func (tq *TextureQuery) loadUserProfile(ctx context.Context, query *UserProfileQuery, nodes []*Texture, init func(*Texture), assign func(*Texture, *UserProfile)) error {
+ edgeIDs := make([]driver.Value, len(nodes))
+ byID := make(map[int]*Texture)
+ nids := make(map[int]map[*Texture]struct{})
+ for i, node := range nodes {
+ edgeIDs[i] = node.ID
+ byID[node.ID] = node
+ if init != nil {
+ init(node)
+ }
+ }
+ query.Where(func(s *sql.Selector) {
+ joinT := sql.Table(texture.UserProfileTable)
+ s.Join(joinT).On(s.C(userprofile.FieldID), joinT.C(texture.UserProfilePrimaryKey[1]))
+ s.Where(sql.InValues(joinT.C(texture.UserProfilePrimaryKey[0]), edgeIDs...))
+ columns := s.SelectedColumns()
+ s.Select(joinT.C(texture.UserProfilePrimaryKey[0]))
+ s.AppendSelect(columns...)
+ s.SetDistinct(false)
+ })
+ if err := query.prepareQuery(ctx); err != nil {
+ return err
+ }
+ qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
+ return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) {
+ assign := spec.Assign
+ values := spec.ScanValues
+ spec.ScanValues = func(columns []string) ([]any, error) {
+ values, err := values(columns[1:])
+ if err != nil {
+ return nil, err
+ }
+ return append([]any{new(sql.NullInt64)}, values...), nil
+ }
+ spec.Assign = func(columns []string, values []any) error {
+ outValue := int(values[0].(*sql.NullInt64).Int64)
+ inValue := int(values[1].(*sql.NullInt64).Int64)
+ if nids[inValue] == nil {
+ nids[inValue] = map[*Texture]struct{}{byID[outValue]: {}}
+ return assign(columns[1:], values[1:])
+ }
+ nids[inValue][byID[outValue]] = struct{}{}
+ return nil
+ }
+ })
+ })
+ neighbors, err := withInterceptors[[]*UserProfile](ctx, query, qr, query.inters)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ nodes, ok := nids[n.ID]
+ if !ok {
+ return fmt.Errorf(`unexpected "user_profile" node returned %v`, n.ID)
+ }
+ for kn := range nodes {
+ assign(kn, n)
+ }
+ }
+ return nil
+}
+func (tq *TextureQuery) loadUsertexture(ctx context.Context, query *UserTextureQuery, nodes []*Texture, init func(*Texture), assign func(*Texture, *UserTexture)) error {
+ fks := make([]driver.Value, 0, len(nodes))
+ nodeids := make(map[int]*Texture)
+ for i := range nodes {
+ fks = append(fks, nodes[i].ID)
+ nodeids[nodes[i].ID] = nodes[i]
+ if init != nil {
+ init(nodes[i])
+ }
+ }
+ if len(query.ctx.Fields) > 0 {
+ query.ctx.AppendFieldOnce(usertexture.FieldTextureID)
+ }
+ query.Where(predicate.UserTexture(func(s *sql.Selector) {
+ s.Where(sql.InValues(s.C(texture.UsertextureColumn), fks...))
+ }))
+ neighbors, err := query.All(ctx)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ fk := n.TextureID
+ node, ok := nodeids[fk]
+ if !ok {
+ return fmt.Errorf(`unexpected referenced foreign-key "texture_id" returned %v for node %v`, fk, n.ID)
+ }
+ assign(node, n)
+ }
+ return nil
+}
+
+func (tq *TextureQuery) sqlCount(ctx context.Context) (int, error) {
+ _spec := tq.querySpec()
+ if len(tq.modifiers) > 0 {
+ _spec.Modifiers = tq.modifiers
+ }
+ _spec.Node.Columns = tq.ctx.Fields
+ if len(tq.ctx.Fields) > 0 {
+ _spec.Unique = tq.ctx.Unique != nil && *tq.ctx.Unique
+ }
+ return sqlgraph.CountNodes(ctx, tq.driver, _spec)
+}
+
+func (tq *TextureQuery) querySpec() *sqlgraph.QuerySpec {
+ _spec := sqlgraph.NewQuerySpec(texture.Table, texture.Columns, sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt))
+ _spec.From = tq.sql
+ if unique := tq.ctx.Unique; unique != nil {
+ _spec.Unique = *unique
+ } else if tq.path != nil {
+ _spec.Unique = true
+ }
+ if fields := tq.ctx.Fields; len(fields) > 0 {
+ _spec.Node.Columns = make([]string, 0, len(fields))
+ _spec.Node.Columns = append(_spec.Node.Columns, texture.FieldID)
+ for i := range fields {
+ if fields[i] != texture.FieldID {
+ _spec.Node.Columns = append(_spec.Node.Columns, fields[i])
+ }
+ }
+ }
+ if ps := tq.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if limit := tq.ctx.Limit; limit != nil {
+ _spec.Limit = *limit
+ }
+ if offset := tq.ctx.Offset; offset != nil {
+ _spec.Offset = *offset
+ }
+ if ps := tq.order; len(ps) > 0 {
+ _spec.Order = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ return _spec
+}
+
+func (tq *TextureQuery) sqlQuery(ctx context.Context) *sql.Selector {
+ builder := sql.Dialect(tq.driver.Dialect())
+ t1 := builder.Table(texture.Table)
+ columns := tq.ctx.Fields
+ if len(columns) == 0 {
+ columns = texture.Columns
+ }
+ selector := builder.Select(t1.Columns(columns...)...).From(t1)
+ if tq.sql != nil {
+ selector = tq.sql
+ selector.Select(selector.Columns(columns...)...)
+ }
+ if tq.ctx.Unique != nil && *tq.ctx.Unique {
+ selector.Distinct()
+ }
+ for _, m := range tq.modifiers {
+ m(selector)
+ }
+ for _, p := range tq.predicates {
+ p(selector)
+ }
+ for _, p := range tq.order {
+ p(selector)
+ }
+ if offset := tq.ctx.Offset; offset != nil {
+ // limit is mandatory for offset clause. We start
+ // with default value, and override it below if needed.
+ selector.Offset(*offset).Limit(math.MaxInt32)
+ }
+ if limit := tq.ctx.Limit; limit != nil {
+ selector.Limit(*limit)
+ }
+ return selector
+}
+
+// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
+// updated, deleted or "selected ... for update" by other sessions, until the transaction is
+// either committed or rolled-back.
+func (tq *TextureQuery) ForUpdate(opts ...sql.LockOption) *TextureQuery {
+ if tq.driver.Dialect() == dialect.Postgres {
+ tq.Unique(false)
+ }
+ tq.modifiers = append(tq.modifiers, func(s *sql.Selector) {
+ s.ForUpdate(opts...)
+ })
+ return tq
+}
+
+// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
+// on any rows that are read. Other sessions can read the rows, but cannot modify them
+// until your transaction commits.
+func (tq *TextureQuery) ForShare(opts ...sql.LockOption) *TextureQuery {
+ if tq.driver.Dialect() == dialect.Postgres {
+ tq.Unique(false)
+ }
+ tq.modifiers = append(tq.modifiers, func(s *sql.Selector) {
+ s.ForShare(opts...)
+ })
+ return tq
+}
+
+// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
+// updated, deleted or "selected ... for update" by other sessions, until the transaction is
+// either committed or rolled-back.
+func (tq *TextureQuery) ForUpdateA(opts ...sql.LockOption) *TextureQuery {
+ if tq.driver.Dialect() == dialect.SQLite {
+ return tq
+ }
+ return tq.ForUpdate(opts...)
+}
+
+// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
+// on any rows that are read. Other sessions can read the rows, but cannot modify them
+// until your transaction commits.
+func (tq *TextureQuery) ForShareA(opts ...sql.LockOption) *TextureQuery {
+ if tq.driver.Dialect() == dialect.SQLite {
+ return tq
+ }
+ return tq.ForShare(opts...)
+}
+
+// TextureGroupBy is the group-by builder for Texture entities.
+type TextureGroupBy struct {
+ selector
+ build *TextureQuery
+}
+
+// Aggregate adds the given aggregation functions to the group-by query.
+func (tgb *TextureGroupBy) Aggregate(fns ...AggregateFunc) *TextureGroupBy {
+ tgb.fns = append(tgb.fns, fns...)
+ return tgb
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (tgb *TextureGroupBy) Scan(ctx context.Context, v any) error {
+ ctx = setContextOp(ctx, tgb.build.ctx, "GroupBy")
+ if err := tgb.build.prepareQuery(ctx); err != nil {
+ return err
+ }
+ return scanWithInterceptors[*TextureQuery, *TextureGroupBy](ctx, tgb.build, tgb, tgb.build.inters, v)
+}
+
+func (tgb *TextureGroupBy) sqlScan(ctx context.Context, root *TextureQuery, v any) error {
+ selector := root.sqlQuery(ctx).Select()
+ aggregation := make([]string, 0, len(tgb.fns))
+ for _, fn := range tgb.fns {
+ aggregation = append(aggregation, fn(selector))
+ }
+ if len(selector.SelectedColumns()) == 0 {
+ columns := make([]string, 0, len(*tgb.flds)+len(tgb.fns))
+ for _, f := range *tgb.flds {
+ columns = append(columns, selector.C(f))
+ }
+ columns = append(columns, aggregation...)
+ selector.Select(columns...)
+ }
+ selector.GroupBy(selector.Columns(*tgb.flds...)...)
+ if err := selector.Err(); err != nil {
+ return err
+ }
+ rows := &sql.Rows{}
+ query, args := selector.Query()
+ if err := tgb.build.driver.Query(ctx, query, args, rows); err != nil {
+ return err
+ }
+ defer rows.Close()
+ return sql.ScanSlice(rows, v)
+}
+
+// TextureSelect is the builder for selecting fields of Texture entities.
+type TextureSelect struct {
+ *TextureQuery
+ selector
+}
+
+// Aggregate adds the given aggregation functions to the selector query.
+func (ts *TextureSelect) Aggregate(fns ...AggregateFunc) *TextureSelect {
+ ts.fns = append(ts.fns, fns...)
+ return ts
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (ts *TextureSelect) Scan(ctx context.Context, v any) error {
+ ctx = setContextOp(ctx, ts.ctx, "Select")
+ if err := ts.prepareQuery(ctx); err != nil {
+ return err
+ }
+ return scanWithInterceptors[*TextureQuery, *TextureSelect](ctx, ts.TextureQuery, ts, ts.inters, v)
+}
+
+func (ts *TextureSelect) sqlScan(ctx context.Context, root *TextureQuery, v any) error {
+ selector := root.sqlQuery(ctx)
+ aggregation := make([]string, 0, len(ts.fns))
+ for _, fn := range ts.fns {
+ aggregation = append(aggregation, fn(selector))
+ }
+ switch n := len(*ts.selector.flds); {
+ case n == 0 && len(aggregation) > 0:
+ selector.Select(aggregation...)
+ case n != 0 && len(aggregation) > 0:
+ selector.AppendSelect(aggregation...)
+ }
+ rows := &sql.Rows{}
+ query, args := selector.Query()
+ if err := ts.driver.Query(ctx, query, args, rows); err != nil {
+ return err
+ }
+ defer rows.Close()
+ return sql.ScanSlice(rows, v)
+}
diff --git a/db/ent/texture_update.go b/db/ent/texture_update.go
new file mode 100644
index 0000000..359cf71
--- /dev/null
+++ b/db/ent/texture_update.go
@@ -0,0 +1,634 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+)
+
+// TextureUpdate is the builder for updating Texture entities.
+type TextureUpdate struct {
+ config
+ hooks []Hook
+ mutation *TextureMutation
+}
+
+// Where appends a list predicates to the TextureUpdate builder.
+func (tu *TextureUpdate) Where(ps ...predicate.Texture) *TextureUpdate {
+ tu.mutation.Where(ps...)
+ return tu
+}
+
+// SetTextureHash sets the "texture_hash" field.
+func (tu *TextureUpdate) SetTextureHash(s string) *TextureUpdate {
+ tu.mutation.SetTextureHash(s)
+ return tu
+}
+
+// SetCreatedUserID sets the "created_user" edge to the User entity by ID.
+func (tu *TextureUpdate) SetCreatedUserID(id int) *TextureUpdate {
+ tu.mutation.SetCreatedUserID(id)
+ return tu
+}
+
+// SetCreatedUser sets the "created_user" edge to the User entity.
+func (tu *TextureUpdate) SetCreatedUser(u *User) *TextureUpdate {
+ return tu.SetCreatedUserID(u.ID)
+}
+
+// AddUserProfileIDs adds the "user_profile" edge to the UserProfile entity by IDs.
+func (tu *TextureUpdate) AddUserProfileIDs(ids ...int) *TextureUpdate {
+ tu.mutation.AddUserProfileIDs(ids...)
+ return tu
+}
+
+// AddUserProfile adds the "user_profile" edges to the UserProfile entity.
+func (tu *TextureUpdate) AddUserProfile(u ...*UserProfile) *TextureUpdate {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return tu.AddUserProfileIDs(ids...)
+}
+
+// AddUsertextureIDs adds the "usertexture" edge to the UserTexture entity by IDs.
+func (tu *TextureUpdate) AddUsertextureIDs(ids ...int) *TextureUpdate {
+ tu.mutation.AddUsertextureIDs(ids...)
+ return tu
+}
+
+// AddUsertexture adds the "usertexture" edges to the UserTexture entity.
+func (tu *TextureUpdate) AddUsertexture(u ...*UserTexture) *TextureUpdate {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return tu.AddUsertextureIDs(ids...)
+}
+
+// Mutation returns the TextureMutation object of the builder.
+func (tu *TextureUpdate) Mutation() *TextureMutation {
+ return tu.mutation
+}
+
+// ClearCreatedUser clears the "created_user" edge to the User entity.
+func (tu *TextureUpdate) ClearCreatedUser() *TextureUpdate {
+ tu.mutation.ClearCreatedUser()
+ return tu
+}
+
+// ClearUserProfile clears all "user_profile" edges to the UserProfile entity.
+func (tu *TextureUpdate) ClearUserProfile() *TextureUpdate {
+ tu.mutation.ClearUserProfile()
+ return tu
+}
+
+// RemoveUserProfileIDs removes the "user_profile" edge to UserProfile entities by IDs.
+func (tu *TextureUpdate) RemoveUserProfileIDs(ids ...int) *TextureUpdate {
+ tu.mutation.RemoveUserProfileIDs(ids...)
+ return tu
+}
+
+// RemoveUserProfile removes "user_profile" edges to UserProfile entities.
+func (tu *TextureUpdate) RemoveUserProfile(u ...*UserProfile) *TextureUpdate {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return tu.RemoveUserProfileIDs(ids...)
+}
+
+// ClearUsertexture clears all "usertexture" edges to the UserTexture entity.
+func (tu *TextureUpdate) ClearUsertexture() *TextureUpdate {
+ tu.mutation.ClearUsertexture()
+ return tu
+}
+
+// RemoveUsertextureIDs removes the "usertexture" edge to UserTexture entities by IDs.
+func (tu *TextureUpdate) RemoveUsertextureIDs(ids ...int) *TextureUpdate {
+ tu.mutation.RemoveUsertextureIDs(ids...)
+ return tu
+}
+
+// RemoveUsertexture removes "usertexture" edges to UserTexture entities.
+func (tu *TextureUpdate) RemoveUsertexture(u ...*UserTexture) *TextureUpdate {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return tu.RemoveUsertextureIDs(ids...)
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (tu *TextureUpdate) Save(ctx context.Context) (int, error) {
+ return withHooks(ctx, tu.sqlSave, tu.mutation, tu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (tu *TextureUpdate) SaveX(ctx context.Context) int {
+ affected, err := tu.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return affected
+}
+
+// Exec executes the query.
+func (tu *TextureUpdate) Exec(ctx context.Context) error {
+ _, err := tu.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (tu *TextureUpdate) ExecX(ctx context.Context) {
+ if err := tu.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (tu *TextureUpdate) check() error {
+ if _, ok := tu.mutation.CreatedUserID(); tu.mutation.CreatedUserCleared() && !ok {
+ return errors.New(`ent: clearing a required unique edge "Texture.created_user"`)
+ }
+ return nil
+}
+
+func (tu *TextureUpdate) sqlSave(ctx context.Context) (n int, err error) {
+ if err := tu.check(); err != nil {
+ return n, err
+ }
+ _spec := sqlgraph.NewUpdateSpec(texture.Table, texture.Columns, sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt))
+ if ps := tu.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if value, ok := tu.mutation.TextureHash(); ok {
+ _spec.SetField(texture.FieldTextureHash, field.TypeString, value)
+ }
+ if tu.mutation.CreatedUserCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: texture.CreatedUserTable,
+ Columns: []string{texture.CreatedUserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := tu.mutation.CreatedUserIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: texture.CreatedUserTable,
+ Columns: []string{texture.CreatedUserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if tu.mutation.UserProfileCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: false,
+ Table: texture.UserProfileTable,
+ Columns: texture.UserProfilePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := tu.mutation.RemovedUserProfileIDs(); len(nodes) > 0 && !tu.mutation.UserProfileCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: false,
+ Table: texture.UserProfileTable,
+ Columns: texture.UserProfilePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := tu.mutation.UserProfileIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: false,
+ Table: texture.UserProfileTable,
+ Columns: texture.UserProfilePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if tu.mutation.UsertextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: texture.UsertextureTable,
+ Columns: []string{texture.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := tu.mutation.RemovedUsertextureIDs(); len(nodes) > 0 && !tu.mutation.UsertextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: texture.UsertextureTable,
+ Columns: []string{texture.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := tu.mutation.UsertextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: texture.UsertextureTable,
+ Columns: []string{texture.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if n, err = sqlgraph.UpdateNodes(ctx, tu.driver, _spec); err != nil {
+ if _, ok := err.(*sqlgraph.NotFoundError); ok {
+ err = &NotFoundError{texture.Label}
+ } else if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return 0, err
+ }
+ tu.mutation.done = true
+ return n, nil
+}
+
+// TextureUpdateOne is the builder for updating a single Texture entity.
+type TextureUpdateOne struct {
+ config
+ fields []string
+ hooks []Hook
+ mutation *TextureMutation
+}
+
+// SetTextureHash sets the "texture_hash" field.
+func (tuo *TextureUpdateOne) SetTextureHash(s string) *TextureUpdateOne {
+ tuo.mutation.SetTextureHash(s)
+ return tuo
+}
+
+// SetCreatedUserID sets the "created_user" edge to the User entity by ID.
+func (tuo *TextureUpdateOne) SetCreatedUserID(id int) *TextureUpdateOne {
+ tuo.mutation.SetCreatedUserID(id)
+ return tuo
+}
+
+// SetCreatedUser sets the "created_user" edge to the User entity.
+func (tuo *TextureUpdateOne) SetCreatedUser(u *User) *TextureUpdateOne {
+ return tuo.SetCreatedUserID(u.ID)
+}
+
+// AddUserProfileIDs adds the "user_profile" edge to the UserProfile entity by IDs.
+func (tuo *TextureUpdateOne) AddUserProfileIDs(ids ...int) *TextureUpdateOne {
+ tuo.mutation.AddUserProfileIDs(ids...)
+ return tuo
+}
+
+// AddUserProfile adds the "user_profile" edges to the UserProfile entity.
+func (tuo *TextureUpdateOne) AddUserProfile(u ...*UserProfile) *TextureUpdateOne {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return tuo.AddUserProfileIDs(ids...)
+}
+
+// AddUsertextureIDs adds the "usertexture" edge to the UserTexture entity by IDs.
+func (tuo *TextureUpdateOne) AddUsertextureIDs(ids ...int) *TextureUpdateOne {
+ tuo.mutation.AddUsertextureIDs(ids...)
+ return tuo
+}
+
+// AddUsertexture adds the "usertexture" edges to the UserTexture entity.
+func (tuo *TextureUpdateOne) AddUsertexture(u ...*UserTexture) *TextureUpdateOne {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return tuo.AddUsertextureIDs(ids...)
+}
+
+// Mutation returns the TextureMutation object of the builder.
+func (tuo *TextureUpdateOne) Mutation() *TextureMutation {
+ return tuo.mutation
+}
+
+// ClearCreatedUser clears the "created_user" edge to the User entity.
+func (tuo *TextureUpdateOne) ClearCreatedUser() *TextureUpdateOne {
+ tuo.mutation.ClearCreatedUser()
+ return tuo
+}
+
+// ClearUserProfile clears all "user_profile" edges to the UserProfile entity.
+func (tuo *TextureUpdateOne) ClearUserProfile() *TextureUpdateOne {
+ tuo.mutation.ClearUserProfile()
+ return tuo
+}
+
+// RemoveUserProfileIDs removes the "user_profile" edge to UserProfile entities by IDs.
+func (tuo *TextureUpdateOne) RemoveUserProfileIDs(ids ...int) *TextureUpdateOne {
+ tuo.mutation.RemoveUserProfileIDs(ids...)
+ return tuo
+}
+
+// RemoveUserProfile removes "user_profile" edges to UserProfile entities.
+func (tuo *TextureUpdateOne) RemoveUserProfile(u ...*UserProfile) *TextureUpdateOne {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return tuo.RemoveUserProfileIDs(ids...)
+}
+
+// ClearUsertexture clears all "usertexture" edges to the UserTexture entity.
+func (tuo *TextureUpdateOne) ClearUsertexture() *TextureUpdateOne {
+ tuo.mutation.ClearUsertexture()
+ return tuo
+}
+
+// RemoveUsertextureIDs removes the "usertexture" edge to UserTexture entities by IDs.
+func (tuo *TextureUpdateOne) RemoveUsertextureIDs(ids ...int) *TextureUpdateOne {
+ tuo.mutation.RemoveUsertextureIDs(ids...)
+ return tuo
+}
+
+// RemoveUsertexture removes "usertexture" edges to UserTexture entities.
+func (tuo *TextureUpdateOne) RemoveUsertexture(u ...*UserTexture) *TextureUpdateOne {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return tuo.RemoveUsertextureIDs(ids...)
+}
+
+// Where appends a list predicates to the TextureUpdate builder.
+func (tuo *TextureUpdateOne) Where(ps ...predicate.Texture) *TextureUpdateOne {
+ tuo.mutation.Where(ps...)
+ return tuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (tuo *TextureUpdateOne) Select(field string, fields ...string) *TextureUpdateOne {
+ tuo.fields = append([]string{field}, fields...)
+ return tuo
+}
+
+// Save executes the query and returns the updated Texture entity.
+func (tuo *TextureUpdateOne) Save(ctx context.Context) (*Texture, error) {
+ return withHooks(ctx, tuo.sqlSave, tuo.mutation, tuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (tuo *TextureUpdateOne) SaveX(ctx context.Context) *Texture {
+ node, err := tuo.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return node
+}
+
+// Exec executes the query on the entity.
+func (tuo *TextureUpdateOne) Exec(ctx context.Context) error {
+ _, err := tuo.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (tuo *TextureUpdateOne) ExecX(ctx context.Context) {
+ if err := tuo.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (tuo *TextureUpdateOne) check() error {
+ if _, ok := tuo.mutation.CreatedUserID(); tuo.mutation.CreatedUserCleared() && !ok {
+ return errors.New(`ent: clearing a required unique edge "Texture.created_user"`)
+ }
+ return nil
+}
+
+func (tuo *TextureUpdateOne) sqlSave(ctx context.Context) (_node *Texture, err error) {
+ if err := tuo.check(); err != nil {
+ return _node, err
+ }
+ _spec := sqlgraph.NewUpdateSpec(texture.Table, texture.Columns, sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt))
+ id, ok := tuo.mutation.ID()
+ if !ok {
+ return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Texture.id" for update`)}
+ }
+ _spec.Node.ID.Value = id
+ if fields := tuo.fields; len(fields) > 0 {
+ _spec.Node.Columns = make([]string, 0, len(fields))
+ _spec.Node.Columns = append(_spec.Node.Columns, texture.FieldID)
+ for _, f := range fields {
+ if !texture.ValidColumn(f) {
+ return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+ }
+ if f != texture.FieldID {
+ _spec.Node.Columns = append(_spec.Node.Columns, f)
+ }
+ }
+ }
+ if ps := tuo.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if value, ok := tuo.mutation.TextureHash(); ok {
+ _spec.SetField(texture.FieldTextureHash, field.TypeString, value)
+ }
+ if tuo.mutation.CreatedUserCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: texture.CreatedUserTable,
+ Columns: []string{texture.CreatedUserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := tuo.mutation.CreatedUserIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: texture.CreatedUserTable,
+ Columns: []string{texture.CreatedUserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if tuo.mutation.UserProfileCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: false,
+ Table: texture.UserProfileTable,
+ Columns: texture.UserProfilePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := tuo.mutation.RemovedUserProfileIDs(); len(nodes) > 0 && !tuo.mutation.UserProfileCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: false,
+ Table: texture.UserProfileTable,
+ Columns: texture.UserProfilePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := tuo.mutation.UserProfileIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: false,
+ Table: texture.UserProfileTable,
+ Columns: texture.UserProfilePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if tuo.mutation.UsertextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: texture.UsertextureTable,
+ Columns: []string{texture.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := tuo.mutation.RemovedUsertextureIDs(); len(nodes) > 0 && !tuo.mutation.UsertextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: texture.UsertextureTable,
+ Columns: []string{texture.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := tuo.mutation.UsertextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: texture.UsertextureTable,
+ Columns: []string{texture.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ _node = &Texture{config: tuo.config}
+ _spec.Assign = _node.assignValues
+ _spec.ScanValues = _node.scanValues
+ if err = sqlgraph.UpdateNode(ctx, tuo.driver, _spec); err != nil {
+ if _, ok := err.(*sqlgraph.NotFoundError); ok {
+ err = &NotFoundError{texture.Label}
+ } else if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return nil, err
+ }
+ tuo.mutation.done = true
+ return _node, nil
+}
diff --git a/db/ent/tx.go b/db/ent/tx.go
new file mode 100644
index 0000000..11b4d49
--- /dev/null
+++ b/db/ent/tx.go
@@ -0,0 +1,222 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "sync"
+
+ "entgo.io/ent/dialect"
+)
+
+// Tx is a transactional client that is created by calling Client.Tx().
+type Tx struct {
+ config
+ // Texture is the client for interacting with the Texture builders.
+ Texture *TextureClient
+ // User is the client for interacting with the User builders.
+ User *UserClient
+ // UserProfile is the client for interacting with the UserProfile builders.
+ UserProfile *UserProfileClient
+ // UserTexture is the client for interacting with the UserTexture builders.
+ UserTexture *UserTextureClient
+ // UserToken is the client for interacting with the UserToken builders.
+ UserToken *UserTokenClient
+
+ // lazily loaded.
+ client *Client
+ clientOnce sync.Once
+ // ctx lives for the life of the transaction. It is
+ // the same context used by the underlying connection.
+ ctx context.Context
+}
+
+type (
+ // Committer is the interface that wraps the Commit method.
+ Committer interface {
+ Commit(context.Context, *Tx) error
+ }
+
+ // The CommitFunc type is an adapter to allow the use of ordinary
+ // function as a Committer. If f is a function with the appropriate
+ // signature, CommitFunc(f) is a Committer that calls f.
+ CommitFunc func(context.Context, *Tx) error
+
+ // CommitHook defines the "commit middleware". A function that gets a Committer
+ // and returns a Committer. For example:
+ //
+ // hook := func(next ent.Committer) ent.Committer {
+ // return ent.CommitFunc(func(ctx context.Context, tx *ent.Tx) error {
+ // // Do some stuff before.
+ // if err := next.Commit(ctx, tx); err != nil {
+ // return err
+ // }
+ // // Do some stuff after.
+ // return nil
+ // })
+ // }
+ //
+ CommitHook func(Committer) Committer
+)
+
+// Commit calls f(ctx, m).
+func (f CommitFunc) Commit(ctx context.Context, tx *Tx) error {
+ return f(ctx, tx)
+}
+
+// Commit commits the transaction.
+func (tx *Tx) Commit() error {
+ txDriver := tx.config.driver.(*txDriver)
+ var fn Committer = CommitFunc(func(context.Context, *Tx) error {
+ return txDriver.tx.Commit()
+ })
+ txDriver.mu.Lock()
+ hooks := append([]CommitHook(nil), txDriver.onCommit...)
+ txDriver.mu.Unlock()
+ for i := len(hooks) - 1; i >= 0; i-- {
+ fn = hooks[i](fn)
+ }
+ return fn.Commit(tx.ctx, tx)
+}
+
+// OnCommit adds a hook to call on commit.
+func (tx *Tx) OnCommit(f CommitHook) {
+ txDriver := tx.config.driver.(*txDriver)
+ txDriver.mu.Lock()
+ txDriver.onCommit = append(txDriver.onCommit, f)
+ txDriver.mu.Unlock()
+}
+
+type (
+ // Rollbacker is the interface that wraps the Rollback method.
+ Rollbacker interface {
+ Rollback(context.Context, *Tx) error
+ }
+
+ // The RollbackFunc type is an adapter to allow the use of ordinary
+ // function as a Rollbacker. If f is a function with the appropriate
+ // signature, RollbackFunc(f) is a Rollbacker that calls f.
+ RollbackFunc func(context.Context, *Tx) error
+
+ // RollbackHook defines the "rollback middleware". A function that gets a Rollbacker
+ // and returns a Rollbacker. For example:
+ //
+ // hook := func(next ent.Rollbacker) ent.Rollbacker {
+ // return ent.RollbackFunc(func(ctx context.Context, tx *ent.Tx) error {
+ // // Do some stuff before.
+ // if err := next.Rollback(ctx, tx); err != nil {
+ // return err
+ // }
+ // // Do some stuff after.
+ // return nil
+ // })
+ // }
+ //
+ RollbackHook func(Rollbacker) Rollbacker
+)
+
+// Rollback calls f(ctx, m).
+func (f RollbackFunc) Rollback(ctx context.Context, tx *Tx) error {
+ return f(ctx, tx)
+}
+
+// Rollback rollbacks the transaction.
+func (tx *Tx) Rollback() error {
+ txDriver := tx.config.driver.(*txDriver)
+ var fn Rollbacker = RollbackFunc(func(context.Context, *Tx) error {
+ return txDriver.tx.Rollback()
+ })
+ txDriver.mu.Lock()
+ hooks := append([]RollbackHook(nil), txDriver.onRollback...)
+ txDriver.mu.Unlock()
+ for i := len(hooks) - 1; i >= 0; i-- {
+ fn = hooks[i](fn)
+ }
+ return fn.Rollback(tx.ctx, tx)
+}
+
+// OnRollback adds a hook to call on rollback.
+func (tx *Tx) OnRollback(f RollbackHook) {
+ txDriver := tx.config.driver.(*txDriver)
+ txDriver.mu.Lock()
+ txDriver.onRollback = append(txDriver.onRollback, f)
+ txDriver.mu.Unlock()
+}
+
+// Client returns a Client that binds to current transaction.
+func (tx *Tx) Client() *Client {
+ tx.clientOnce.Do(func() {
+ tx.client = &Client{config: tx.config}
+ tx.client.init()
+ })
+ return tx.client
+}
+
+func (tx *Tx) init() {
+ tx.Texture = NewTextureClient(tx.config)
+ tx.User = NewUserClient(tx.config)
+ tx.UserProfile = NewUserProfileClient(tx.config)
+ tx.UserTexture = NewUserTextureClient(tx.config)
+ tx.UserToken = NewUserTokenClient(tx.config)
+}
+
+// txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation.
+// The idea is to support transactions without adding any extra code to the builders.
+// When a builder calls to driver.Tx(), it gets the same dialect.Tx instance.
+// Commit and Rollback are nop for the internal builders and the user must call one
+// of them in order to commit or rollback the transaction.
+//
+// If a closed transaction is embedded in one of the generated entities, and the entity
+// applies a query, for example: Texture.QueryXXX(), the query will be executed
+// through the driver which created this transaction.
+//
+// Note that txDriver is not goroutine safe.
+type txDriver struct {
+ // the driver we started the transaction from.
+ drv dialect.Driver
+ // tx is the underlying transaction.
+ tx dialect.Tx
+ // completion hooks.
+ mu sync.Mutex
+ onCommit []CommitHook
+ onRollback []RollbackHook
+}
+
+// newTx creates a new transactional driver.
+func newTx(ctx context.Context, drv dialect.Driver) (*txDriver, error) {
+ tx, err := drv.Tx(ctx)
+ if err != nil {
+ return nil, err
+ }
+ return &txDriver{tx: tx, drv: drv}, nil
+}
+
+// Tx returns the transaction wrapper (txDriver) to avoid Commit or Rollback calls
+// from the internal builders. Should be called only by the internal builders.
+func (tx *txDriver) Tx(context.Context) (dialect.Tx, error) { return tx, nil }
+
+// Dialect returns the dialect of the driver we started the transaction from.
+func (tx *txDriver) Dialect() string { return tx.drv.Dialect() }
+
+// Close is a nop close.
+func (*txDriver) Close() error { return nil }
+
+// Commit is a nop commit for the internal builders.
+// User must call `Tx.Commit` in order to commit the transaction.
+func (*txDriver) Commit() error { return nil }
+
+// Rollback is a nop rollback for the internal builders.
+// User must call `Tx.Rollback` in order to rollback the transaction.
+func (*txDriver) Rollback() error { return nil }
+
+// Exec calls tx.Exec.
+func (tx *txDriver) Exec(ctx context.Context, query string, args, v any) error {
+ return tx.tx.Exec(ctx, query, args, v)
+}
+
+// Query calls tx.Query.
+func (tx *txDriver) Query(ctx context.Context, query string, args, v any) error {
+ return tx.tx.Query(ctx, query, args, v)
+}
+
+var _ dialect.Driver = (*txDriver)(nil)
diff --git a/db/ent/user.go b/db/ent/user.go
new file mode 100644
index 0000000..21ff390
--- /dev/null
+++ b/db/ent/user.go
@@ -0,0 +1,226 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "fmt"
+ "strings"
+
+ "entgo.io/ent"
+ "entgo.io/ent/dialect/sql"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+// User is the model entity for the User schema.
+type User struct {
+ config `json:"-"`
+ // ID of the ent.
+ ID int `json:"id,omitempty"`
+ // Email holds the value of the "email" field.
+ Email string `json:"email,omitempty"`
+ // Password holds the value of the "password" field.
+ Password string `json:"password,omitempty"`
+ // Salt holds the value of the "salt" field.
+ Salt string `json:"salt,omitempty"`
+ // RegIP holds the value of the "reg_ip" field.
+ RegIP string `json:"reg_ip,omitempty"`
+ // State holds the value of the "state" field.
+ State int `json:"state,omitempty"`
+ // RegTime holds the value of the "reg_time" field.
+ RegTime int64 `json:"reg_time,omitempty"`
+ // Edges holds the relations/edges for other nodes in the graph.
+ // The values are being populated by the UserQuery when eager-loading is set.
+ Edges UserEdges `json:"edges"`
+ selectValues sql.SelectValues
+}
+
+// UserEdges holds the relations/edges for other nodes in the graph.
+type UserEdges struct {
+ // CreatedTexture holds the value of the created_texture edge.
+ CreatedTexture []*Texture `json:"created_texture,omitempty"`
+ // Profile holds the value of the profile edge.
+ Profile *UserProfile `json:"profile,omitempty"`
+ // Token holds the value of the token edge.
+ Token *UserToken `json:"token,omitempty"`
+ // loadedTypes holds the information for reporting if a
+ // type was loaded (or requested) in eager-loading or not.
+ loadedTypes [3]bool
+}
+
+// CreatedTextureOrErr returns the CreatedTexture value or an error if the edge
+// was not loaded in eager-loading.
+func (e UserEdges) CreatedTextureOrErr() ([]*Texture, error) {
+ if e.loadedTypes[0] {
+ return e.CreatedTexture, nil
+ }
+ return nil, &NotLoadedError{edge: "created_texture"}
+}
+
+// ProfileOrErr returns the Profile value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e UserEdges) ProfileOrErr() (*UserProfile, error) {
+ if e.loadedTypes[1] {
+ if e.Profile == nil {
+ // Edge was loaded but was not found.
+ return nil, &NotFoundError{label: userprofile.Label}
+ }
+ return e.Profile, nil
+ }
+ return nil, &NotLoadedError{edge: "profile"}
+}
+
+// TokenOrErr returns the Token value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e UserEdges) TokenOrErr() (*UserToken, error) {
+ if e.loadedTypes[2] {
+ if e.Token == nil {
+ // Edge was loaded but was not found.
+ return nil, &NotFoundError{label: usertoken.Label}
+ }
+ return e.Token, nil
+ }
+ return nil, &NotLoadedError{edge: "token"}
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*User) scanValues(columns []string) ([]any, error) {
+ values := make([]any, len(columns))
+ for i := range columns {
+ switch columns[i] {
+ case user.FieldID, user.FieldState, user.FieldRegTime:
+ values[i] = new(sql.NullInt64)
+ case user.FieldEmail, user.FieldPassword, user.FieldSalt, user.FieldRegIP:
+ values[i] = new(sql.NullString)
+ default:
+ values[i] = new(sql.UnknownType)
+ }
+ }
+ return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the User fields.
+func (u *User) assignValues(columns []string, values []any) error {
+ if m, n := len(values), len(columns); m < n {
+ return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+ }
+ for i := range columns {
+ switch columns[i] {
+ case user.FieldID:
+ value, ok := values[i].(*sql.NullInt64)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field id", value)
+ }
+ u.ID = int(value.Int64)
+ case user.FieldEmail:
+ if value, ok := values[i].(*sql.NullString); !ok {
+ return fmt.Errorf("unexpected type %T for field email", values[i])
+ } else if value.Valid {
+ u.Email = value.String
+ }
+ case user.FieldPassword:
+ if value, ok := values[i].(*sql.NullString); !ok {
+ return fmt.Errorf("unexpected type %T for field password", values[i])
+ } else if value.Valid {
+ u.Password = value.String
+ }
+ case user.FieldSalt:
+ if value, ok := values[i].(*sql.NullString); !ok {
+ return fmt.Errorf("unexpected type %T for field salt", values[i])
+ } else if value.Valid {
+ u.Salt = value.String
+ }
+ case user.FieldRegIP:
+ if value, ok := values[i].(*sql.NullString); !ok {
+ return fmt.Errorf("unexpected type %T for field reg_ip", values[i])
+ } else if value.Valid {
+ u.RegIP = value.String
+ }
+ case user.FieldState:
+ if value, ok := values[i].(*sql.NullInt64); !ok {
+ return fmt.Errorf("unexpected type %T for field state", values[i])
+ } else if value.Valid {
+ u.State = int(value.Int64)
+ }
+ case user.FieldRegTime:
+ if value, ok := values[i].(*sql.NullInt64); !ok {
+ return fmt.Errorf("unexpected type %T for field reg_time", values[i])
+ } else if value.Valid {
+ u.RegTime = value.Int64
+ }
+ default:
+ u.selectValues.Set(columns[i], values[i])
+ }
+ }
+ return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the User.
+// This includes values selected through modifiers, order, etc.
+func (u *User) Value(name string) (ent.Value, error) {
+ return u.selectValues.Get(name)
+}
+
+// QueryCreatedTexture queries the "created_texture" edge of the User entity.
+func (u *User) QueryCreatedTexture() *TextureQuery {
+ return NewUserClient(u.config).QueryCreatedTexture(u)
+}
+
+// QueryProfile queries the "profile" edge of the User entity.
+func (u *User) QueryProfile() *UserProfileQuery {
+ return NewUserClient(u.config).QueryProfile(u)
+}
+
+// QueryToken queries the "token" edge of the User entity.
+func (u *User) QueryToken() *UserTokenQuery {
+ return NewUserClient(u.config).QueryToken(u)
+}
+
+// Update returns a builder for updating this User.
+// Note that you need to call User.Unwrap() before calling this method if this User
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (u *User) Update() *UserUpdateOne {
+ return NewUserClient(u.config).UpdateOne(u)
+}
+
+// Unwrap unwraps the User entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (u *User) Unwrap() *User {
+ _tx, ok := u.config.driver.(*txDriver)
+ if !ok {
+ panic("ent: User is not a transactional entity")
+ }
+ u.config.driver = _tx.drv
+ return u
+}
+
+// String implements the fmt.Stringer.
+func (u *User) String() string {
+ var builder strings.Builder
+ builder.WriteString("User(")
+ builder.WriteString(fmt.Sprintf("id=%v, ", u.ID))
+ builder.WriteString("email=")
+ builder.WriteString(u.Email)
+ builder.WriteString(", ")
+ builder.WriteString("password=")
+ builder.WriteString(u.Password)
+ builder.WriteString(", ")
+ builder.WriteString("salt=")
+ builder.WriteString(u.Salt)
+ builder.WriteString(", ")
+ builder.WriteString("reg_ip=")
+ builder.WriteString(u.RegIP)
+ builder.WriteString(", ")
+ builder.WriteString("state=")
+ builder.WriteString(fmt.Sprintf("%v", u.State))
+ builder.WriteString(", ")
+ builder.WriteString("reg_time=")
+ builder.WriteString(fmt.Sprintf("%v", u.RegTime))
+ builder.WriteByte(')')
+ return builder.String()
+}
+
+// Users is a parsable slice of User.
+type Users []*User
diff --git a/db/ent/user/user.go b/db/ent/user/user.go
new file mode 100644
index 0000000..0604af8
--- /dev/null
+++ b/db/ent/user/user.go
@@ -0,0 +1,164 @@
+// Code generated by ent, DO NOT EDIT.
+
+package user
+
+import (
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+const (
+ // Label holds the string label denoting the user type in the database.
+ Label = "user"
+ // FieldID holds the string denoting the id field in the database.
+ FieldID = "id"
+ // FieldEmail holds the string denoting the email field in the database.
+ FieldEmail = "email"
+ // FieldPassword holds the string denoting the password field in the database.
+ FieldPassword = "password"
+ // FieldSalt holds the string denoting the salt field in the database.
+ FieldSalt = "salt"
+ // FieldRegIP holds the string denoting the reg_ip field in the database.
+ FieldRegIP = "reg_ip"
+ // FieldState holds the string denoting the state field in the database.
+ FieldState = "state"
+ // FieldRegTime holds the string denoting the reg_time field in the database.
+ FieldRegTime = "reg_time"
+ // EdgeCreatedTexture holds the string denoting the created_texture edge name in mutations.
+ EdgeCreatedTexture = "created_texture"
+ // EdgeProfile holds the string denoting the profile edge name in mutations.
+ EdgeProfile = "profile"
+ // EdgeToken holds the string denoting the token edge name in mutations.
+ EdgeToken = "token"
+ // Table holds the table name of the user in the database.
+ Table = "users"
+ // CreatedTextureTable is the table that holds the created_texture relation/edge.
+ CreatedTextureTable = "textures"
+ // CreatedTextureInverseTable is the table name for the Texture entity.
+ // It exists in this package in order to avoid circular dependency with the "texture" package.
+ CreatedTextureInverseTable = "textures"
+ // CreatedTextureColumn is the table column denoting the created_texture relation/edge.
+ CreatedTextureColumn = "texture_created_user"
+ // ProfileTable is the table that holds the profile relation/edge.
+ ProfileTable = "user_profiles"
+ // ProfileInverseTable is the table name for the UserProfile entity.
+ // It exists in this package in order to avoid circular dependency with the "userprofile" package.
+ ProfileInverseTable = "user_profiles"
+ // ProfileColumn is the table column denoting the profile relation/edge.
+ ProfileColumn = "user_profile"
+ // TokenTable is the table that holds the token relation/edge.
+ TokenTable = "user_tokens"
+ // TokenInverseTable is the table name for the UserToken entity.
+ // It exists in this package in order to avoid circular dependency with the "usertoken" package.
+ TokenInverseTable = "user_tokens"
+ // TokenColumn is the table column denoting the token relation/edge.
+ TokenColumn = "user_token"
+)
+
+// Columns holds all SQL columns for user fields.
+var Columns = []string{
+ FieldID,
+ FieldEmail,
+ FieldPassword,
+ FieldSalt,
+ FieldRegIP,
+ FieldState,
+ FieldRegTime,
+}
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+ for i := range Columns {
+ if column == Columns[i] {
+ return true
+ }
+ }
+ return false
+}
+
+// OrderOption defines the ordering options for the User queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByEmail orders the results by the email field.
+func ByEmail(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldEmail, opts...).ToFunc()
+}
+
+// ByPassword orders the results by the password field.
+func ByPassword(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldPassword, opts...).ToFunc()
+}
+
+// BySalt orders the results by the salt field.
+func BySalt(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldSalt, opts...).ToFunc()
+}
+
+// ByRegIP orders the results by the reg_ip field.
+func ByRegIP(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldRegIP, opts...).ToFunc()
+}
+
+// ByState orders the results by the state field.
+func ByState(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldState, opts...).ToFunc()
+}
+
+// ByRegTime orders the results by the reg_time field.
+func ByRegTime(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldRegTime, opts...).ToFunc()
+}
+
+// ByCreatedTextureCount orders the results by created_texture count.
+func ByCreatedTextureCount(opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborsCount(s, newCreatedTextureStep(), opts...)
+ }
+}
+
+// ByCreatedTexture orders the results by created_texture terms.
+func ByCreatedTexture(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newCreatedTextureStep(), append([]sql.OrderTerm{term}, terms...)...)
+ }
+}
+
+// ByProfileField orders the results by profile field.
+func ByProfileField(field string, opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newProfileStep(), sql.OrderByField(field, opts...))
+ }
+}
+
+// ByTokenField orders the results by token field.
+func ByTokenField(field string, opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newTokenStep(), sql.OrderByField(field, opts...))
+ }
+}
+func newCreatedTextureStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(CreatedTextureInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, CreatedTextureTable, CreatedTextureColumn),
+ )
+}
+func newProfileStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(ProfileInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, false, ProfileTable, ProfileColumn),
+ )
+}
+func newTokenStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(TokenInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, false, TokenTable, TokenColumn),
+ )
+}
diff --git a/db/ent/user/where.go b/db/ent/user/where.go
new file mode 100644
index 0000000..f19d46e
--- /dev/null
+++ b/db/ent/user/where.go
@@ -0,0 +1,525 @@
+// Code generated by ent, DO NOT EDIT.
+
+package user
+
+import (
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id int) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id int) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id int) predicate.User {
+ return predicate.User(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...int) predicate.User {
+ return predicate.User(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...int) predicate.User {
+ return predicate.User(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id int) predicate.User {
+ return predicate.User(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id int) predicate.User {
+ return predicate.User(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id int) predicate.User {
+ return predicate.User(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id int) predicate.User {
+ return predicate.User(sql.FieldLTE(FieldID, id))
+}
+
+// Email applies equality check predicate on the "email" field. It's identical to EmailEQ.
+func Email(v string) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldEmail, v))
+}
+
+// Password applies equality check predicate on the "password" field. It's identical to PasswordEQ.
+func Password(v string) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldPassword, v))
+}
+
+// Salt applies equality check predicate on the "salt" field. It's identical to SaltEQ.
+func Salt(v string) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldSalt, v))
+}
+
+// RegIP applies equality check predicate on the "reg_ip" field. It's identical to RegIPEQ.
+func RegIP(v string) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldRegIP, v))
+}
+
+// State applies equality check predicate on the "state" field. It's identical to StateEQ.
+func State(v int) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldState, v))
+}
+
+// RegTime applies equality check predicate on the "reg_time" field. It's identical to RegTimeEQ.
+func RegTime(v int64) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldRegTime, v))
+}
+
+// EmailEQ applies the EQ predicate on the "email" field.
+func EmailEQ(v string) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldEmail, v))
+}
+
+// EmailNEQ applies the NEQ predicate on the "email" field.
+func EmailNEQ(v string) predicate.User {
+ return predicate.User(sql.FieldNEQ(FieldEmail, v))
+}
+
+// EmailIn applies the In predicate on the "email" field.
+func EmailIn(vs ...string) predicate.User {
+ return predicate.User(sql.FieldIn(FieldEmail, vs...))
+}
+
+// EmailNotIn applies the NotIn predicate on the "email" field.
+func EmailNotIn(vs ...string) predicate.User {
+ return predicate.User(sql.FieldNotIn(FieldEmail, vs...))
+}
+
+// EmailGT applies the GT predicate on the "email" field.
+func EmailGT(v string) predicate.User {
+ return predicate.User(sql.FieldGT(FieldEmail, v))
+}
+
+// EmailGTE applies the GTE predicate on the "email" field.
+func EmailGTE(v string) predicate.User {
+ return predicate.User(sql.FieldGTE(FieldEmail, v))
+}
+
+// EmailLT applies the LT predicate on the "email" field.
+func EmailLT(v string) predicate.User {
+ return predicate.User(sql.FieldLT(FieldEmail, v))
+}
+
+// EmailLTE applies the LTE predicate on the "email" field.
+func EmailLTE(v string) predicate.User {
+ return predicate.User(sql.FieldLTE(FieldEmail, v))
+}
+
+// EmailContains applies the Contains predicate on the "email" field.
+func EmailContains(v string) predicate.User {
+ return predicate.User(sql.FieldContains(FieldEmail, v))
+}
+
+// EmailHasPrefix applies the HasPrefix predicate on the "email" field.
+func EmailHasPrefix(v string) predicate.User {
+ return predicate.User(sql.FieldHasPrefix(FieldEmail, v))
+}
+
+// EmailHasSuffix applies the HasSuffix predicate on the "email" field.
+func EmailHasSuffix(v string) predicate.User {
+ return predicate.User(sql.FieldHasSuffix(FieldEmail, v))
+}
+
+// EmailEqualFold applies the EqualFold predicate on the "email" field.
+func EmailEqualFold(v string) predicate.User {
+ return predicate.User(sql.FieldEqualFold(FieldEmail, v))
+}
+
+// EmailContainsFold applies the ContainsFold predicate on the "email" field.
+func EmailContainsFold(v string) predicate.User {
+ return predicate.User(sql.FieldContainsFold(FieldEmail, v))
+}
+
+// PasswordEQ applies the EQ predicate on the "password" field.
+func PasswordEQ(v string) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldPassword, v))
+}
+
+// PasswordNEQ applies the NEQ predicate on the "password" field.
+func PasswordNEQ(v string) predicate.User {
+ return predicate.User(sql.FieldNEQ(FieldPassword, v))
+}
+
+// PasswordIn applies the In predicate on the "password" field.
+func PasswordIn(vs ...string) predicate.User {
+ return predicate.User(sql.FieldIn(FieldPassword, vs...))
+}
+
+// PasswordNotIn applies the NotIn predicate on the "password" field.
+func PasswordNotIn(vs ...string) predicate.User {
+ return predicate.User(sql.FieldNotIn(FieldPassword, vs...))
+}
+
+// PasswordGT applies the GT predicate on the "password" field.
+func PasswordGT(v string) predicate.User {
+ return predicate.User(sql.FieldGT(FieldPassword, v))
+}
+
+// PasswordGTE applies the GTE predicate on the "password" field.
+func PasswordGTE(v string) predicate.User {
+ return predicate.User(sql.FieldGTE(FieldPassword, v))
+}
+
+// PasswordLT applies the LT predicate on the "password" field.
+func PasswordLT(v string) predicate.User {
+ return predicate.User(sql.FieldLT(FieldPassword, v))
+}
+
+// PasswordLTE applies the LTE predicate on the "password" field.
+func PasswordLTE(v string) predicate.User {
+ return predicate.User(sql.FieldLTE(FieldPassword, v))
+}
+
+// PasswordContains applies the Contains predicate on the "password" field.
+func PasswordContains(v string) predicate.User {
+ return predicate.User(sql.FieldContains(FieldPassword, v))
+}
+
+// PasswordHasPrefix applies the HasPrefix predicate on the "password" field.
+func PasswordHasPrefix(v string) predicate.User {
+ return predicate.User(sql.FieldHasPrefix(FieldPassword, v))
+}
+
+// PasswordHasSuffix applies the HasSuffix predicate on the "password" field.
+func PasswordHasSuffix(v string) predicate.User {
+ return predicate.User(sql.FieldHasSuffix(FieldPassword, v))
+}
+
+// PasswordEqualFold applies the EqualFold predicate on the "password" field.
+func PasswordEqualFold(v string) predicate.User {
+ return predicate.User(sql.FieldEqualFold(FieldPassword, v))
+}
+
+// PasswordContainsFold applies the ContainsFold predicate on the "password" field.
+func PasswordContainsFold(v string) predicate.User {
+ return predicate.User(sql.FieldContainsFold(FieldPassword, v))
+}
+
+// SaltEQ applies the EQ predicate on the "salt" field.
+func SaltEQ(v string) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldSalt, v))
+}
+
+// SaltNEQ applies the NEQ predicate on the "salt" field.
+func SaltNEQ(v string) predicate.User {
+ return predicate.User(sql.FieldNEQ(FieldSalt, v))
+}
+
+// SaltIn applies the In predicate on the "salt" field.
+func SaltIn(vs ...string) predicate.User {
+ return predicate.User(sql.FieldIn(FieldSalt, vs...))
+}
+
+// SaltNotIn applies the NotIn predicate on the "salt" field.
+func SaltNotIn(vs ...string) predicate.User {
+ return predicate.User(sql.FieldNotIn(FieldSalt, vs...))
+}
+
+// SaltGT applies the GT predicate on the "salt" field.
+func SaltGT(v string) predicate.User {
+ return predicate.User(sql.FieldGT(FieldSalt, v))
+}
+
+// SaltGTE applies the GTE predicate on the "salt" field.
+func SaltGTE(v string) predicate.User {
+ return predicate.User(sql.FieldGTE(FieldSalt, v))
+}
+
+// SaltLT applies the LT predicate on the "salt" field.
+func SaltLT(v string) predicate.User {
+ return predicate.User(sql.FieldLT(FieldSalt, v))
+}
+
+// SaltLTE applies the LTE predicate on the "salt" field.
+func SaltLTE(v string) predicate.User {
+ return predicate.User(sql.FieldLTE(FieldSalt, v))
+}
+
+// SaltContains applies the Contains predicate on the "salt" field.
+func SaltContains(v string) predicate.User {
+ return predicate.User(sql.FieldContains(FieldSalt, v))
+}
+
+// SaltHasPrefix applies the HasPrefix predicate on the "salt" field.
+func SaltHasPrefix(v string) predicate.User {
+ return predicate.User(sql.FieldHasPrefix(FieldSalt, v))
+}
+
+// SaltHasSuffix applies the HasSuffix predicate on the "salt" field.
+func SaltHasSuffix(v string) predicate.User {
+ return predicate.User(sql.FieldHasSuffix(FieldSalt, v))
+}
+
+// SaltEqualFold applies the EqualFold predicate on the "salt" field.
+func SaltEqualFold(v string) predicate.User {
+ return predicate.User(sql.FieldEqualFold(FieldSalt, v))
+}
+
+// SaltContainsFold applies the ContainsFold predicate on the "salt" field.
+func SaltContainsFold(v string) predicate.User {
+ return predicate.User(sql.FieldContainsFold(FieldSalt, v))
+}
+
+// RegIPEQ applies the EQ predicate on the "reg_ip" field.
+func RegIPEQ(v string) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldRegIP, v))
+}
+
+// RegIPNEQ applies the NEQ predicate on the "reg_ip" field.
+func RegIPNEQ(v string) predicate.User {
+ return predicate.User(sql.FieldNEQ(FieldRegIP, v))
+}
+
+// RegIPIn applies the In predicate on the "reg_ip" field.
+func RegIPIn(vs ...string) predicate.User {
+ return predicate.User(sql.FieldIn(FieldRegIP, vs...))
+}
+
+// RegIPNotIn applies the NotIn predicate on the "reg_ip" field.
+func RegIPNotIn(vs ...string) predicate.User {
+ return predicate.User(sql.FieldNotIn(FieldRegIP, vs...))
+}
+
+// RegIPGT applies the GT predicate on the "reg_ip" field.
+func RegIPGT(v string) predicate.User {
+ return predicate.User(sql.FieldGT(FieldRegIP, v))
+}
+
+// RegIPGTE applies the GTE predicate on the "reg_ip" field.
+func RegIPGTE(v string) predicate.User {
+ return predicate.User(sql.FieldGTE(FieldRegIP, v))
+}
+
+// RegIPLT applies the LT predicate on the "reg_ip" field.
+func RegIPLT(v string) predicate.User {
+ return predicate.User(sql.FieldLT(FieldRegIP, v))
+}
+
+// RegIPLTE applies the LTE predicate on the "reg_ip" field.
+func RegIPLTE(v string) predicate.User {
+ return predicate.User(sql.FieldLTE(FieldRegIP, v))
+}
+
+// RegIPContains applies the Contains predicate on the "reg_ip" field.
+func RegIPContains(v string) predicate.User {
+ return predicate.User(sql.FieldContains(FieldRegIP, v))
+}
+
+// RegIPHasPrefix applies the HasPrefix predicate on the "reg_ip" field.
+func RegIPHasPrefix(v string) predicate.User {
+ return predicate.User(sql.FieldHasPrefix(FieldRegIP, v))
+}
+
+// RegIPHasSuffix applies the HasSuffix predicate on the "reg_ip" field.
+func RegIPHasSuffix(v string) predicate.User {
+ return predicate.User(sql.FieldHasSuffix(FieldRegIP, v))
+}
+
+// RegIPEqualFold applies the EqualFold predicate on the "reg_ip" field.
+func RegIPEqualFold(v string) predicate.User {
+ return predicate.User(sql.FieldEqualFold(FieldRegIP, v))
+}
+
+// RegIPContainsFold applies the ContainsFold predicate on the "reg_ip" field.
+func RegIPContainsFold(v string) predicate.User {
+ return predicate.User(sql.FieldContainsFold(FieldRegIP, v))
+}
+
+// StateEQ applies the EQ predicate on the "state" field.
+func StateEQ(v int) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldState, v))
+}
+
+// StateNEQ applies the NEQ predicate on the "state" field.
+func StateNEQ(v int) predicate.User {
+ return predicate.User(sql.FieldNEQ(FieldState, v))
+}
+
+// StateIn applies the In predicate on the "state" field.
+func StateIn(vs ...int) predicate.User {
+ return predicate.User(sql.FieldIn(FieldState, vs...))
+}
+
+// StateNotIn applies the NotIn predicate on the "state" field.
+func StateNotIn(vs ...int) predicate.User {
+ return predicate.User(sql.FieldNotIn(FieldState, vs...))
+}
+
+// StateGT applies the GT predicate on the "state" field.
+func StateGT(v int) predicate.User {
+ return predicate.User(sql.FieldGT(FieldState, v))
+}
+
+// StateGTE applies the GTE predicate on the "state" field.
+func StateGTE(v int) predicate.User {
+ return predicate.User(sql.FieldGTE(FieldState, v))
+}
+
+// StateLT applies the LT predicate on the "state" field.
+func StateLT(v int) predicate.User {
+ return predicate.User(sql.FieldLT(FieldState, v))
+}
+
+// StateLTE applies the LTE predicate on the "state" field.
+func StateLTE(v int) predicate.User {
+ return predicate.User(sql.FieldLTE(FieldState, v))
+}
+
+// RegTimeEQ applies the EQ predicate on the "reg_time" field.
+func RegTimeEQ(v int64) predicate.User {
+ return predicate.User(sql.FieldEQ(FieldRegTime, v))
+}
+
+// RegTimeNEQ applies the NEQ predicate on the "reg_time" field.
+func RegTimeNEQ(v int64) predicate.User {
+ return predicate.User(sql.FieldNEQ(FieldRegTime, v))
+}
+
+// RegTimeIn applies the In predicate on the "reg_time" field.
+func RegTimeIn(vs ...int64) predicate.User {
+ return predicate.User(sql.FieldIn(FieldRegTime, vs...))
+}
+
+// RegTimeNotIn applies the NotIn predicate on the "reg_time" field.
+func RegTimeNotIn(vs ...int64) predicate.User {
+ return predicate.User(sql.FieldNotIn(FieldRegTime, vs...))
+}
+
+// RegTimeGT applies the GT predicate on the "reg_time" field.
+func RegTimeGT(v int64) predicate.User {
+ return predicate.User(sql.FieldGT(FieldRegTime, v))
+}
+
+// RegTimeGTE applies the GTE predicate on the "reg_time" field.
+func RegTimeGTE(v int64) predicate.User {
+ return predicate.User(sql.FieldGTE(FieldRegTime, v))
+}
+
+// RegTimeLT applies the LT predicate on the "reg_time" field.
+func RegTimeLT(v int64) predicate.User {
+ return predicate.User(sql.FieldLT(FieldRegTime, v))
+}
+
+// RegTimeLTE applies the LTE predicate on the "reg_time" field.
+func RegTimeLTE(v int64) predicate.User {
+ return predicate.User(sql.FieldLTE(FieldRegTime, v))
+}
+
+// HasCreatedTexture applies the HasEdge predicate on the "created_texture" edge.
+func HasCreatedTexture() predicate.User {
+ return predicate.User(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, CreatedTextureTable, CreatedTextureColumn),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasCreatedTextureWith applies the HasEdge predicate on the "created_texture" edge with a given conditions (other predicates).
+func HasCreatedTextureWith(preds ...predicate.Texture) predicate.User {
+ return predicate.User(func(s *sql.Selector) {
+ step := newCreatedTextureStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// HasProfile applies the HasEdge predicate on the "profile" edge.
+func HasProfile() predicate.User {
+ return predicate.User(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, false, ProfileTable, ProfileColumn),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasProfileWith applies the HasEdge predicate on the "profile" edge with a given conditions (other predicates).
+func HasProfileWith(preds ...predicate.UserProfile) predicate.User {
+ return predicate.User(func(s *sql.Selector) {
+ step := newProfileStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// HasToken applies the HasEdge predicate on the "token" edge.
+func HasToken() predicate.User {
+ return predicate.User(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, false, TokenTable, TokenColumn),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasTokenWith applies the HasEdge predicate on the "token" edge with a given conditions (other predicates).
+func HasTokenWith(preds ...predicate.UserToken) predicate.User {
+ return predicate.User(func(s *sql.Selector) {
+ step := newTokenStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.User) predicate.User {
+ return predicate.User(func(s *sql.Selector) {
+ s1 := s.Clone().SetP(nil)
+ for _, p := range predicates {
+ p(s1)
+ }
+ s.Where(s1.P())
+ })
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.User) predicate.User {
+ return predicate.User(func(s *sql.Selector) {
+ s1 := s.Clone().SetP(nil)
+ for i, p := range predicates {
+ if i > 0 {
+ s1.Or()
+ }
+ p(s1)
+ }
+ s.Where(s1.P())
+ })
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.User) predicate.User {
+ return predicate.User(func(s *sql.Selector) {
+ p(s.Not())
+ })
+}
diff --git a/db/ent/user_create.go b/db/ent/user_create.go
new file mode 100644
index 0000000..8aa35c2
--- /dev/null
+++ b/db/ent/user_create.go
@@ -0,0 +1,348 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+// UserCreate is the builder for creating a User entity.
+type UserCreate struct {
+ config
+ mutation *UserMutation
+ hooks []Hook
+}
+
+// SetEmail sets the "email" field.
+func (uc *UserCreate) SetEmail(s string) *UserCreate {
+ uc.mutation.SetEmail(s)
+ return uc
+}
+
+// SetPassword sets the "password" field.
+func (uc *UserCreate) SetPassword(s string) *UserCreate {
+ uc.mutation.SetPassword(s)
+ return uc
+}
+
+// SetSalt sets the "salt" field.
+func (uc *UserCreate) SetSalt(s string) *UserCreate {
+ uc.mutation.SetSalt(s)
+ return uc
+}
+
+// SetRegIP sets the "reg_ip" field.
+func (uc *UserCreate) SetRegIP(s string) *UserCreate {
+ uc.mutation.SetRegIP(s)
+ return uc
+}
+
+// SetState sets the "state" field.
+func (uc *UserCreate) SetState(i int) *UserCreate {
+ uc.mutation.SetState(i)
+ return uc
+}
+
+// SetRegTime sets the "reg_time" field.
+func (uc *UserCreate) SetRegTime(i int64) *UserCreate {
+ uc.mutation.SetRegTime(i)
+ return uc
+}
+
+// AddCreatedTextureIDs adds the "created_texture" edge to the Texture entity by IDs.
+func (uc *UserCreate) AddCreatedTextureIDs(ids ...int) *UserCreate {
+ uc.mutation.AddCreatedTextureIDs(ids...)
+ return uc
+}
+
+// AddCreatedTexture adds the "created_texture" edges to the Texture entity.
+func (uc *UserCreate) AddCreatedTexture(t ...*Texture) *UserCreate {
+ ids := make([]int, len(t))
+ for i := range t {
+ ids[i] = t[i].ID
+ }
+ return uc.AddCreatedTextureIDs(ids...)
+}
+
+// SetProfileID sets the "profile" edge to the UserProfile entity by ID.
+func (uc *UserCreate) SetProfileID(id int) *UserCreate {
+ uc.mutation.SetProfileID(id)
+ return uc
+}
+
+// SetNillableProfileID sets the "profile" edge to the UserProfile entity by ID if the given value is not nil.
+func (uc *UserCreate) SetNillableProfileID(id *int) *UserCreate {
+ if id != nil {
+ uc = uc.SetProfileID(*id)
+ }
+ return uc
+}
+
+// SetProfile sets the "profile" edge to the UserProfile entity.
+func (uc *UserCreate) SetProfile(u *UserProfile) *UserCreate {
+ return uc.SetProfileID(u.ID)
+}
+
+// SetTokenID sets the "token" edge to the UserToken entity by ID.
+func (uc *UserCreate) SetTokenID(id int) *UserCreate {
+ uc.mutation.SetTokenID(id)
+ return uc
+}
+
+// SetNillableTokenID sets the "token" edge to the UserToken entity by ID if the given value is not nil.
+func (uc *UserCreate) SetNillableTokenID(id *int) *UserCreate {
+ if id != nil {
+ uc = uc.SetTokenID(*id)
+ }
+ return uc
+}
+
+// SetToken sets the "token" edge to the UserToken entity.
+func (uc *UserCreate) SetToken(u *UserToken) *UserCreate {
+ return uc.SetTokenID(u.ID)
+}
+
+// Mutation returns the UserMutation object of the builder.
+func (uc *UserCreate) Mutation() *UserMutation {
+ return uc.mutation
+}
+
+// Save creates the User in the database.
+func (uc *UserCreate) Save(ctx context.Context) (*User, error) {
+ return withHooks(ctx, uc.sqlSave, uc.mutation, uc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (uc *UserCreate) SaveX(ctx context.Context) *User {
+ v, err := uc.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Exec executes the query.
+func (uc *UserCreate) Exec(ctx context.Context) error {
+ _, err := uc.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (uc *UserCreate) ExecX(ctx context.Context) {
+ if err := uc.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (uc *UserCreate) check() error {
+ if _, ok := uc.mutation.Email(); !ok {
+ return &ValidationError{Name: "email", err: errors.New(`ent: missing required field "User.email"`)}
+ }
+ if _, ok := uc.mutation.Password(); !ok {
+ return &ValidationError{Name: "password", err: errors.New(`ent: missing required field "User.password"`)}
+ }
+ if _, ok := uc.mutation.Salt(); !ok {
+ return &ValidationError{Name: "salt", err: errors.New(`ent: missing required field "User.salt"`)}
+ }
+ if _, ok := uc.mutation.RegIP(); !ok {
+ return &ValidationError{Name: "reg_ip", err: errors.New(`ent: missing required field "User.reg_ip"`)}
+ }
+ if _, ok := uc.mutation.State(); !ok {
+ return &ValidationError{Name: "state", err: errors.New(`ent: missing required field "User.state"`)}
+ }
+ if _, ok := uc.mutation.RegTime(); !ok {
+ return &ValidationError{Name: "reg_time", err: errors.New(`ent: missing required field "User.reg_time"`)}
+ }
+ return nil
+}
+
+func (uc *UserCreate) sqlSave(ctx context.Context) (*User, error) {
+ if err := uc.check(); err != nil {
+ return nil, err
+ }
+ _node, _spec := uc.createSpec()
+ if err := sqlgraph.CreateNode(ctx, uc.driver, _spec); err != nil {
+ if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return nil, err
+ }
+ id := _spec.ID.Value.(int64)
+ _node.ID = int(id)
+ uc.mutation.id = &_node.ID
+ uc.mutation.done = true
+ return _node, nil
+}
+
+func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
+ var (
+ _node = &User{config: uc.config}
+ _spec = sqlgraph.NewCreateSpec(user.Table, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt))
+ )
+ if value, ok := uc.mutation.Email(); ok {
+ _spec.SetField(user.FieldEmail, field.TypeString, value)
+ _node.Email = value
+ }
+ if value, ok := uc.mutation.Password(); ok {
+ _spec.SetField(user.FieldPassword, field.TypeString, value)
+ _node.Password = value
+ }
+ if value, ok := uc.mutation.Salt(); ok {
+ _spec.SetField(user.FieldSalt, field.TypeString, value)
+ _node.Salt = value
+ }
+ if value, ok := uc.mutation.RegIP(); ok {
+ _spec.SetField(user.FieldRegIP, field.TypeString, value)
+ _node.RegIP = value
+ }
+ if value, ok := uc.mutation.State(); ok {
+ _spec.SetField(user.FieldState, field.TypeInt, value)
+ _node.State = value
+ }
+ if value, ok := uc.mutation.RegTime(); ok {
+ _spec.SetField(user.FieldRegTime, field.TypeInt64, value)
+ _node.RegTime = value
+ }
+ if nodes := uc.mutation.CreatedTextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: user.CreatedTextureTable,
+ Columns: []string{user.CreatedTextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ if nodes := uc.mutation.ProfileIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: false,
+ Table: user.ProfileTable,
+ Columns: []string{user.ProfileColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ if nodes := uc.mutation.TokenIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: false,
+ Table: user.TokenTable,
+ Columns: []string{user.TokenColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertoken.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ return _node, _spec
+}
+
+// UserCreateBulk is the builder for creating many User entities in bulk.
+type UserCreateBulk struct {
+ config
+ builders []*UserCreate
+}
+
+// Save creates the User entities in the database.
+func (ucb *UserCreateBulk) Save(ctx context.Context) ([]*User, error) {
+ specs := make([]*sqlgraph.CreateSpec, len(ucb.builders))
+ nodes := make([]*User, len(ucb.builders))
+ mutators := make([]Mutator, len(ucb.builders))
+ for i := range ucb.builders {
+ func(i int, root context.Context) {
+ builder := ucb.builders[i]
+ var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+ mutation, ok := m.(*UserMutation)
+ if !ok {
+ return nil, fmt.Errorf("unexpected mutation type %T", m)
+ }
+ if err := builder.check(); err != nil {
+ return nil, err
+ }
+ builder.mutation = mutation
+ var err error
+ nodes[i], specs[i] = builder.createSpec()
+ if i < len(mutators)-1 {
+ _, err = mutators[i+1].Mutate(root, ucb.builders[i+1].mutation)
+ } else {
+ spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+ // Invoke the actual operation on the latest mutation in the chain.
+ if err = sqlgraph.BatchCreate(ctx, ucb.driver, spec); err != nil {
+ if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ mutation.id = &nodes[i].ID
+ if specs[i].ID.Value != nil {
+ id := specs[i].ID.Value.(int64)
+ nodes[i].ID = int(id)
+ }
+ mutation.done = true
+ return nodes[i], nil
+ })
+ for i := len(builder.hooks) - 1; i >= 0; i-- {
+ mut = builder.hooks[i](mut)
+ }
+ mutators[i] = mut
+ }(i, ctx)
+ }
+ if len(mutators) > 0 {
+ if _, err := mutators[0].Mutate(ctx, ucb.builders[0].mutation); err != nil {
+ return nil, err
+ }
+ }
+ return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (ucb *UserCreateBulk) SaveX(ctx context.Context) []*User {
+ v, err := ucb.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Exec executes the query.
+func (ucb *UserCreateBulk) Exec(ctx context.Context) error {
+ _, err := ucb.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (ucb *UserCreateBulk) ExecX(ctx context.Context) {
+ if err := ucb.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
diff --git a/db/ent/user_delete.go b/db/ent/user_delete.go
new file mode 100644
index 0000000..c7c11e2
--- /dev/null
+++ b/db/ent/user_delete.go
@@ -0,0 +1,88 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+)
+
+// UserDelete is the builder for deleting a User entity.
+type UserDelete struct {
+ config
+ hooks []Hook
+ mutation *UserMutation
+}
+
+// Where appends a list predicates to the UserDelete builder.
+func (ud *UserDelete) Where(ps ...predicate.User) *UserDelete {
+ ud.mutation.Where(ps...)
+ return ud
+}
+
+// Exec executes the deletion query and returns how many vertices were deleted.
+func (ud *UserDelete) Exec(ctx context.Context) (int, error) {
+ return withHooks(ctx, ud.sqlExec, ud.mutation, ud.hooks)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (ud *UserDelete) ExecX(ctx context.Context) int {
+ n, err := ud.Exec(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return n
+}
+
+func (ud *UserDelete) sqlExec(ctx context.Context) (int, error) {
+ _spec := sqlgraph.NewDeleteSpec(user.Table, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt))
+ if ps := ud.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ affected, err := sqlgraph.DeleteNodes(ctx, ud.driver, _spec)
+ if err != nil && sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ ud.mutation.done = true
+ return affected, err
+}
+
+// UserDeleteOne is the builder for deleting a single User entity.
+type UserDeleteOne struct {
+ ud *UserDelete
+}
+
+// Where appends a list predicates to the UserDelete builder.
+func (udo *UserDeleteOne) Where(ps ...predicate.User) *UserDeleteOne {
+ udo.ud.mutation.Where(ps...)
+ return udo
+}
+
+// Exec executes the deletion query.
+func (udo *UserDeleteOne) Exec(ctx context.Context) error {
+ n, err := udo.ud.Exec(ctx)
+ switch {
+ case err != nil:
+ return err
+ case n == 0:
+ return &NotFoundError{user.Label}
+ default:
+ return nil
+ }
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (udo *UserDeleteOne) ExecX(ctx context.Context) {
+ if err := udo.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
diff --git a/db/ent/user_query.go b/db/ent/user_query.go
new file mode 100644
index 0000000..fb2b507
--- /dev/null
+++ b/db/ent/user_query.go
@@ -0,0 +1,805 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "database/sql/driver"
+ "fmt"
+ "math"
+
+ "entgo.io/ent/dialect"
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+// UserQuery is the builder for querying User entities.
+type UserQuery struct {
+ config
+ ctx *QueryContext
+ order []user.OrderOption
+ inters []Interceptor
+ predicates []predicate.User
+ withCreatedTexture *TextureQuery
+ withProfile *UserProfileQuery
+ withToken *UserTokenQuery
+ modifiers []func(*sql.Selector)
+ // intermediate query (i.e. traversal path).
+ sql *sql.Selector
+ path func(context.Context) (*sql.Selector, error)
+}
+
+// Where adds a new predicate for the UserQuery builder.
+func (uq *UserQuery) Where(ps ...predicate.User) *UserQuery {
+ uq.predicates = append(uq.predicates, ps...)
+ return uq
+}
+
+// Limit the number of records to be returned by this query.
+func (uq *UserQuery) Limit(limit int) *UserQuery {
+ uq.ctx.Limit = &limit
+ return uq
+}
+
+// Offset to start from.
+func (uq *UserQuery) Offset(offset int) *UserQuery {
+ uq.ctx.Offset = &offset
+ return uq
+}
+
+// Unique configures the query builder to filter duplicate records on query.
+// By default, unique is set to true, and can be disabled using this method.
+func (uq *UserQuery) Unique(unique bool) *UserQuery {
+ uq.ctx.Unique = &unique
+ return uq
+}
+
+// Order specifies how the records should be ordered.
+func (uq *UserQuery) Order(o ...user.OrderOption) *UserQuery {
+ uq.order = append(uq.order, o...)
+ return uq
+}
+
+// QueryCreatedTexture chains the current query on the "created_texture" edge.
+func (uq *UserQuery) QueryCreatedTexture() *TextureQuery {
+ query := (&TextureClient{config: uq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := uq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := uq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(user.Table, user.FieldID, selector),
+ sqlgraph.To(texture.Table, texture.FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, user.CreatedTextureTable, user.CreatedTextureColumn),
+ )
+ fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// QueryProfile chains the current query on the "profile" edge.
+func (uq *UserQuery) QueryProfile() *UserProfileQuery {
+ query := (&UserProfileClient{config: uq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := uq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := uq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(user.Table, user.FieldID, selector),
+ sqlgraph.To(userprofile.Table, userprofile.FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, false, user.ProfileTable, user.ProfileColumn),
+ )
+ fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// QueryToken chains the current query on the "token" edge.
+func (uq *UserQuery) QueryToken() *UserTokenQuery {
+ query := (&UserTokenClient{config: uq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := uq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := uq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(user.Table, user.FieldID, selector),
+ sqlgraph.To(usertoken.Table, usertoken.FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, false, user.TokenTable, user.TokenColumn),
+ )
+ fromU = sqlgraph.SetNeighbors(uq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// First returns the first User entity from the query.
+// Returns a *NotFoundError when no User was found.
+func (uq *UserQuery) First(ctx context.Context) (*User, error) {
+ nodes, err := uq.Limit(1).All(setContextOp(ctx, uq.ctx, "First"))
+ if err != nil {
+ return nil, err
+ }
+ if len(nodes) == 0 {
+ return nil, &NotFoundError{user.Label}
+ }
+ return nodes[0], nil
+}
+
+// FirstX is like First, but panics if an error occurs.
+func (uq *UserQuery) FirstX(ctx context.Context) *User {
+ node, err := uq.First(ctx)
+ if err != nil && !IsNotFound(err) {
+ panic(err)
+ }
+ return node
+}
+
+// FirstID returns the first User ID from the query.
+// Returns a *NotFoundError when no User ID was found.
+func (uq *UserQuery) FirstID(ctx context.Context) (id int, err error) {
+ var ids []int
+ if ids, err = uq.Limit(1).IDs(setContextOp(ctx, uq.ctx, "FirstID")); err != nil {
+ return
+ }
+ if len(ids) == 0 {
+ err = &NotFoundError{user.Label}
+ return
+ }
+ return ids[0], nil
+}
+
+// FirstIDX is like FirstID, but panics if an error occurs.
+func (uq *UserQuery) FirstIDX(ctx context.Context) int {
+ id, err := uq.FirstID(ctx)
+ if err != nil && !IsNotFound(err) {
+ panic(err)
+ }
+ return id
+}
+
+// Only returns a single User entity found by the query, ensuring it only returns one.
+// Returns a *NotSingularError when more than one User entity is found.
+// Returns a *NotFoundError when no User entities are found.
+func (uq *UserQuery) Only(ctx context.Context) (*User, error) {
+ nodes, err := uq.Limit(2).All(setContextOp(ctx, uq.ctx, "Only"))
+ if err != nil {
+ return nil, err
+ }
+ switch len(nodes) {
+ case 1:
+ return nodes[0], nil
+ case 0:
+ return nil, &NotFoundError{user.Label}
+ default:
+ return nil, &NotSingularError{user.Label}
+ }
+}
+
+// OnlyX is like Only, but panics if an error occurs.
+func (uq *UserQuery) OnlyX(ctx context.Context) *User {
+ node, err := uq.Only(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return node
+}
+
+// OnlyID is like Only, but returns the only User ID in the query.
+// Returns a *NotSingularError when more than one User ID is found.
+// Returns a *NotFoundError when no entities are found.
+func (uq *UserQuery) OnlyID(ctx context.Context) (id int, err error) {
+ var ids []int
+ if ids, err = uq.Limit(2).IDs(setContextOp(ctx, uq.ctx, "OnlyID")); err != nil {
+ return
+ }
+ switch len(ids) {
+ case 1:
+ id = ids[0]
+ case 0:
+ err = &NotFoundError{user.Label}
+ default:
+ err = &NotSingularError{user.Label}
+ }
+ return
+}
+
+// OnlyIDX is like OnlyID, but panics if an error occurs.
+func (uq *UserQuery) OnlyIDX(ctx context.Context) int {
+ id, err := uq.OnlyID(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
+// All executes the query and returns a list of Users.
+func (uq *UserQuery) All(ctx context.Context) ([]*User, error) {
+ ctx = setContextOp(ctx, uq.ctx, "All")
+ if err := uq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ qr := querierAll[[]*User, *UserQuery]()
+ return withInterceptors[[]*User](ctx, uq, qr, uq.inters)
+}
+
+// AllX is like All, but panics if an error occurs.
+func (uq *UserQuery) AllX(ctx context.Context) []*User {
+ nodes, err := uq.All(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return nodes
+}
+
+// IDs executes the query and returns a list of User IDs.
+func (uq *UserQuery) IDs(ctx context.Context) (ids []int, err error) {
+ if uq.ctx.Unique == nil && uq.path != nil {
+ uq.Unique(true)
+ }
+ ctx = setContextOp(ctx, uq.ctx, "IDs")
+ if err = uq.Select(user.FieldID).Scan(ctx, &ids); err != nil {
+ return nil, err
+ }
+ return ids, nil
+}
+
+// IDsX is like IDs, but panics if an error occurs.
+func (uq *UserQuery) IDsX(ctx context.Context) []int {
+ ids, err := uq.IDs(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return ids
+}
+
+// Count returns the count of the given query.
+func (uq *UserQuery) Count(ctx context.Context) (int, error) {
+ ctx = setContextOp(ctx, uq.ctx, "Count")
+ if err := uq.prepareQuery(ctx); err != nil {
+ return 0, err
+ }
+ return withInterceptors[int](ctx, uq, querierCount[*UserQuery](), uq.inters)
+}
+
+// CountX is like Count, but panics if an error occurs.
+func (uq *UserQuery) CountX(ctx context.Context) int {
+ count, err := uq.Count(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return count
+}
+
+// Exist returns true if the query has elements in the graph.
+func (uq *UserQuery) Exist(ctx context.Context) (bool, error) {
+ ctx = setContextOp(ctx, uq.ctx, "Exist")
+ switch _, err := uq.FirstID(ctx); {
+ case IsNotFound(err):
+ return false, nil
+ case err != nil:
+ return false, fmt.Errorf("ent: check existence: %w", err)
+ default:
+ return true, nil
+ }
+}
+
+// ExistX is like Exist, but panics if an error occurs.
+func (uq *UserQuery) ExistX(ctx context.Context) bool {
+ exist, err := uq.Exist(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return exist
+}
+
+// Clone returns a duplicate of the UserQuery builder, including all associated steps. It can be
+// used to prepare common query builders and use them differently after the clone is made.
+func (uq *UserQuery) Clone() *UserQuery {
+ if uq == nil {
+ return nil
+ }
+ return &UserQuery{
+ config: uq.config,
+ ctx: uq.ctx.Clone(),
+ order: append([]user.OrderOption{}, uq.order...),
+ inters: append([]Interceptor{}, uq.inters...),
+ predicates: append([]predicate.User{}, uq.predicates...),
+ withCreatedTexture: uq.withCreatedTexture.Clone(),
+ withProfile: uq.withProfile.Clone(),
+ withToken: uq.withToken.Clone(),
+ // clone intermediate query.
+ sql: uq.sql.Clone(),
+ path: uq.path,
+ }
+}
+
+// WithCreatedTexture tells the query-builder to eager-load the nodes that are connected to
+// the "created_texture" edge. The optional arguments are used to configure the query builder of the edge.
+func (uq *UserQuery) WithCreatedTexture(opts ...func(*TextureQuery)) *UserQuery {
+ query := (&TextureClient{config: uq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ uq.withCreatedTexture = query
+ return uq
+}
+
+// WithProfile tells the query-builder to eager-load the nodes that are connected to
+// the "profile" edge. The optional arguments are used to configure the query builder of the edge.
+func (uq *UserQuery) WithProfile(opts ...func(*UserProfileQuery)) *UserQuery {
+ query := (&UserProfileClient{config: uq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ uq.withProfile = query
+ return uq
+}
+
+// WithToken tells the query-builder to eager-load the nodes that are connected to
+// the "token" edge. The optional arguments are used to configure the query builder of the edge.
+func (uq *UserQuery) WithToken(opts ...func(*UserTokenQuery)) *UserQuery {
+ query := (&UserTokenClient{config: uq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ uq.withToken = query
+ return uq
+}
+
+// GroupBy is used to group vertices by one or more fields/columns.
+// It is often used with aggregate functions, like: count, max, mean, min, sum.
+//
+// Example:
+//
+// var v []struct {
+// Email string `json:"email,omitempty"`
+// Count int `json:"count,omitempty"`
+// }
+//
+// client.User.Query().
+// GroupBy(user.FieldEmail).
+// Aggregate(ent.Count()).
+// Scan(ctx, &v)
+func (uq *UserQuery) GroupBy(field string, fields ...string) *UserGroupBy {
+ uq.ctx.Fields = append([]string{field}, fields...)
+ grbuild := &UserGroupBy{build: uq}
+ grbuild.flds = &uq.ctx.Fields
+ grbuild.label = user.Label
+ grbuild.scan = grbuild.Scan
+ return grbuild
+}
+
+// Select allows the selection one or more fields/columns for the given query,
+// instead of selecting all fields in the entity.
+//
+// Example:
+//
+// var v []struct {
+// Email string `json:"email,omitempty"`
+// }
+//
+// client.User.Query().
+// Select(user.FieldEmail).
+// Scan(ctx, &v)
+func (uq *UserQuery) Select(fields ...string) *UserSelect {
+ uq.ctx.Fields = append(uq.ctx.Fields, fields...)
+ sbuild := &UserSelect{UserQuery: uq}
+ sbuild.label = user.Label
+ sbuild.flds, sbuild.scan = &uq.ctx.Fields, sbuild.Scan
+ return sbuild
+}
+
+// Aggregate returns a UserSelect configured with the given aggregations.
+func (uq *UserQuery) Aggregate(fns ...AggregateFunc) *UserSelect {
+ return uq.Select().Aggregate(fns...)
+}
+
+func (uq *UserQuery) prepareQuery(ctx context.Context) error {
+ for _, inter := range uq.inters {
+ if inter == nil {
+ return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
+ }
+ if trv, ok := inter.(Traverser); ok {
+ if err := trv.Traverse(ctx, uq); err != nil {
+ return err
+ }
+ }
+ }
+ for _, f := range uq.ctx.Fields {
+ if !user.ValidColumn(f) {
+ return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+ }
+ }
+ if uq.path != nil {
+ prev, err := uq.path(ctx)
+ if err != nil {
+ return err
+ }
+ uq.sql = prev
+ }
+ return nil
+}
+
+func (uq *UserQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*User, error) {
+ var (
+ nodes = []*User{}
+ _spec = uq.querySpec()
+ loadedTypes = [3]bool{
+ uq.withCreatedTexture != nil,
+ uq.withProfile != nil,
+ uq.withToken != nil,
+ }
+ )
+ _spec.ScanValues = func(columns []string) ([]any, error) {
+ return (*User).scanValues(nil, columns)
+ }
+ _spec.Assign = func(columns []string, values []any) error {
+ node := &User{config: uq.config}
+ nodes = append(nodes, node)
+ node.Edges.loadedTypes = loadedTypes
+ return node.assignValues(columns, values)
+ }
+ if len(uq.modifiers) > 0 {
+ _spec.Modifiers = uq.modifiers
+ }
+ for i := range hooks {
+ hooks[i](ctx, _spec)
+ }
+ if err := sqlgraph.QueryNodes(ctx, uq.driver, _spec); err != nil {
+ return nil, err
+ }
+ if len(nodes) == 0 {
+ return nodes, nil
+ }
+ if query := uq.withCreatedTexture; query != nil {
+ if err := uq.loadCreatedTexture(ctx, query, nodes,
+ func(n *User) { n.Edges.CreatedTexture = []*Texture{} },
+ func(n *User, e *Texture) { n.Edges.CreatedTexture = append(n.Edges.CreatedTexture, e) }); err != nil {
+ return nil, err
+ }
+ }
+ if query := uq.withProfile; query != nil {
+ if err := uq.loadProfile(ctx, query, nodes, nil,
+ func(n *User, e *UserProfile) { n.Edges.Profile = e }); err != nil {
+ return nil, err
+ }
+ }
+ if query := uq.withToken; query != nil {
+ if err := uq.loadToken(ctx, query, nodes, nil,
+ func(n *User, e *UserToken) { n.Edges.Token = e }); err != nil {
+ return nil, err
+ }
+ }
+ return nodes, nil
+}
+
+func (uq *UserQuery) loadCreatedTexture(ctx context.Context, query *TextureQuery, nodes []*User, init func(*User), assign func(*User, *Texture)) error {
+ fks := make([]driver.Value, 0, len(nodes))
+ nodeids := make(map[int]*User)
+ for i := range nodes {
+ fks = append(fks, nodes[i].ID)
+ nodeids[nodes[i].ID] = nodes[i]
+ if init != nil {
+ init(nodes[i])
+ }
+ }
+ query.withFKs = true
+ query.Where(predicate.Texture(func(s *sql.Selector) {
+ s.Where(sql.InValues(s.C(user.CreatedTextureColumn), fks...))
+ }))
+ neighbors, err := query.All(ctx)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ fk := n.texture_created_user
+ if fk == nil {
+ return fmt.Errorf(`foreign-key "texture_created_user" is nil for node %v`, n.ID)
+ }
+ node, ok := nodeids[*fk]
+ if !ok {
+ return fmt.Errorf(`unexpected referenced foreign-key "texture_created_user" returned %v for node %v`, *fk, n.ID)
+ }
+ assign(node, n)
+ }
+ return nil
+}
+func (uq *UserQuery) loadProfile(ctx context.Context, query *UserProfileQuery, nodes []*User, init func(*User), assign func(*User, *UserProfile)) error {
+ fks := make([]driver.Value, 0, len(nodes))
+ nodeids := make(map[int]*User)
+ for i := range nodes {
+ fks = append(fks, nodes[i].ID)
+ nodeids[nodes[i].ID] = nodes[i]
+ }
+ query.withFKs = true
+ query.Where(predicate.UserProfile(func(s *sql.Selector) {
+ s.Where(sql.InValues(s.C(user.ProfileColumn), fks...))
+ }))
+ neighbors, err := query.All(ctx)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ fk := n.user_profile
+ if fk == nil {
+ return fmt.Errorf(`foreign-key "user_profile" is nil for node %v`, n.ID)
+ }
+ node, ok := nodeids[*fk]
+ if !ok {
+ return fmt.Errorf(`unexpected referenced foreign-key "user_profile" returned %v for node %v`, *fk, n.ID)
+ }
+ assign(node, n)
+ }
+ return nil
+}
+func (uq *UserQuery) loadToken(ctx context.Context, query *UserTokenQuery, nodes []*User, init func(*User), assign func(*User, *UserToken)) error {
+ fks := make([]driver.Value, 0, len(nodes))
+ nodeids := make(map[int]*User)
+ for i := range nodes {
+ fks = append(fks, nodes[i].ID)
+ nodeids[nodes[i].ID] = nodes[i]
+ }
+ query.withFKs = true
+ query.Where(predicate.UserToken(func(s *sql.Selector) {
+ s.Where(sql.InValues(s.C(user.TokenColumn), fks...))
+ }))
+ neighbors, err := query.All(ctx)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ fk := n.user_token
+ if fk == nil {
+ return fmt.Errorf(`foreign-key "user_token" is nil for node %v`, n.ID)
+ }
+ node, ok := nodeids[*fk]
+ if !ok {
+ return fmt.Errorf(`unexpected referenced foreign-key "user_token" returned %v for node %v`, *fk, n.ID)
+ }
+ assign(node, n)
+ }
+ return nil
+}
+
+func (uq *UserQuery) sqlCount(ctx context.Context) (int, error) {
+ _spec := uq.querySpec()
+ if len(uq.modifiers) > 0 {
+ _spec.Modifiers = uq.modifiers
+ }
+ _spec.Node.Columns = uq.ctx.Fields
+ if len(uq.ctx.Fields) > 0 {
+ _spec.Unique = uq.ctx.Unique != nil && *uq.ctx.Unique
+ }
+ return sqlgraph.CountNodes(ctx, uq.driver, _spec)
+}
+
+func (uq *UserQuery) querySpec() *sqlgraph.QuerySpec {
+ _spec := sqlgraph.NewQuerySpec(user.Table, user.Columns, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt))
+ _spec.From = uq.sql
+ if unique := uq.ctx.Unique; unique != nil {
+ _spec.Unique = *unique
+ } else if uq.path != nil {
+ _spec.Unique = true
+ }
+ if fields := uq.ctx.Fields; len(fields) > 0 {
+ _spec.Node.Columns = make([]string, 0, len(fields))
+ _spec.Node.Columns = append(_spec.Node.Columns, user.FieldID)
+ for i := range fields {
+ if fields[i] != user.FieldID {
+ _spec.Node.Columns = append(_spec.Node.Columns, fields[i])
+ }
+ }
+ }
+ if ps := uq.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if limit := uq.ctx.Limit; limit != nil {
+ _spec.Limit = *limit
+ }
+ if offset := uq.ctx.Offset; offset != nil {
+ _spec.Offset = *offset
+ }
+ if ps := uq.order; len(ps) > 0 {
+ _spec.Order = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ return _spec
+}
+
+func (uq *UserQuery) sqlQuery(ctx context.Context) *sql.Selector {
+ builder := sql.Dialect(uq.driver.Dialect())
+ t1 := builder.Table(user.Table)
+ columns := uq.ctx.Fields
+ if len(columns) == 0 {
+ columns = user.Columns
+ }
+ selector := builder.Select(t1.Columns(columns...)...).From(t1)
+ if uq.sql != nil {
+ selector = uq.sql
+ selector.Select(selector.Columns(columns...)...)
+ }
+ if uq.ctx.Unique != nil && *uq.ctx.Unique {
+ selector.Distinct()
+ }
+ for _, m := range uq.modifiers {
+ m(selector)
+ }
+ for _, p := range uq.predicates {
+ p(selector)
+ }
+ for _, p := range uq.order {
+ p(selector)
+ }
+ if offset := uq.ctx.Offset; offset != nil {
+ // limit is mandatory for offset clause. We start
+ // with default value, and override it below if needed.
+ selector.Offset(*offset).Limit(math.MaxInt32)
+ }
+ if limit := uq.ctx.Limit; limit != nil {
+ selector.Limit(*limit)
+ }
+ return selector
+}
+
+// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
+// updated, deleted or "selected ... for update" by other sessions, until the transaction is
+// either committed or rolled-back.
+func (uq *UserQuery) ForUpdate(opts ...sql.LockOption) *UserQuery {
+ if uq.driver.Dialect() == dialect.Postgres {
+ uq.Unique(false)
+ }
+ uq.modifiers = append(uq.modifiers, func(s *sql.Selector) {
+ s.ForUpdate(opts...)
+ })
+ return uq
+}
+
+// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
+// on any rows that are read. Other sessions can read the rows, but cannot modify them
+// until your transaction commits.
+func (uq *UserQuery) ForShare(opts ...sql.LockOption) *UserQuery {
+ if uq.driver.Dialect() == dialect.Postgres {
+ uq.Unique(false)
+ }
+ uq.modifiers = append(uq.modifiers, func(s *sql.Selector) {
+ s.ForShare(opts...)
+ })
+ return uq
+}
+
+// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
+// updated, deleted or "selected ... for update" by other sessions, until the transaction is
+// either committed or rolled-back.
+func (uq *UserQuery) ForUpdateA(opts ...sql.LockOption) *UserQuery {
+ if uq.driver.Dialect() == dialect.SQLite {
+ return uq
+ }
+ return uq.ForUpdate(opts...)
+}
+
+// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
+// on any rows that are read. Other sessions can read the rows, but cannot modify them
+// until your transaction commits.
+func (uq *UserQuery) ForShareA(opts ...sql.LockOption) *UserQuery {
+ if uq.driver.Dialect() == dialect.SQLite {
+ return uq
+ }
+ return uq.ForShare(opts...)
+}
+
+// UserGroupBy is the group-by builder for User entities.
+type UserGroupBy struct {
+ selector
+ build *UserQuery
+}
+
+// Aggregate adds the given aggregation functions to the group-by query.
+func (ugb *UserGroupBy) Aggregate(fns ...AggregateFunc) *UserGroupBy {
+ ugb.fns = append(ugb.fns, fns...)
+ return ugb
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (ugb *UserGroupBy) Scan(ctx context.Context, v any) error {
+ ctx = setContextOp(ctx, ugb.build.ctx, "GroupBy")
+ if err := ugb.build.prepareQuery(ctx); err != nil {
+ return err
+ }
+ return scanWithInterceptors[*UserQuery, *UserGroupBy](ctx, ugb.build, ugb, ugb.build.inters, v)
+}
+
+func (ugb *UserGroupBy) sqlScan(ctx context.Context, root *UserQuery, v any) error {
+ selector := root.sqlQuery(ctx).Select()
+ aggregation := make([]string, 0, len(ugb.fns))
+ for _, fn := range ugb.fns {
+ aggregation = append(aggregation, fn(selector))
+ }
+ if len(selector.SelectedColumns()) == 0 {
+ columns := make([]string, 0, len(*ugb.flds)+len(ugb.fns))
+ for _, f := range *ugb.flds {
+ columns = append(columns, selector.C(f))
+ }
+ columns = append(columns, aggregation...)
+ selector.Select(columns...)
+ }
+ selector.GroupBy(selector.Columns(*ugb.flds...)...)
+ if err := selector.Err(); err != nil {
+ return err
+ }
+ rows := &sql.Rows{}
+ query, args := selector.Query()
+ if err := ugb.build.driver.Query(ctx, query, args, rows); err != nil {
+ return err
+ }
+ defer rows.Close()
+ return sql.ScanSlice(rows, v)
+}
+
+// UserSelect is the builder for selecting fields of User entities.
+type UserSelect struct {
+ *UserQuery
+ selector
+}
+
+// Aggregate adds the given aggregation functions to the selector query.
+func (us *UserSelect) Aggregate(fns ...AggregateFunc) *UserSelect {
+ us.fns = append(us.fns, fns...)
+ return us
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (us *UserSelect) Scan(ctx context.Context, v any) error {
+ ctx = setContextOp(ctx, us.ctx, "Select")
+ if err := us.prepareQuery(ctx); err != nil {
+ return err
+ }
+ return scanWithInterceptors[*UserQuery, *UserSelect](ctx, us.UserQuery, us, us.inters, v)
+}
+
+func (us *UserSelect) sqlScan(ctx context.Context, root *UserQuery, v any) error {
+ selector := root.sqlQuery(ctx)
+ aggregation := make([]string, 0, len(us.fns))
+ for _, fn := range us.fns {
+ aggregation = append(aggregation, fn(selector))
+ }
+ switch n := len(*us.selector.flds); {
+ case n == 0 && len(aggregation) > 0:
+ selector.Select(aggregation...)
+ case n != 0 && len(aggregation) > 0:
+ selector.AppendSelect(aggregation...)
+ }
+ rows := &sql.Rows{}
+ query, args := selector.Query()
+ if err := us.driver.Query(ctx, query, args, rows); err != nil {
+ return err
+ }
+ defer rows.Close()
+ return sql.ScanSlice(rows, v)
+}
diff --git a/db/ent/user_update.go b/db/ent/user_update.go
new file mode 100644
index 0000000..9a9141f
--- /dev/null
+++ b/db/ent/user_update.go
@@ -0,0 +1,704 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+// UserUpdate is the builder for updating User entities.
+type UserUpdate struct {
+ config
+ hooks []Hook
+ mutation *UserMutation
+}
+
+// Where appends a list predicates to the UserUpdate builder.
+func (uu *UserUpdate) Where(ps ...predicate.User) *UserUpdate {
+ uu.mutation.Where(ps...)
+ return uu
+}
+
+// SetEmail sets the "email" field.
+func (uu *UserUpdate) SetEmail(s string) *UserUpdate {
+ uu.mutation.SetEmail(s)
+ return uu
+}
+
+// SetPassword sets the "password" field.
+func (uu *UserUpdate) SetPassword(s string) *UserUpdate {
+ uu.mutation.SetPassword(s)
+ return uu
+}
+
+// SetSalt sets the "salt" field.
+func (uu *UserUpdate) SetSalt(s string) *UserUpdate {
+ uu.mutation.SetSalt(s)
+ return uu
+}
+
+// SetRegIP sets the "reg_ip" field.
+func (uu *UserUpdate) SetRegIP(s string) *UserUpdate {
+ uu.mutation.SetRegIP(s)
+ return uu
+}
+
+// SetState sets the "state" field.
+func (uu *UserUpdate) SetState(i int) *UserUpdate {
+ uu.mutation.ResetState()
+ uu.mutation.SetState(i)
+ return uu
+}
+
+// AddState adds i to the "state" field.
+func (uu *UserUpdate) AddState(i int) *UserUpdate {
+ uu.mutation.AddState(i)
+ return uu
+}
+
+// SetRegTime sets the "reg_time" field.
+func (uu *UserUpdate) SetRegTime(i int64) *UserUpdate {
+ uu.mutation.ResetRegTime()
+ uu.mutation.SetRegTime(i)
+ return uu
+}
+
+// AddRegTime adds i to the "reg_time" field.
+func (uu *UserUpdate) AddRegTime(i int64) *UserUpdate {
+ uu.mutation.AddRegTime(i)
+ return uu
+}
+
+// AddCreatedTextureIDs adds the "created_texture" edge to the Texture entity by IDs.
+func (uu *UserUpdate) AddCreatedTextureIDs(ids ...int) *UserUpdate {
+ uu.mutation.AddCreatedTextureIDs(ids...)
+ return uu
+}
+
+// AddCreatedTexture adds the "created_texture" edges to the Texture entity.
+func (uu *UserUpdate) AddCreatedTexture(t ...*Texture) *UserUpdate {
+ ids := make([]int, len(t))
+ for i := range t {
+ ids[i] = t[i].ID
+ }
+ return uu.AddCreatedTextureIDs(ids...)
+}
+
+// SetProfileID sets the "profile" edge to the UserProfile entity by ID.
+func (uu *UserUpdate) SetProfileID(id int) *UserUpdate {
+ uu.mutation.SetProfileID(id)
+ return uu
+}
+
+// SetNillableProfileID sets the "profile" edge to the UserProfile entity by ID if the given value is not nil.
+func (uu *UserUpdate) SetNillableProfileID(id *int) *UserUpdate {
+ if id != nil {
+ uu = uu.SetProfileID(*id)
+ }
+ return uu
+}
+
+// SetProfile sets the "profile" edge to the UserProfile entity.
+func (uu *UserUpdate) SetProfile(u *UserProfile) *UserUpdate {
+ return uu.SetProfileID(u.ID)
+}
+
+// SetTokenID sets the "token" edge to the UserToken entity by ID.
+func (uu *UserUpdate) SetTokenID(id int) *UserUpdate {
+ uu.mutation.SetTokenID(id)
+ return uu
+}
+
+// SetNillableTokenID sets the "token" edge to the UserToken entity by ID if the given value is not nil.
+func (uu *UserUpdate) SetNillableTokenID(id *int) *UserUpdate {
+ if id != nil {
+ uu = uu.SetTokenID(*id)
+ }
+ return uu
+}
+
+// SetToken sets the "token" edge to the UserToken entity.
+func (uu *UserUpdate) SetToken(u *UserToken) *UserUpdate {
+ return uu.SetTokenID(u.ID)
+}
+
+// Mutation returns the UserMutation object of the builder.
+func (uu *UserUpdate) Mutation() *UserMutation {
+ return uu.mutation
+}
+
+// ClearCreatedTexture clears all "created_texture" edges to the Texture entity.
+func (uu *UserUpdate) ClearCreatedTexture() *UserUpdate {
+ uu.mutation.ClearCreatedTexture()
+ return uu
+}
+
+// RemoveCreatedTextureIDs removes the "created_texture" edge to Texture entities by IDs.
+func (uu *UserUpdate) RemoveCreatedTextureIDs(ids ...int) *UserUpdate {
+ uu.mutation.RemoveCreatedTextureIDs(ids...)
+ return uu
+}
+
+// RemoveCreatedTexture removes "created_texture" edges to Texture entities.
+func (uu *UserUpdate) RemoveCreatedTexture(t ...*Texture) *UserUpdate {
+ ids := make([]int, len(t))
+ for i := range t {
+ ids[i] = t[i].ID
+ }
+ return uu.RemoveCreatedTextureIDs(ids...)
+}
+
+// ClearProfile clears the "profile" edge to the UserProfile entity.
+func (uu *UserUpdate) ClearProfile() *UserUpdate {
+ uu.mutation.ClearProfile()
+ return uu
+}
+
+// ClearToken clears the "token" edge to the UserToken entity.
+func (uu *UserUpdate) ClearToken() *UserUpdate {
+ uu.mutation.ClearToken()
+ return uu
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (uu *UserUpdate) Save(ctx context.Context) (int, error) {
+ return withHooks(ctx, uu.sqlSave, uu.mutation, uu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (uu *UserUpdate) SaveX(ctx context.Context) int {
+ affected, err := uu.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return affected
+}
+
+// Exec executes the query.
+func (uu *UserUpdate) Exec(ctx context.Context) error {
+ _, err := uu.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (uu *UserUpdate) ExecX(ctx context.Context) {
+ if err := uu.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
+ _spec := sqlgraph.NewUpdateSpec(user.Table, user.Columns, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt))
+ if ps := uu.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if value, ok := uu.mutation.Email(); ok {
+ _spec.SetField(user.FieldEmail, field.TypeString, value)
+ }
+ if value, ok := uu.mutation.Password(); ok {
+ _spec.SetField(user.FieldPassword, field.TypeString, value)
+ }
+ if value, ok := uu.mutation.Salt(); ok {
+ _spec.SetField(user.FieldSalt, field.TypeString, value)
+ }
+ if value, ok := uu.mutation.RegIP(); ok {
+ _spec.SetField(user.FieldRegIP, field.TypeString, value)
+ }
+ if value, ok := uu.mutation.State(); ok {
+ _spec.SetField(user.FieldState, field.TypeInt, value)
+ }
+ if value, ok := uu.mutation.AddedState(); ok {
+ _spec.AddField(user.FieldState, field.TypeInt, value)
+ }
+ if value, ok := uu.mutation.RegTime(); ok {
+ _spec.SetField(user.FieldRegTime, field.TypeInt64, value)
+ }
+ if value, ok := uu.mutation.AddedRegTime(); ok {
+ _spec.AddField(user.FieldRegTime, field.TypeInt64, value)
+ }
+ if uu.mutation.CreatedTextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: user.CreatedTextureTable,
+ Columns: []string{user.CreatedTextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := uu.mutation.RemovedCreatedTextureIDs(); len(nodes) > 0 && !uu.mutation.CreatedTextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: user.CreatedTextureTable,
+ Columns: []string{user.CreatedTextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := uu.mutation.CreatedTextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: user.CreatedTextureTable,
+ Columns: []string{user.CreatedTextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if uu.mutation.ProfileCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: false,
+ Table: user.ProfileTable,
+ Columns: []string{user.ProfileColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := uu.mutation.ProfileIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: false,
+ Table: user.ProfileTable,
+ Columns: []string{user.ProfileColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if uu.mutation.TokenCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: false,
+ Table: user.TokenTable,
+ Columns: []string{user.TokenColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertoken.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := uu.mutation.TokenIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: false,
+ Table: user.TokenTable,
+ Columns: []string{user.TokenColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertoken.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, _spec); err != nil {
+ if _, ok := err.(*sqlgraph.NotFoundError); ok {
+ err = &NotFoundError{user.Label}
+ } else if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return 0, err
+ }
+ uu.mutation.done = true
+ return n, nil
+}
+
+// UserUpdateOne is the builder for updating a single User entity.
+type UserUpdateOne struct {
+ config
+ fields []string
+ hooks []Hook
+ mutation *UserMutation
+}
+
+// SetEmail sets the "email" field.
+func (uuo *UserUpdateOne) SetEmail(s string) *UserUpdateOne {
+ uuo.mutation.SetEmail(s)
+ return uuo
+}
+
+// SetPassword sets the "password" field.
+func (uuo *UserUpdateOne) SetPassword(s string) *UserUpdateOne {
+ uuo.mutation.SetPassword(s)
+ return uuo
+}
+
+// SetSalt sets the "salt" field.
+func (uuo *UserUpdateOne) SetSalt(s string) *UserUpdateOne {
+ uuo.mutation.SetSalt(s)
+ return uuo
+}
+
+// SetRegIP sets the "reg_ip" field.
+func (uuo *UserUpdateOne) SetRegIP(s string) *UserUpdateOne {
+ uuo.mutation.SetRegIP(s)
+ return uuo
+}
+
+// SetState sets the "state" field.
+func (uuo *UserUpdateOne) SetState(i int) *UserUpdateOne {
+ uuo.mutation.ResetState()
+ uuo.mutation.SetState(i)
+ return uuo
+}
+
+// AddState adds i to the "state" field.
+func (uuo *UserUpdateOne) AddState(i int) *UserUpdateOne {
+ uuo.mutation.AddState(i)
+ return uuo
+}
+
+// SetRegTime sets the "reg_time" field.
+func (uuo *UserUpdateOne) SetRegTime(i int64) *UserUpdateOne {
+ uuo.mutation.ResetRegTime()
+ uuo.mutation.SetRegTime(i)
+ return uuo
+}
+
+// AddRegTime adds i to the "reg_time" field.
+func (uuo *UserUpdateOne) AddRegTime(i int64) *UserUpdateOne {
+ uuo.mutation.AddRegTime(i)
+ return uuo
+}
+
+// AddCreatedTextureIDs adds the "created_texture" edge to the Texture entity by IDs.
+func (uuo *UserUpdateOne) AddCreatedTextureIDs(ids ...int) *UserUpdateOne {
+ uuo.mutation.AddCreatedTextureIDs(ids...)
+ return uuo
+}
+
+// AddCreatedTexture adds the "created_texture" edges to the Texture entity.
+func (uuo *UserUpdateOne) AddCreatedTexture(t ...*Texture) *UserUpdateOne {
+ ids := make([]int, len(t))
+ for i := range t {
+ ids[i] = t[i].ID
+ }
+ return uuo.AddCreatedTextureIDs(ids...)
+}
+
+// SetProfileID sets the "profile" edge to the UserProfile entity by ID.
+func (uuo *UserUpdateOne) SetProfileID(id int) *UserUpdateOne {
+ uuo.mutation.SetProfileID(id)
+ return uuo
+}
+
+// SetNillableProfileID sets the "profile" edge to the UserProfile entity by ID if the given value is not nil.
+func (uuo *UserUpdateOne) SetNillableProfileID(id *int) *UserUpdateOne {
+ if id != nil {
+ uuo = uuo.SetProfileID(*id)
+ }
+ return uuo
+}
+
+// SetProfile sets the "profile" edge to the UserProfile entity.
+func (uuo *UserUpdateOne) SetProfile(u *UserProfile) *UserUpdateOne {
+ return uuo.SetProfileID(u.ID)
+}
+
+// SetTokenID sets the "token" edge to the UserToken entity by ID.
+func (uuo *UserUpdateOne) SetTokenID(id int) *UserUpdateOne {
+ uuo.mutation.SetTokenID(id)
+ return uuo
+}
+
+// SetNillableTokenID sets the "token" edge to the UserToken entity by ID if the given value is not nil.
+func (uuo *UserUpdateOne) SetNillableTokenID(id *int) *UserUpdateOne {
+ if id != nil {
+ uuo = uuo.SetTokenID(*id)
+ }
+ return uuo
+}
+
+// SetToken sets the "token" edge to the UserToken entity.
+func (uuo *UserUpdateOne) SetToken(u *UserToken) *UserUpdateOne {
+ return uuo.SetTokenID(u.ID)
+}
+
+// Mutation returns the UserMutation object of the builder.
+func (uuo *UserUpdateOne) Mutation() *UserMutation {
+ return uuo.mutation
+}
+
+// ClearCreatedTexture clears all "created_texture" edges to the Texture entity.
+func (uuo *UserUpdateOne) ClearCreatedTexture() *UserUpdateOne {
+ uuo.mutation.ClearCreatedTexture()
+ return uuo
+}
+
+// RemoveCreatedTextureIDs removes the "created_texture" edge to Texture entities by IDs.
+func (uuo *UserUpdateOne) RemoveCreatedTextureIDs(ids ...int) *UserUpdateOne {
+ uuo.mutation.RemoveCreatedTextureIDs(ids...)
+ return uuo
+}
+
+// RemoveCreatedTexture removes "created_texture" edges to Texture entities.
+func (uuo *UserUpdateOne) RemoveCreatedTexture(t ...*Texture) *UserUpdateOne {
+ ids := make([]int, len(t))
+ for i := range t {
+ ids[i] = t[i].ID
+ }
+ return uuo.RemoveCreatedTextureIDs(ids...)
+}
+
+// ClearProfile clears the "profile" edge to the UserProfile entity.
+func (uuo *UserUpdateOne) ClearProfile() *UserUpdateOne {
+ uuo.mutation.ClearProfile()
+ return uuo
+}
+
+// ClearToken clears the "token" edge to the UserToken entity.
+func (uuo *UserUpdateOne) ClearToken() *UserUpdateOne {
+ uuo.mutation.ClearToken()
+ return uuo
+}
+
+// Where appends a list predicates to the UserUpdate builder.
+func (uuo *UserUpdateOne) Where(ps ...predicate.User) *UserUpdateOne {
+ uuo.mutation.Where(ps...)
+ return uuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (uuo *UserUpdateOne) Select(field string, fields ...string) *UserUpdateOne {
+ uuo.fields = append([]string{field}, fields...)
+ return uuo
+}
+
+// Save executes the query and returns the updated User entity.
+func (uuo *UserUpdateOne) Save(ctx context.Context) (*User, error) {
+ return withHooks(ctx, uuo.sqlSave, uuo.mutation, uuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (uuo *UserUpdateOne) SaveX(ctx context.Context) *User {
+ node, err := uuo.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return node
+}
+
+// Exec executes the query on the entity.
+func (uuo *UserUpdateOne) Exec(ctx context.Context) error {
+ _, err := uuo.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (uuo *UserUpdateOne) ExecX(ctx context.Context) {
+ if err := uuo.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) {
+ _spec := sqlgraph.NewUpdateSpec(user.Table, user.Columns, sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt))
+ id, ok := uuo.mutation.ID()
+ if !ok {
+ return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "User.id" for update`)}
+ }
+ _spec.Node.ID.Value = id
+ if fields := uuo.fields; len(fields) > 0 {
+ _spec.Node.Columns = make([]string, 0, len(fields))
+ _spec.Node.Columns = append(_spec.Node.Columns, user.FieldID)
+ for _, f := range fields {
+ if !user.ValidColumn(f) {
+ return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+ }
+ if f != user.FieldID {
+ _spec.Node.Columns = append(_spec.Node.Columns, f)
+ }
+ }
+ }
+ if ps := uuo.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if value, ok := uuo.mutation.Email(); ok {
+ _spec.SetField(user.FieldEmail, field.TypeString, value)
+ }
+ if value, ok := uuo.mutation.Password(); ok {
+ _spec.SetField(user.FieldPassword, field.TypeString, value)
+ }
+ if value, ok := uuo.mutation.Salt(); ok {
+ _spec.SetField(user.FieldSalt, field.TypeString, value)
+ }
+ if value, ok := uuo.mutation.RegIP(); ok {
+ _spec.SetField(user.FieldRegIP, field.TypeString, value)
+ }
+ if value, ok := uuo.mutation.State(); ok {
+ _spec.SetField(user.FieldState, field.TypeInt, value)
+ }
+ if value, ok := uuo.mutation.AddedState(); ok {
+ _spec.AddField(user.FieldState, field.TypeInt, value)
+ }
+ if value, ok := uuo.mutation.RegTime(); ok {
+ _spec.SetField(user.FieldRegTime, field.TypeInt64, value)
+ }
+ if value, ok := uuo.mutation.AddedRegTime(); ok {
+ _spec.AddField(user.FieldRegTime, field.TypeInt64, value)
+ }
+ if uuo.mutation.CreatedTextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: user.CreatedTextureTable,
+ Columns: []string{user.CreatedTextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := uuo.mutation.RemovedCreatedTextureIDs(); len(nodes) > 0 && !uuo.mutation.CreatedTextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: user.CreatedTextureTable,
+ Columns: []string{user.CreatedTextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := uuo.mutation.CreatedTextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: user.CreatedTextureTable,
+ Columns: []string{user.CreatedTextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if uuo.mutation.ProfileCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: false,
+ Table: user.ProfileTable,
+ Columns: []string{user.ProfileColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := uuo.mutation.ProfileIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: false,
+ Table: user.ProfileTable,
+ Columns: []string{user.ProfileColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if uuo.mutation.TokenCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: false,
+ Table: user.TokenTable,
+ Columns: []string{user.TokenColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertoken.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := uuo.mutation.TokenIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: false,
+ Table: user.TokenTable,
+ Columns: []string{user.TokenColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertoken.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ _node = &User{config: uuo.config}
+ _spec.Assign = _node.assignValues
+ _spec.ScanValues = _node.scanValues
+ if err = sqlgraph.UpdateNode(ctx, uuo.driver, _spec); err != nil {
+ if _, ok := err.(*sqlgraph.NotFoundError); ok {
+ err = &NotFoundError{user.Label}
+ } else if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return nil, err
+ }
+ uuo.mutation.done = true
+ return _node, nil
+}
diff --git a/db/ent/userprofile.go b/db/ent/userprofile.go
new file mode 100644
index 0000000..f59359c
--- /dev/null
+++ b/db/ent/userprofile.go
@@ -0,0 +1,187 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "fmt"
+ "strings"
+
+ "entgo.io/ent"
+ "entgo.io/ent/dialect/sql"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+)
+
+// UserProfile is the model entity for the UserProfile schema.
+type UserProfile struct {
+ config `json:"-"`
+ // ID of the ent.
+ ID int `json:"id,omitempty"`
+ // Name holds the value of the "name" field.
+ Name string `json:"name,omitempty"`
+ // UUID holds the value of the "uuid" field.
+ UUID string `json:"uuid,omitempty"`
+ // Edges holds the relations/edges for other nodes in the graph.
+ // The values are being populated by the UserProfileQuery when eager-loading is set.
+ Edges UserProfileEdges `json:"edges"`
+ user_profile *int
+ selectValues sql.SelectValues
+}
+
+// UserProfileEdges holds the relations/edges for other nodes in the graph.
+type UserProfileEdges struct {
+ // User holds the value of the user edge.
+ User *User `json:"user,omitempty"`
+ // Texture holds the value of the texture edge.
+ Texture []*Texture `json:"texture,omitempty"`
+ // Usertexture holds the value of the usertexture edge.
+ Usertexture []*UserTexture `json:"usertexture,omitempty"`
+ // loadedTypes holds the information for reporting if a
+ // type was loaded (or requested) in eager-loading or not.
+ loadedTypes [3]bool
+}
+
+// UserOrErr returns the User value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e UserProfileEdges) UserOrErr() (*User, error) {
+ if e.loadedTypes[0] {
+ if e.User == nil {
+ // Edge was loaded but was not found.
+ return nil, &NotFoundError{label: user.Label}
+ }
+ return e.User, nil
+ }
+ return nil, &NotLoadedError{edge: "user"}
+}
+
+// TextureOrErr returns the Texture value or an error if the edge
+// was not loaded in eager-loading.
+func (e UserProfileEdges) TextureOrErr() ([]*Texture, error) {
+ if e.loadedTypes[1] {
+ return e.Texture, nil
+ }
+ return nil, &NotLoadedError{edge: "texture"}
+}
+
+// UsertextureOrErr returns the Usertexture value or an error if the edge
+// was not loaded in eager-loading.
+func (e UserProfileEdges) UsertextureOrErr() ([]*UserTexture, error) {
+ if e.loadedTypes[2] {
+ return e.Usertexture, nil
+ }
+ return nil, &NotLoadedError{edge: "usertexture"}
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*UserProfile) scanValues(columns []string) ([]any, error) {
+ values := make([]any, len(columns))
+ for i := range columns {
+ switch columns[i] {
+ case userprofile.FieldID:
+ values[i] = new(sql.NullInt64)
+ case userprofile.FieldName, userprofile.FieldUUID:
+ values[i] = new(sql.NullString)
+ case userprofile.ForeignKeys[0]: // user_profile
+ values[i] = new(sql.NullInt64)
+ default:
+ values[i] = new(sql.UnknownType)
+ }
+ }
+ return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the UserProfile fields.
+func (up *UserProfile) assignValues(columns []string, values []any) error {
+ if m, n := len(values), len(columns); m < n {
+ return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+ }
+ for i := range columns {
+ switch columns[i] {
+ case userprofile.FieldID:
+ value, ok := values[i].(*sql.NullInt64)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field id", value)
+ }
+ up.ID = int(value.Int64)
+ case userprofile.FieldName:
+ if value, ok := values[i].(*sql.NullString); !ok {
+ return fmt.Errorf("unexpected type %T for field name", values[i])
+ } else if value.Valid {
+ up.Name = value.String
+ }
+ case userprofile.FieldUUID:
+ if value, ok := values[i].(*sql.NullString); !ok {
+ return fmt.Errorf("unexpected type %T for field uuid", values[i])
+ } else if value.Valid {
+ up.UUID = value.String
+ }
+ case userprofile.ForeignKeys[0]:
+ if value, ok := values[i].(*sql.NullInt64); !ok {
+ return fmt.Errorf("unexpected type %T for edge-field user_profile", value)
+ } else if value.Valid {
+ up.user_profile = new(int)
+ *up.user_profile = int(value.Int64)
+ }
+ default:
+ up.selectValues.Set(columns[i], values[i])
+ }
+ }
+ return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the UserProfile.
+// This includes values selected through modifiers, order, etc.
+func (up *UserProfile) Value(name string) (ent.Value, error) {
+ return up.selectValues.Get(name)
+}
+
+// QueryUser queries the "user" edge of the UserProfile entity.
+func (up *UserProfile) QueryUser() *UserQuery {
+ return NewUserProfileClient(up.config).QueryUser(up)
+}
+
+// QueryTexture queries the "texture" edge of the UserProfile entity.
+func (up *UserProfile) QueryTexture() *TextureQuery {
+ return NewUserProfileClient(up.config).QueryTexture(up)
+}
+
+// QueryUsertexture queries the "usertexture" edge of the UserProfile entity.
+func (up *UserProfile) QueryUsertexture() *UserTextureQuery {
+ return NewUserProfileClient(up.config).QueryUsertexture(up)
+}
+
+// Update returns a builder for updating this UserProfile.
+// Note that you need to call UserProfile.Unwrap() before calling this method if this UserProfile
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (up *UserProfile) Update() *UserProfileUpdateOne {
+ return NewUserProfileClient(up.config).UpdateOne(up)
+}
+
+// Unwrap unwraps the UserProfile entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (up *UserProfile) Unwrap() *UserProfile {
+ _tx, ok := up.config.driver.(*txDriver)
+ if !ok {
+ panic("ent: UserProfile is not a transactional entity")
+ }
+ up.config.driver = _tx.drv
+ return up
+}
+
+// String implements the fmt.Stringer.
+func (up *UserProfile) String() string {
+ var builder strings.Builder
+ builder.WriteString("UserProfile(")
+ builder.WriteString(fmt.Sprintf("id=%v, ", up.ID))
+ builder.WriteString("name=")
+ builder.WriteString(up.Name)
+ builder.WriteString(", ")
+ builder.WriteString("uuid=")
+ builder.WriteString(up.UUID)
+ builder.WriteByte(')')
+ return builder.String()
+}
+
+// UserProfiles is a parsable slice of UserProfile.
+type UserProfiles []*UserProfile
diff --git a/db/ent/userprofile/userprofile.go b/db/ent/userprofile/userprofile.go
new file mode 100644
index 0000000..f170ba8
--- /dev/null
+++ b/db/ent/userprofile/userprofile.go
@@ -0,0 +1,154 @@
+// Code generated by ent, DO NOT EDIT.
+
+package userprofile
+
+import (
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+const (
+ // Label holds the string label denoting the userprofile type in the database.
+ Label = "user_profile"
+ // FieldID holds the string denoting the id field in the database.
+ FieldID = "id"
+ // FieldName holds the string denoting the name field in the database.
+ FieldName = "name"
+ // FieldUUID holds the string denoting the uuid field in the database.
+ FieldUUID = "uuid"
+ // EdgeUser holds the string denoting the user edge name in mutations.
+ EdgeUser = "user"
+ // EdgeTexture holds the string denoting the texture edge name in mutations.
+ EdgeTexture = "texture"
+ // EdgeUsertexture holds the string denoting the usertexture edge name in mutations.
+ EdgeUsertexture = "usertexture"
+ // Table holds the table name of the userprofile in the database.
+ Table = "user_profiles"
+ // UserTable is the table that holds the user relation/edge.
+ UserTable = "user_profiles"
+ // UserInverseTable is the table name for the User entity.
+ // It exists in this package in order to avoid circular dependency with the "user" package.
+ UserInverseTable = "users"
+ // UserColumn is the table column denoting the user relation/edge.
+ UserColumn = "user_profile"
+ // TextureTable is the table that holds the texture relation/edge. The primary key declared below.
+ TextureTable = "user_textures"
+ // TextureInverseTable is the table name for the Texture entity.
+ // It exists in this package in order to avoid circular dependency with the "texture" package.
+ TextureInverseTable = "textures"
+ // UsertextureTable is the table that holds the usertexture relation/edge.
+ UsertextureTable = "user_textures"
+ // UsertextureInverseTable is the table name for the UserTexture entity.
+ // It exists in this package in order to avoid circular dependency with the "usertexture" package.
+ UsertextureInverseTable = "user_textures"
+ // UsertextureColumn is the table column denoting the usertexture relation/edge.
+ UsertextureColumn = "user_profile_id"
+)
+
+// Columns holds all SQL columns for userprofile fields.
+var Columns = []string{
+ FieldID,
+ FieldName,
+ FieldUUID,
+}
+
+// ForeignKeys holds the SQL foreign-keys that are owned by the "user_profiles"
+// table and are not defined as standalone fields in the schema.
+var ForeignKeys = []string{
+ "user_profile",
+}
+
+var (
+ // TexturePrimaryKey and TextureColumn2 are the table columns denoting the
+ // primary key for the texture relation (M2M).
+ TexturePrimaryKey = []string{"texture_id", "user_profile_id"}
+)
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+ for i := range Columns {
+ if column == Columns[i] {
+ return true
+ }
+ }
+ for i := range ForeignKeys {
+ if column == ForeignKeys[i] {
+ return true
+ }
+ }
+ return false
+}
+
+// OrderOption defines the ordering options for the UserProfile queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByName orders the results by the name field.
+func ByName(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldName, opts...).ToFunc()
+}
+
+// ByUUID orders the results by the uuid field.
+func ByUUID(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldUUID, opts...).ToFunc()
+}
+
+// ByUserField orders the results by user field.
+func ByUserField(field string, opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newUserStep(), sql.OrderByField(field, opts...))
+ }
+}
+
+// ByTextureCount orders the results by texture count.
+func ByTextureCount(opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborsCount(s, newTextureStep(), opts...)
+ }
+}
+
+// ByTexture orders the results by texture terms.
+func ByTexture(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newTextureStep(), append([]sql.OrderTerm{term}, terms...)...)
+ }
+}
+
+// ByUsertextureCount orders the results by usertexture count.
+func ByUsertextureCount(opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborsCount(s, newUsertextureStep(), opts...)
+ }
+}
+
+// ByUsertexture orders the results by usertexture terms.
+func ByUsertexture(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newUsertextureStep(), append([]sql.OrderTerm{term}, terms...)...)
+ }
+}
+func newUserStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(UserInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, true, UserTable, UserColumn),
+ )
+}
+func newTextureStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(TextureInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.M2M, true, TextureTable, TexturePrimaryKey...),
+ )
+}
+func newUsertextureStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(UsertextureInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, UsertextureTable, UsertextureColumn),
+ )
+}
diff --git a/db/ent/userprofile/where.go b/db/ent/userprofile/where.go
new file mode 100644
index 0000000..01c4b1a
--- /dev/null
+++ b/db/ent/userprofile/where.go
@@ -0,0 +1,295 @@
+// Code generated by ent, DO NOT EDIT.
+
+package userprofile
+
+import (
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id int) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id int) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id int) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...int) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...int) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id int) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id int) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id int) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id int) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldLTE(FieldID, id))
+}
+
+// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
+func Name(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldEQ(FieldName, v))
+}
+
+// UUID applies equality check predicate on the "uuid" field. It's identical to UUIDEQ.
+func UUID(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldEQ(FieldUUID, v))
+}
+
+// NameEQ applies the EQ predicate on the "name" field.
+func NameEQ(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldEQ(FieldName, v))
+}
+
+// NameNEQ applies the NEQ predicate on the "name" field.
+func NameNEQ(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldNEQ(FieldName, v))
+}
+
+// NameIn applies the In predicate on the "name" field.
+func NameIn(vs ...string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldIn(FieldName, vs...))
+}
+
+// NameNotIn applies the NotIn predicate on the "name" field.
+func NameNotIn(vs ...string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldNotIn(FieldName, vs...))
+}
+
+// NameGT applies the GT predicate on the "name" field.
+func NameGT(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldGT(FieldName, v))
+}
+
+// NameGTE applies the GTE predicate on the "name" field.
+func NameGTE(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldGTE(FieldName, v))
+}
+
+// NameLT applies the LT predicate on the "name" field.
+func NameLT(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldLT(FieldName, v))
+}
+
+// NameLTE applies the LTE predicate on the "name" field.
+func NameLTE(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldLTE(FieldName, v))
+}
+
+// NameContains applies the Contains predicate on the "name" field.
+func NameContains(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldContains(FieldName, v))
+}
+
+// NameHasPrefix applies the HasPrefix predicate on the "name" field.
+func NameHasPrefix(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldHasPrefix(FieldName, v))
+}
+
+// NameHasSuffix applies the HasSuffix predicate on the "name" field.
+func NameHasSuffix(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldHasSuffix(FieldName, v))
+}
+
+// NameEqualFold applies the EqualFold predicate on the "name" field.
+func NameEqualFold(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldEqualFold(FieldName, v))
+}
+
+// NameContainsFold applies the ContainsFold predicate on the "name" field.
+func NameContainsFold(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldContainsFold(FieldName, v))
+}
+
+// UUIDEQ applies the EQ predicate on the "uuid" field.
+func UUIDEQ(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldEQ(FieldUUID, v))
+}
+
+// UUIDNEQ applies the NEQ predicate on the "uuid" field.
+func UUIDNEQ(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldNEQ(FieldUUID, v))
+}
+
+// UUIDIn applies the In predicate on the "uuid" field.
+func UUIDIn(vs ...string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldIn(FieldUUID, vs...))
+}
+
+// UUIDNotIn applies the NotIn predicate on the "uuid" field.
+func UUIDNotIn(vs ...string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldNotIn(FieldUUID, vs...))
+}
+
+// UUIDGT applies the GT predicate on the "uuid" field.
+func UUIDGT(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldGT(FieldUUID, v))
+}
+
+// UUIDGTE applies the GTE predicate on the "uuid" field.
+func UUIDGTE(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldGTE(FieldUUID, v))
+}
+
+// UUIDLT applies the LT predicate on the "uuid" field.
+func UUIDLT(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldLT(FieldUUID, v))
+}
+
+// UUIDLTE applies the LTE predicate on the "uuid" field.
+func UUIDLTE(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldLTE(FieldUUID, v))
+}
+
+// UUIDContains applies the Contains predicate on the "uuid" field.
+func UUIDContains(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldContains(FieldUUID, v))
+}
+
+// UUIDHasPrefix applies the HasPrefix predicate on the "uuid" field.
+func UUIDHasPrefix(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldHasPrefix(FieldUUID, v))
+}
+
+// UUIDHasSuffix applies the HasSuffix predicate on the "uuid" field.
+func UUIDHasSuffix(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldHasSuffix(FieldUUID, v))
+}
+
+// UUIDEqualFold applies the EqualFold predicate on the "uuid" field.
+func UUIDEqualFold(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldEqualFold(FieldUUID, v))
+}
+
+// UUIDContainsFold applies the ContainsFold predicate on the "uuid" field.
+func UUIDContainsFold(v string) predicate.UserProfile {
+ return predicate.UserProfile(sql.FieldContainsFold(FieldUUID, v))
+}
+
+// HasUser applies the HasEdge predicate on the "user" edge.
+func HasUser() predicate.UserProfile {
+ return predicate.UserProfile(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, true, UserTable, UserColumn),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates).
+func HasUserWith(preds ...predicate.User) predicate.UserProfile {
+ return predicate.UserProfile(func(s *sql.Selector) {
+ step := newUserStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// HasTexture applies the HasEdge predicate on the "texture" edge.
+func HasTexture() predicate.UserProfile {
+ return predicate.UserProfile(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.M2M, true, TextureTable, TexturePrimaryKey...),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasTextureWith applies the HasEdge predicate on the "texture" edge with a given conditions (other predicates).
+func HasTextureWith(preds ...predicate.Texture) predicate.UserProfile {
+ return predicate.UserProfile(func(s *sql.Selector) {
+ step := newTextureStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// HasUsertexture applies the HasEdge predicate on the "usertexture" edge.
+func HasUsertexture() predicate.UserProfile {
+ return predicate.UserProfile(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, UsertextureTable, UsertextureColumn),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasUsertextureWith applies the HasEdge predicate on the "usertexture" edge with a given conditions (other predicates).
+func HasUsertextureWith(preds ...predicate.UserTexture) predicate.UserProfile {
+ return predicate.UserProfile(func(s *sql.Selector) {
+ step := newUsertextureStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.UserProfile) predicate.UserProfile {
+ return predicate.UserProfile(func(s *sql.Selector) {
+ s1 := s.Clone().SetP(nil)
+ for _, p := range predicates {
+ p(s1)
+ }
+ s.Where(s1.P())
+ })
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.UserProfile) predicate.UserProfile {
+ return predicate.UserProfile(func(s *sql.Selector) {
+ s1 := s.Clone().SetP(nil)
+ for i, p := range predicates {
+ if i > 0 {
+ s1.Or()
+ }
+ p(s1)
+ }
+ s.Where(s1.P())
+ })
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.UserProfile) predicate.UserProfile {
+ return predicate.UserProfile(func(s *sql.Selector) {
+ p(s.Not())
+ })
+}
diff --git a/db/ent/userprofile_create.go b/db/ent/userprofile_create.go
new file mode 100644
index 0000000..6b17bc8
--- /dev/null
+++ b/db/ent/userprofile_create.go
@@ -0,0 +1,288 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+)
+
+// UserProfileCreate is the builder for creating a UserProfile entity.
+type UserProfileCreate struct {
+ config
+ mutation *UserProfileMutation
+ hooks []Hook
+}
+
+// SetName sets the "name" field.
+func (upc *UserProfileCreate) SetName(s string) *UserProfileCreate {
+ upc.mutation.SetName(s)
+ return upc
+}
+
+// SetUUID sets the "uuid" field.
+func (upc *UserProfileCreate) SetUUID(s string) *UserProfileCreate {
+ upc.mutation.SetUUID(s)
+ return upc
+}
+
+// SetUserID sets the "user" edge to the User entity by ID.
+func (upc *UserProfileCreate) SetUserID(id int) *UserProfileCreate {
+ upc.mutation.SetUserID(id)
+ return upc
+}
+
+// SetUser sets the "user" edge to the User entity.
+func (upc *UserProfileCreate) SetUser(u *User) *UserProfileCreate {
+ return upc.SetUserID(u.ID)
+}
+
+// AddTextureIDs adds the "texture" edge to the Texture entity by IDs.
+func (upc *UserProfileCreate) AddTextureIDs(ids ...int) *UserProfileCreate {
+ upc.mutation.AddTextureIDs(ids...)
+ return upc
+}
+
+// AddTexture adds the "texture" edges to the Texture entity.
+func (upc *UserProfileCreate) AddTexture(t ...*Texture) *UserProfileCreate {
+ ids := make([]int, len(t))
+ for i := range t {
+ ids[i] = t[i].ID
+ }
+ return upc.AddTextureIDs(ids...)
+}
+
+// AddUsertextureIDs adds the "usertexture" edge to the UserTexture entity by IDs.
+func (upc *UserProfileCreate) AddUsertextureIDs(ids ...int) *UserProfileCreate {
+ upc.mutation.AddUsertextureIDs(ids...)
+ return upc
+}
+
+// AddUsertexture adds the "usertexture" edges to the UserTexture entity.
+func (upc *UserProfileCreate) AddUsertexture(u ...*UserTexture) *UserProfileCreate {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return upc.AddUsertextureIDs(ids...)
+}
+
+// Mutation returns the UserProfileMutation object of the builder.
+func (upc *UserProfileCreate) Mutation() *UserProfileMutation {
+ return upc.mutation
+}
+
+// Save creates the UserProfile in the database.
+func (upc *UserProfileCreate) Save(ctx context.Context) (*UserProfile, error) {
+ return withHooks(ctx, upc.sqlSave, upc.mutation, upc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (upc *UserProfileCreate) SaveX(ctx context.Context) *UserProfile {
+ v, err := upc.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Exec executes the query.
+func (upc *UserProfileCreate) Exec(ctx context.Context) error {
+ _, err := upc.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (upc *UserProfileCreate) ExecX(ctx context.Context) {
+ if err := upc.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (upc *UserProfileCreate) check() error {
+ if _, ok := upc.mutation.Name(); !ok {
+ return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "UserProfile.name"`)}
+ }
+ if _, ok := upc.mutation.UUID(); !ok {
+ return &ValidationError{Name: "uuid", err: errors.New(`ent: missing required field "UserProfile.uuid"`)}
+ }
+ if _, ok := upc.mutation.UserID(); !ok {
+ return &ValidationError{Name: "user", err: errors.New(`ent: missing required edge "UserProfile.user"`)}
+ }
+ return nil
+}
+
+func (upc *UserProfileCreate) sqlSave(ctx context.Context) (*UserProfile, error) {
+ if err := upc.check(); err != nil {
+ return nil, err
+ }
+ _node, _spec := upc.createSpec()
+ if err := sqlgraph.CreateNode(ctx, upc.driver, _spec); err != nil {
+ if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return nil, err
+ }
+ id := _spec.ID.Value.(int64)
+ _node.ID = int(id)
+ upc.mutation.id = &_node.ID
+ upc.mutation.done = true
+ return _node, nil
+}
+
+func (upc *UserProfileCreate) createSpec() (*UserProfile, *sqlgraph.CreateSpec) {
+ var (
+ _node = &UserProfile{config: upc.config}
+ _spec = sqlgraph.NewCreateSpec(userprofile.Table, sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt))
+ )
+ if value, ok := upc.mutation.Name(); ok {
+ _spec.SetField(userprofile.FieldName, field.TypeString, value)
+ _node.Name = value
+ }
+ if value, ok := upc.mutation.UUID(); ok {
+ _spec.SetField(userprofile.FieldUUID, field.TypeString, value)
+ _node.UUID = value
+ }
+ if nodes := upc.mutation.UserIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: true,
+ Table: userprofile.UserTable,
+ Columns: []string{userprofile.UserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _node.user_profile = &nodes[0]
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ if nodes := upc.mutation.TextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: true,
+ Table: userprofile.TextureTable,
+ Columns: userprofile.TexturePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ if nodes := upc.mutation.UsertextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: userprofile.UsertextureTable,
+ Columns: []string{userprofile.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ return _node, _spec
+}
+
+// UserProfileCreateBulk is the builder for creating many UserProfile entities in bulk.
+type UserProfileCreateBulk struct {
+ config
+ builders []*UserProfileCreate
+}
+
+// Save creates the UserProfile entities in the database.
+func (upcb *UserProfileCreateBulk) Save(ctx context.Context) ([]*UserProfile, error) {
+ specs := make([]*sqlgraph.CreateSpec, len(upcb.builders))
+ nodes := make([]*UserProfile, len(upcb.builders))
+ mutators := make([]Mutator, len(upcb.builders))
+ for i := range upcb.builders {
+ func(i int, root context.Context) {
+ builder := upcb.builders[i]
+ var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+ mutation, ok := m.(*UserProfileMutation)
+ if !ok {
+ return nil, fmt.Errorf("unexpected mutation type %T", m)
+ }
+ if err := builder.check(); err != nil {
+ return nil, err
+ }
+ builder.mutation = mutation
+ var err error
+ nodes[i], specs[i] = builder.createSpec()
+ if i < len(mutators)-1 {
+ _, err = mutators[i+1].Mutate(root, upcb.builders[i+1].mutation)
+ } else {
+ spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+ // Invoke the actual operation on the latest mutation in the chain.
+ if err = sqlgraph.BatchCreate(ctx, upcb.driver, spec); err != nil {
+ if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ mutation.id = &nodes[i].ID
+ if specs[i].ID.Value != nil {
+ id := specs[i].ID.Value.(int64)
+ nodes[i].ID = int(id)
+ }
+ mutation.done = true
+ return nodes[i], nil
+ })
+ for i := len(builder.hooks) - 1; i >= 0; i-- {
+ mut = builder.hooks[i](mut)
+ }
+ mutators[i] = mut
+ }(i, ctx)
+ }
+ if len(mutators) > 0 {
+ if _, err := mutators[0].Mutate(ctx, upcb.builders[0].mutation); err != nil {
+ return nil, err
+ }
+ }
+ return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (upcb *UserProfileCreateBulk) SaveX(ctx context.Context) []*UserProfile {
+ v, err := upcb.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Exec executes the query.
+func (upcb *UserProfileCreateBulk) Exec(ctx context.Context) error {
+ _, err := upcb.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (upcb *UserProfileCreateBulk) ExecX(ctx context.Context) {
+ if err := upcb.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
diff --git a/db/ent/userprofile_delete.go b/db/ent/userprofile_delete.go
new file mode 100644
index 0000000..1575761
--- /dev/null
+++ b/db/ent/userprofile_delete.go
@@ -0,0 +1,88 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+)
+
+// UserProfileDelete is the builder for deleting a UserProfile entity.
+type UserProfileDelete struct {
+ config
+ hooks []Hook
+ mutation *UserProfileMutation
+}
+
+// Where appends a list predicates to the UserProfileDelete builder.
+func (upd *UserProfileDelete) Where(ps ...predicate.UserProfile) *UserProfileDelete {
+ upd.mutation.Where(ps...)
+ return upd
+}
+
+// Exec executes the deletion query and returns how many vertices were deleted.
+func (upd *UserProfileDelete) Exec(ctx context.Context) (int, error) {
+ return withHooks(ctx, upd.sqlExec, upd.mutation, upd.hooks)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (upd *UserProfileDelete) ExecX(ctx context.Context) int {
+ n, err := upd.Exec(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return n
+}
+
+func (upd *UserProfileDelete) sqlExec(ctx context.Context) (int, error) {
+ _spec := sqlgraph.NewDeleteSpec(userprofile.Table, sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt))
+ if ps := upd.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ affected, err := sqlgraph.DeleteNodes(ctx, upd.driver, _spec)
+ if err != nil && sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ upd.mutation.done = true
+ return affected, err
+}
+
+// UserProfileDeleteOne is the builder for deleting a single UserProfile entity.
+type UserProfileDeleteOne struct {
+ upd *UserProfileDelete
+}
+
+// Where appends a list predicates to the UserProfileDelete builder.
+func (updo *UserProfileDeleteOne) Where(ps ...predicate.UserProfile) *UserProfileDeleteOne {
+ updo.upd.mutation.Where(ps...)
+ return updo
+}
+
+// Exec executes the deletion query.
+func (updo *UserProfileDeleteOne) Exec(ctx context.Context) error {
+ n, err := updo.upd.Exec(ctx)
+ switch {
+ case err != nil:
+ return err
+ case n == 0:
+ return &NotFoundError{userprofile.Label}
+ default:
+ return nil
+ }
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (updo *UserProfileDeleteOne) ExecX(ctx context.Context) {
+ if err := updo.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
diff --git a/db/ent/userprofile_query.go b/db/ent/userprofile_query.go
new file mode 100644
index 0000000..41ab268
--- /dev/null
+++ b/db/ent/userprofile_query.go
@@ -0,0 +1,850 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "database/sql/driver"
+ "fmt"
+ "math"
+
+ "entgo.io/ent/dialect"
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+)
+
+// UserProfileQuery is the builder for querying UserProfile entities.
+type UserProfileQuery struct {
+ config
+ ctx *QueryContext
+ order []userprofile.OrderOption
+ inters []Interceptor
+ predicates []predicate.UserProfile
+ withUser *UserQuery
+ withTexture *TextureQuery
+ withUsertexture *UserTextureQuery
+ withFKs bool
+ modifiers []func(*sql.Selector)
+ // intermediate query (i.e. traversal path).
+ sql *sql.Selector
+ path func(context.Context) (*sql.Selector, error)
+}
+
+// Where adds a new predicate for the UserProfileQuery builder.
+func (upq *UserProfileQuery) Where(ps ...predicate.UserProfile) *UserProfileQuery {
+ upq.predicates = append(upq.predicates, ps...)
+ return upq
+}
+
+// Limit the number of records to be returned by this query.
+func (upq *UserProfileQuery) Limit(limit int) *UserProfileQuery {
+ upq.ctx.Limit = &limit
+ return upq
+}
+
+// Offset to start from.
+func (upq *UserProfileQuery) Offset(offset int) *UserProfileQuery {
+ upq.ctx.Offset = &offset
+ return upq
+}
+
+// Unique configures the query builder to filter duplicate records on query.
+// By default, unique is set to true, and can be disabled using this method.
+func (upq *UserProfileQuery) Unique(unique bool) *UserProfileQuery {
+ upq.ctx.Unique = &unique
+ return upq
+}
+
+// Order specifies how the records should be ordered.
+func (upq *UserProfileQuery) Order(o ...userprofile.OrderOption) *UserProfileQuery {
+ upq.order = append(upq.order, o...)
+ return upq
+}
+
+// QueryUser chains the current query on the "user" edge.
+func (upq *UserProfileQuery) QueryUser() *UserQuery {
+ query := (&UserClient{config: upq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := upq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := upq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(userprofile.Table, userprofile.FieldID, selector),
+ sqlgraph.To(user.Table, user.FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, true, userprofile.UserTable, userprofile.UserColumn),
+ )
+ fromU = sqlgraph.SetNeighbors(upq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// QueryTexture chains the current query on the "texture" edge.
+func (upq *UserProfileQuery) QueryTexture() *TextureQuery {
+ query := (&TextureClient{config: upq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := upq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := upq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(userprofile.Table, userprofile.FieldID, selector),
+ sqlgraph.To(texture.Table, texture.FieldID),
+ sqlgraph.Edge(sqlgraph.M2M, true, userprofile.TextureTable, userprofile.TexturePrimaryKey...),
+ )
+ fromU = sqlgraph.SetNeighbors(upq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// QueryUsertexture chains the current query on the "usertexture" edge.
+func (upq *UserProfileQuery) QueryUsertexture() *UserTextureQuery {
+ query := (&UserTextureClient{config: upq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := upq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := upq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(userprofile.Table, userprofile.FieldID, selector),
+ sqlgraph.To(usertexture.Table, usertexture.FieldID),
+ sqlgraph.Edge(sqlgraph.O2M, true, userprofile.UsertextureTable, userprofile.UsertextureColumn),
+ )
+ fromU = sqlgraph.SetNeighbors(upq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// First returns the first UserProfile entity from the query.
+// Returns a *NotFoundError when no UserProfile was found.
+func (upq *UserProfileQuery) First(ctx context.Context) (*UserProfile, error) {
+ nodes, err := upq.Limit(1).All(setContextOp(ctx, upq.ctx, "First"))
+ if err != nil {
+ return nil, err
+ }
+ if len(nodes) == 0 {
+ return nil, &NotFoundError{userprofile.Label}
+ }
+ return nodes[0], nil
+}
+
+// FirstX is like First, but panics if an error occurs.
+func (upq *UserProfileQuery) FirstX(ctx context.Context) *UserProfile {
+ node, err := upq.First(ctx)
+ if err != nil && !IsNotFound(err) {
+ panic(err)
+ }
+ return node
+}
+
+// FirstID returns the first UserProfile ID from the query.
+// Returns a *NotFoundError when no UserProfile ID was found.
+func (upq *UserProfileQuery) FirstID(ctx context.Context) (id int, err error) {
+ var ids []int
+ if ids, err = upq.Limit(1).IDs(setContextOp(ctx, upq.ctx, "FirstID")); err != nil {
+ return
+ }
+ if len(ids) == 0 {
+ err = &NotFoundError{userprofile.Label}
+ return
+ }
+ return ids[0], nil
+}
+
+// FirstIDX is like FirstID, but panics if an error occurs.
+func (upq *UserProfileQuery) FirstIDX(ctx context.Context) int {
+ id, err := upq.FirstID(ctx)
+ if err != nil && !IsNotFound(err) {
+ panic(err)
+ }
+ return id
+}
+
+// Only returns a single UserProfile entity found by the query, ensuring it only returns one.
+// Returns a *NotSingularError when more than one UserProfile entity is found.
+// Returns a *NotFoundError when no UserProfile entities are found.
+func (upq *UserProfileQuery) Only(ctx context.Context) (*UserProfile, error) {
+ nodes, err := upq.Limit(2).All(setContextOp(ctx, upq.ctx, "Only"))
+ if err != nil {
+ return nil, err
+ }
+ switch len(nodes) {
+ case 1:
+ return nodes[0], nil
+ case 0:
+ return nil, &NotFoundError{userprofile.Label}
+ default:
+ return nil, &NotSingularError{userprofile.Label}
+ }
+}
+
+// OnlyX is like Only, but panics if an error occurs.
+func (upq *UserProfileQuery) OnlyX(ctx context.Context) *UserProfile {
+ node, err := upq.Only(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return node
+}
+
+// OnlyID is like Only, but returns the only UserProfile ID in the query.
+// Returns a *NotSingularError when more than one UserProfile ID is found.
+// Returns a *NotFoundError when no entities are found.
+func (upq *UserProfileQuery) OnlyID(ctx context.Context) (id int, err error) {
+ var ids []int
+ if ids, err = upq.Limit(2).IDs(setContextOp(ctx, upq.ctx, "OnlyID")); err != nil {
+ return
+ }
+ switch len(ids) {
+ case 1:
+ id = ids[0]
+ case 0:
+ err = &NotFoundError{userprofile.Label}
+ default:
+ err = &NotSingularError{userprofile.Label}
+ }
+ return
+}
+
+// OnlyIDX is like OnlyID, but panics if an error occurs.
+func (upq *UserProfileQuery) OnlyIDX(ctx context.Context) int {
+ id, err := upq.OnlyID(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
+// All executes the query and returns a list of UserProfiles.
+func (upq *UserProfileQuery) All(ctx context.Context) ([]*UserProfile, error) {
+ ctx = setContextOp(ctx, upq.ctx, "All")
+ if err := upq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ qr := querierAll[[]*UserProfile, *UserProfileQuery]()
+ return withInterceptors[[]*UserProfile](ctx, upq, qr, upq.inters)
+}
+
+// AllX is like All, but panics if an error occurs.
+func (upq *UserProfileQuery) AllX(ctx context.Context) []*UserProfile {
+ nodes, err := upq.All(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return nodes
+}
+
+// IDs executes the query and returns a list of UserProfile IDs.
+func (upq *UserProfileQuery) IDs(ctx context.Context) (ids []int, err error) {
+ if upq.ctx.Unique == nil && upq.path != nil {
+ upq.Unique(true)
+ }
+ ctx = setContextOp(ctx, upq.ctx, "IDs")
+ if err = upq.Select(userprofile.FieldID).Scan(ctx, &ids); err != nil {
+ return nil, err
+ }
+ return ids, nil
+}
+
+// IDsX is like IDs, but panics if an error occurs.
+func (upq *UserProfileQuery) IDsX(ctx context.Context) []int {
+ ids, err := upq.IDs(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return ids
+}
+
+// Count returns the count of the given query.
+func (upq *UserProfileQuery) Count(ctx context.Context) (int, error) {
+ ctx = setContextOp(ctx, upq.ctx, "Count")
+ if err := upq.prepareQuery(ctx); err != nil {
+ return 0, err
+ }
+ return withInterceptors[int](ctx, upq, querierCount[*UserProfileQuery](), upq.inters)
+}
+
+// CountX is like Count, but panics if an error occurs.
+func (upq *UserProfileQuery) CountX(ctx context.Context) int {
+ count, err := upq.Count(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return count
+}
+
+// Exist returns true if the query has elements in the graph.
+func (upq *UserProfileQuery) Exist(ctx context.Context) (bool, error) {
+ ctx = setContextOp(ctx, upq.ctx, "Exist")
+ switch _, err := upq.FirstID(ctx); {
+ case IsNotFound(err):
+ return false, nil
+ case err != nil:
+ return false, fmt.Errorf("ent: check existence: %w", err)
+ default:
+ return true, nil
+ }
+}
+
+// ExistX is like Exist, but panics if an error occurs.
+func (upq *UserProfileQuery) ExistX(ctx context.Context) bool {
+ exist, err := upq.Exist(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return exist
+}
+
+// Clone returns a duplicate of the UserProfileQuery builder, including all associated steps. It can be
+// used to prepare common query builders and use them differently after the clone is made.
+func (upq *UserProfileQuery) Clone() *UserProfileQuery {
+ if upq == nil {
+ return nil
+ }
+ return &UserProfileQuery{
+ config: upq.config,
+ ctx: upq.ctx.Clone(),
+ order: append([]userprofile.OrderOption{}, upq.order...),
+ inters: append([]Interceptor{}, upq.inters...),
+ predicates: append([]predicate.UserProfile{}, upq.predicates...),
+ withUser: upq.withUser.Clone(),
+ withTexture: upq.withTexture.Clone(),
+ withUsertexture: upq.withUsertexture.Clone(),
+ // clone intermediate query.
+ sql: upq.sql.Clone(),
+ path: upq.path,
+ }
+}
+
+// WithUser tells the query-builder to eager-load the nodes that are connected to
+// the "user" edge. The optional arguments are used to configure the query builder of the edge.
+func (upq *UserProfileQuery) WithUser(opts ...func(*UserQuery)) *UserProfileQuery {
+ query := (&UserClient{config: upq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ upq.withUser = query
+ return upq
+}
+
+// WithTexture tells the query-builder to eager-load the nodes that are connected to
+// the "texture" edge. The optional arguments are used to configure the query builder of the edge.
+func (upq *UserProfileQuery) WithTexture(opts ...func(*TextureQuery)) *UserProfileQuery {
+ query := (&TextureClient{config: upq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ upq.withTexture = query
+ return upq
+}
+
+// WithUsertexture tells the query-builder to eager-load the nodes that are connected to
+// the "usertexture" edge. The optional arguments are used to configure the query builder of the edge.
+func (upq *UserProfileQuery) WithUsertexture(opts ...func(*UserTextureQuery)) *UserProfileQuery {
+ query := (&UserTextureClient{config: upq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ upq.withUsertexture = query
+ return upq
+}
+
+// GroupBy is used to group vertices by one or more fields/columns.
+// It is often used with aggregate functions, like: count, max, mean, min, sum.
+//
+// Example:
+//
+// var v []struct {
+// Name string `json:"name,omitempty"`
+// Count int `json:"count,omitempty"`
+// }
+//
+// client.UserProfile.Query().
+// GroupBy(userprofile.FieldName).
+// Aggregate(ent.Count()).
+// Scan(ctx, &v)
+func (upq *UserProfileQuery) GroupBy(field string, fields ...string) *UserProfileGroupBy {
+ upq.ctx.Fields = append([]string{field}, fields...)
+ grbuild := &UserProfileGroupBy{build: upq}
+ grbuild.flds = &upq.ctx.Fields
+ grbuild.label = userprofile.Label
+ grbuild.scan = grbuild.Scan
+ return grbuild
+}
+
+// Select allows the selection one or more fields/columns for the given query,
+// instead of selecting all fields in the entity.
+//
+// Example:
+//
+// var v []struct {
+// Name string `json:"name,omitempty"`
+// }
+//
+// client.UserProfile.Query().
+// Select(userprofile.FieldName).
+// Scan(ctx, &v)
+func (upq *UserProfileQuery) Select(fields ...string) *UserProfileSelect {
+ upq.ctx.Fields = append(upq.ctx.Fields, fields...)
+ sbuild := &UserProfileSelect{UserProfileQuery: upq}
+ sbuild.label = userprofile.Label
+ sbuild.flds, sbuild.scan = &upq.ctx.Fields, sbuild.Scan
+ return sbuild
+}
+
+// Aggregate returns a UserProfileSelect configured with the given aggregations.
+func (upq *UserProfileQuery) Aggregate(fns ...AggregateFunc) *UserProfileSelect {
+ return upq.Select().Aggregate(fns...)
+}
+
+func (upq *UserProfileQuery) prepareQuery(ctx context.Context) error {
+ for _, inter := range upq.inters {
+ if inter == nil {
+ return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
+ }
+ if trv, ok := inter.(Traverser); ok {
+ if err := trv.Traverse(ctx, upq); err != nil {
+ return err
+ }
+ }
+ }
+ for _, f := range upq.ctx.Fields {
+ if !userprofile.ValidColumn(f) {
+ return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+ }
+ }
+ if upq.path != nil {
+ prev, err := upq.path(ctx)
+ if err != nil {
+ return err
+ }
+ upq.sql = prev
+ }
+ return nil
+}
+
+func (upq *UserProfileQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*UserProfile, error) {
+ var (
+ nodes = []*UserProfile{}
+ withFKs = upq.withFKs
+ _spec = upq.querySpec()
+ loadedTypes = [3]bool{
+ upq.withUser != nil,
+ upq.withTexture != nil,
+ upq.withUsertexture != nil,
+ }
+ )
+ if upq.withUser != nil {
+ withFKs = true
+ }
+ if withFKs {
+ _spec.Node.Columns = append(_spec.Node.Columns, userprofile.ForeignKeys...)
+ }
+ _spec.ScanValues = func(columns []string) ([]any, error) {
+ return (*UserProfile).scanValues(nil, columns)
+ }
+ _spec.Assign = func(columns []string, values []any) error {
+ node := &UserProfile{config: upq.config}
+ nodes = append(nodes, node)
+ node.Edges.loadedTypes = loadedTypes
+ return node.assignValues(columns, values)
+ }
+ if len(upq.modifiers) > 0 {
+ _spec.Modifiers = upq.modifiers
+ }
+ for i := range hooks {
+ hooks[i](ctx, _spec)
+ }
+ if err := sqlgraph.QueryNodes(ctx, upq.driver, _spec); err != nil {
+ return nil, err
+ }
+ if len(nodes) == 0 {
+ return nodes, nil
+ }
+ if query := upq.withUser; query != nil {
+ if err := upq.loadUser(ctx, query, nodes, nil,
+ func(n *UserProfile, e *User) { n.Edges.User = e }); err != nil {
+ return nil, err
+ }
+ }
+ if query := upq.withTexture; query != nil {
+ if err := upq.loadTexture(ctx, query, nodes,
+ func(n *UserProfile) { n.Edges.Texture = []*Texture{} },
+ func(n *UserProfile, e *Texture) { n.Edges.Texture = append(n.Edges.Texture, e) }); err != nil {
+ return nil, err
+ }
+ }
+ if query := upq.withUsertexture; query != nil {
+ if err := upq.loadUsertexture(ctx, query, nodes,
+ func(n *UserProfile) { n.Edges.Usertexture = []*UserTexture{} },
+ func(n *UserProfile, e *UserTexture) { n.Edges.Usertexture = append(n.Edges.Usertexture, e) }); err != nil {
+ return nil, err
+ }
+ }
+ return nodes, nil
+}
+
+func (upq *UserProfileQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*UserProfile, init func(*UserProfile), assign func(*UserProfile, *User)) error {
+ ids := make([]int, 0, len(nodes))
+ nodeids := make(map[int][]*UserProfile)
+ for i := range nodes {
+ if nodes[i].user_profile == nil {
+ continue
+ }
+ fk := *nodes[i].user_profile
+ if _, ok := nodeids[fk]; !ok {
+ ids = append(ids, fk)
+ }
+ nodeids[fk] = append(nodeids[fk], nodes[i])
+ }
+ if len(ids) == 0 {
+ return nil
+ }
+ query.Where(user.IDIn(ids...))
+ neighbors, err := query.All(ctx)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ nodes, ok := nodeids[n.ID]
+ if !ok {
+ return fmt.Errorf(`unexpected foreign-key "user_profile" returned %v`, n.ID)
+ }
+ for i := range nodes {
+ assign(nodes[i], n)
+ }
+ }
+ return nil
+}
+func (upq *UserProfileQuery) loadTexture(ctx context.Context, query *TextureQuery, nodes []*UserProfile, init func(*UserProfile), assign func(*UserProfile, *Texture)) error {
+ edgeIDs := make([]driver.Value, len(nodes))
+ byID := make(map[int]*UserProfile)
+ nids := make(map[int]map[*UserProfile]struct{})
+ for i, node := range nodes {
+ edgeIDs[i] = node.ID
+ byID[node.ID] = node
+ if init != nil {
+ init(node)
+ }
+ }
+ query.Where(func(s *sql.Selector) {
+ joinT := sql.Table(userprofile.TextureTable)
+ s.Join(joinT).On(s.C(texture.FieldID), joinT.C(userprofile.TexturePrimaryKey[0]))
+ s.Where(sql.InValues(joinT.C(userprofile.TexturePrimaryKey[1]), edgeIDs...))
+ columns := s.SelectedColumns()
+ s.Select(joinT.C(userprofile.TexturePrimaryKey[1]))
+ s.AppendSelect(columns...)
+ s.SetDistinct(false)
+ })
+ if err := query.prepareQuery(ctx); err != nil {
+ return err
+ }
+ qr := QuerierFunc(func(ctx context.Context, q Query) (Value, error) {
+ return query.sqlAll(ctx, func(_ context.Context, spec *sqlgraph.QuerySpec) {
+ assign := spec.Assign
+ values := spec.ScanValues
+ spec.ScanValues = func(columns []string) ([]any, error) {
+ values, err := values(columns[1:])
+ if err != nil {
+ return nil, err
+ }
+ return append([]any{new(sql.NullInt64)}, values...), nil
+ }
+ spec.Assign = func(columns []string, values []any) error {
+ outValue := int(values[0].(*sql.NullInt64).Int64)
+ inValue := int(values[1].(*sql.NullInt64).Int64)
+ if nids[inValue] == nil {
+ nids[inValue] = map[*UserProfile]struct{}{byID[outValue]: {}}
+ return assign(columns[1:], values[1:])
+ }
+ nids[inValue][byID[outValue]] = struct{}{}
+ return nil
+ }
+ })
+ })
+ neighbors, err := withInterceptors[[]*Texture](ctx, query, qr, query.inters)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ nodes, ok := nids[n.ID]
+ if !ok {
+ return fmt.Errorf(`unexpected "texture" node returned %v`, n.ID)
+ }
+ for kn := range nodes {
+ assign(kn, n)
+ }
+ }
+ return nil
+}
+func (upq *UserProfileQuery) loadUsertexture(ctx context.Context, query *UserTextureQuery, nodes []*UserProfile, init func(*UserProfile), assign func(*UserProfile, *UserTexture)) error {
+ fks := make([]driver.Value, 0, len(nodes))
+ nodeids := make(map[int]*UserProfile)
+ for i := range nodes {
+ fks = append(fks, nodes[i].ID)
+ nodeids[nodes[i].ID] = nodes[i]
+ if init != nil {
+ init(nodes[i])
+ }
+ }
+ if len(query.ctx.Fields) > 0 {
+ query.ctx.AppendFieldOnce(usertexture.FieldUserProfileID)
+ }
+ query.Where(predicate.UserTexture(func(s *sql.Selector) {
+ s.Where(sql.InValues(s.C(userprofile.UsertextureColumn), fks...))
+ }))
+ neighbors, err := query.All(ctx)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ fk := n.UserProfileID
+ node, ok := nodeids[fk]
+ if !ok {
+ return fmt.Errorf(`unexpected referenced foreign-key "user_profile_id" returned %v for node %v`, fk, n.ID)
+ }
+ assign(node, n)
+ }
+ return nil
+}
+
+func (upq *UserProfileQuery) sqlCount(ctx context.Context) (int, error) {
+ _spec := upq.querySpec()
+ if len(upq.modifiers) > 0 {
+ _spec.Modifiers = upq.modifiers
+ }
+ _spec.Node.Columns = upq.ctx.Fields
+ if len(upq.ctx.Fields) > 0 {
+ _spec.Unique = upq.ctx.Unique != nil && *upq.ctx.Unique
+ }
+ return sqlgraph.CountNodes(ctx, upq.driver, _spec)
+}
+
+func (upq *UserProfileQuery) querySpec() *sqlgraph.QuerySpec {
+ _spec := sqlgraph.NewQuerySpec(userprofile.Table, userprofile.Columns, sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt))
+ _spec.From = upq.sql
+ if unique := upq.ctx.Unique; unique != nil {
+ _spec.Unique = *unique
+ } else if upq.path != nil {
+ _spec.Unique = true
+ }
+ if fields := upq.ctx.Fields; len(fields) > 0 {
+ _spec.Node.Columns = make([]string, 0, len(fields))
+ _spec.Node.Columns = append(_spec.Node.Columns, userprofile.FieldID)
+ for i := range fields {
+ if fields[i] != userprofile.FieldID {
+ _spec.Node.Columns = append(_spec.Node.Columns, fields[i])
+ }
+ }
+ }
+ if ps := upq.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if limit := upq.ctx.Limit; limit != nil {
+ _spec.Limit = *limit
+ }
+ if offset := upq.ctx.Offset; offset != nil {
+ _spec.Offset = *offset
+ }
+ if ps := upq.order; len(ps) > 0 {
+ _spec.Order = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ return _spec
+}
+
+func (upq *UserProfileQuery) sqlQuery(ctx context.Context) *sql.Selector {
+ builder := sql.Dialect(upq.driver.Dialect())
+ t1 := builder.Table(userprofile.Table)
+ columns := upq.ctx.Fields
+ if len(columns) == 0 {
+ columns = userprofile.Columns
+ }
+ selector := builder.Select(t1.Columns(columns...)...).From(t1)
+ if upq.sql != nil {
+ selector = upq.sql
+ selector.Select(selector.Columns(columns...)...)
+ }
+ if upq.ctx.Unique != nil && *upq.ctx.Unique {
+ selector.Distinct()
+ }
+ for _, m := range upq.modifiers {
+ m(selector)
+ }
+ for _, p := range upq.predicates {
+ p(selector)
+ }
+ for _, p := range upq.order {
+ p(selector)
+ }
+ if offset := upq.ctx.Offset; offset != nil {
+ // limit is mandatory for offset clause. We start
+ // with default value, and override it below if needed.
+ selector.Offset(*offset).Limit(math.MaxInt32)
+ }
+ if limit := upq.ctx.Limit; limit != nil {
+ selector.Limit(*limit)
+ }
+ return selector
+}
+
+// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
+// updated, deleted or "selected ... for update" by other sessions, until the transaction is
+// either committed or rolled-back.
+func (upq *UserProfileQuery) ForUpdate(opts ...sql.LockOption) *UserProfileQuery {
+ if upq.driver.Dialect() == dialect.Postgres {
+ upq.Unique(false)
+ }
+ upq.modifiers = append(upq.modifiers, func(s *sql.Selector) {
+ s.ForUpdate(opts...)
+ })
+ return upq
+}
+
+// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
+// on any rows that are read. Other sessions can read the rows, but cannot modify them
+// until your transaction commits.
+func (upq *UserProfileQuery) ForShare(opts ...sql.LockOption) *UserProfileQuery {
+ if upq.driver.Dialect() == dialect.Postgres {
+ upq.Unique(false)
+ }
+ upq.modifiers = append(upq.modifiers, func(s *sql.Selector) {
+ s.ForShare(opts...)
+ })
+ return upq
+}
+
+// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
+// updated, deleted or "selected ... for update" by other sessions, until the transaction is
+// either committed or rolled-back.
+func (upq *UserProfileQuery) ForUpdateA(opts ...sql.LockOption) *UserProfileQuery {
+ if upq.driver.Dialect() == dialect.SQLite {
+ return upq
+ }
+ return upq.ForUpdate(opts...)
+}
+
+// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
+// on any rows that are read. Other sessions can read the rows, but cannot modify them
+// until your transaction commits.
+func (upq *UserProfileQuery) ForShareA(opts ...sql.LockOption) *UserProfileQuery {
+ if upq.driver.Dialect() == dialect.SQLite {
+ return upq
+ }
+ return upq.ForShare(opts...)
+}
+
+// UserProfileGroupBy is the group-by builder for UserProfile entities.
+type UserProfileGroupBy struct {
+ selector
+ build *UserProfileQuery
+}
+
+// Aggregate adds the given aggregation functions to the group-by query.
+func (upgb *UserProfileGroupBy) Aggregate(fns ...AggregateFunc) *UserProfileGroupBy {
+ upgb.fns = append(upgb.fns, fns...)
+ return upgb
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (upgb *UserProfileGroupBy) Scan(ctx context.Context, v any) error {
+ ctx = setContextOp(ctx, upgb.build.ctx, "GroupBy")
+ if err := upgb.build.prepareQuery(ctx); err != nil {
+ return err
+ }
+ return scanWithInterceptors[*UserProfileQuery, *UserProfileGroupBy](ctx, upgb.build, upgb, upgb.build.inters, v)
+}
+
+func (upgb *UserProfileGroupBy) sqlScan(ctx context.Context, root *UserProfileQuery, v any) error {
+ selector := root.sqlQuery(ctx).Select()
+ aggregation := make([]string, 0, len(upgb.fns))
+ for _, fn := range upgb.fns {
+ aggregation = append(aggregation, fn(selector))
+ }
+ if len(selector.SelectedColumns()) == 0 {
+ columns := make([]string, 0, len(*upgb.flds)+len(upgb.fns))
+ for _, f := range *upgb.flds {
+ columns = append(columns, selector.C(f))
+ }
+ columns = append(columns, aggregation...)
+ selector.Select(columns...)
+ }
+ selector.GroupBy(selector.Columns(*upgb.flds...)...)
+ if err := selector.Err(); err != nil {
+ return err
+ }
+ rows := &sql.Rows{}
+ query, args := selector.Query()
+ if err := upgb.build.driver.Query(ctx, query, args, rows); err != nil {
+ return err
+ }
+ defer rows.Close()
+ return sql.ScanSlice(rows, v)
+}
+
+// UserProfileSelect is the builder for selecting fields of UserProfile entities.
+type UserProfileSelect struct {
+ *UserProfileQuery
+ selector
+}
+
+// Aggregate adds the given aggregation functions to the selector query.
+func (ups *UserProfileSelect) Aggregate(fns ...AggregateFunc) *UserProfileSelect {
+ ups.fns = append(ups.fns, fns...)
+ return ups
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (ups *UserProfileSelect) Scan(ctx context.Context, v any) error {
+ ctx = setContextOp(ctx, ups.ctx, "Select")
+ if err := ups.prepareQuery(ctx); err != nil {
+ return err
+ }
+ return scanWithInterceptors[*UserProfileQuery, *UserProfileSelect](ctx, ups.UserProfileQuery, ups, ups.inters, v)
+}
+
+func (ups *UserProfileSelect) sqlScan(ctx context.Context, root *UserProfileQuery, v any) error {
+ selector := root.sqlQuery(ctx)
+ aggregation := make([]string, 0, len(ups.fns))
+ for _, fn := range ups.fns {
+ aggregation = append(aggregation, fn(selector))
+ }
+ switch n := len(*ups.selector.flds); {
+ case n == 0 && len(aggregation) > 0:
+ selector.Select(aggregation...)
+ case n != 0 && len(aggregation) > 0:
+ selector.AppendSelect(aggregation...)
+ }
+ rows := &sql.Rows{}
+ query, args := selector.Query()
+ if err := ups.driver.Query(ctx, query, args, rows); err != nil {
+ return err
+ }
+ defer rows.Close()
+ return sql.ScanSlice(rows, v)
+}
diff --git a/db/ent/userprofile_update.go b/db/ent/userprofile_update.go
new file mode 100644
index 0000000..210775b
--- /dev/null
+++ b/db/ent/userprofile_update.go
@@ -0,0 +1,652 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+)
+
+// UserProfileUpdate is the builder for updating UserProfile entities.
+type UserProfileUpdate struct {
+ config
+ hooks []Hook
+ mutation *UserProfileMutation
+}
+
+// Where appends a list predicates to the UserProfileUpdate builder.
+func (upu *UserProfileUpdate) Where(ps ...predicate.UserProfile) *UserProfileUpdate {
+ upu.mutation.Where(ps...)
+ return upu
+}
+
+// SetName sets the "name" field.
+func (upu *UserProfileUpdate) SetName(s string) *UserProfileUpdate {
+ upu.mutation.SetName(s)
+ return upu
+}
+
+// SetUUID sets the "uuid" field.
+func (upu *UserProfileUpdate) SetUUID(s string) *UserProfileUpdate {
+ upu.mutation.SetUUID(s)
+ return upu
+}
+
+// SetUserID sets the "user" edge to the User entity by ID.
+func (upu *UserProfileUpdate) SetUserID(id int) *UserProfileUpdate {
+ upu.mutation.SetUserID(id)
+ return upu
+}
+
+// SetUser sets the "user" edge to the User entity.
+func (upu *UserProfileUpdate) SetUser(u *User) *UserProfileUpdate {
+ return upu.SetUserID(u.ID)
+}
+
+// AddTextureIDs adds the "texture" edge to the Texture entity by IDs.
+func (upu *UserProfileUpdate) AddTextureIDs(ids ...int) *UserProfileUpdate {
+ upu.mutation.AddTextureIDs(ids...)
+ return upu
+}
+
+// AddTexture adds the "texture" edges to the Texture entity.
+func (upu *UserProfileUpdate) AddTexture(t ...*Texture) *UserProfileUpdate {
+ ids := make([]int, len(t))
+ for i := range t {
+ ids[i] = t[i].ID
+ }
+ return upu.AddTextureIDs(ids...)
+}
+
+// AddUsertextureIDs adds the "usertexture" edge to the UserTexture entity by IDs.
+func (upu *UserProfileUpdate) AddUsertextureIDs(ids ...int) *UserProfileUpdate {
+ upu.mutation.AddUsertextureIDs(ids...)
+ return upu
+}
+
+// AddUsertexture adds the "usertexture" edges to the UserTexture entity.
+func (upu *UserProfileUpdate) AddUsertexture(u ...*UserTexture) *UserProfileUpdate {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return upu.AddUsertextureIDs(ids...)
+}
+
+// Mutation returns the UserProfileMutation object of the builder.
+func (upu *UserProfileUpdate) Mutation() *UserProfileMutation {
+ return upu.mutation
+}
+
+// ClearUser clears the "user" edge to the User entity.
+func (upu *UserProfileUpdate) ClearUser() *UserProfileUpdate {
+ upu.mutation.ClearUser()
+ return upu
+}
+
+// ClearTexture clears all "texture" edges to the Texture entity.
+func (upu *UserProfileUpdate) ClearTexture() *UserProfileUpdate {
+ upu.mutation.ClearTexture()
+ return upu
+}
+
+// RemoveTextureIDs removes the "texture" edge to Texture entities by IDs.
+func (upu *UserProfileUpdate) RemoveTextureIDs(ids ...int) *UserProfileUpdate {
+ upu.mutation.RemoveTextureIDs(ids...)
+ return upu
+}
+
+// RemoveTexture removes "texture" edges to Texture entities.
+func (upu *UserProfileUpdate) RemoveTexture(t ...*Texture) *UserProfileUpdate {
+ ids := make([]int, len(t))
+ for i := range t {
+ ids[i] = t[i].ID
+ }
+ return upu.RemoveTextureIDs(ids...)
+}
+
+// ClearUsertexture clears all "usertexture" edges to the UserTexture entity.
+func (upu *UserProfileUpdate) ClearUsertexture() *UserProfileUpdate {
+ upu.mutation.ClearUsertexture()
+ return upu
+}
+
+// RemoveUsertextureIDs removes the "usertexture" edge to UserTexture entities by IDs.
+func (upu *UserProfileUpdate) RemoveUsertextureIDs(ids ...int) *UserProfileUpdate {
+ upu.mutation.RemoveUsertextureIDs(ids...)
+ return upu
+}
+
+// RemoveUsertexture removes "usertexture" edges to UserTexture entities.
+func (upu *UserProfileUpdate) RemoveUsertexture(u ...*UserTexture) *UserProfileUpdate {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return upu.RemoveUsertextureIDs(ids...)
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (upu *UserProfileUpdate) Save(ctx context.Context) (int, error) {
+ return withHooks(ctx, upu.sqlSave, upu.mutation, upu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (upu *UserProfileUpdate) SaveX(ctx context.Context) int {
+ affected, err := upu.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return affected
+}
+
+// Exec executes the query.
+func (upu *UserProfileUpdate) Exec(ctx context.Context) error {
+ _, err := upu.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (upu *UserProfileUpdate) ExecX(ctx context.Context) {
+ if err := upu.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (upu *UserProfileUpdate) check() error {
+ if _, ok := upu.mutation.UserID(); upu.mutation.UserCleared() && !ok {
+ return errors.New(`ent: clearing a required unique edge "UserProfile.user"`)
+ }
+ return nil
+}
+
+func (upu *UserProfileUpdate) sqlSave(ctx context.Context) (n int, err error) {
+ if err := upu.check(); err != nil {
+ return n, err
+ }
+ _spec := sqlgraph.NewUpdateSpec(userprofile.Table, userprofile.Columns, sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt))
+ if ps := upu.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if value, ok := upu.mutation.Name(); ok {
+ _spec.SetField(userprofile.FieldName, field.TypeString, value)
+ }
+ if value, ok := upu.mutation.UUID(); ok {
+ _spec.SetField(userprofile.FieldUUID, field.TypeString, value)
+ }
+ if upu.mutation.UserCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: true,
+ Table: userprofile.UserTable,
+ Columns: []string{userprofile.UserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := upu.mutation.UserIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: true,
+ Table: userprofile.UserTable,
+ Columns: []string{userprofile.UserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if upu.mutation.TextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: true,
+ Table: userprofile.TextureTable,
+ Columns: userprofile.TexturePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := upu.mutation.RemovedTextureIDs(); len(nodes) > 0 && !upu.mutation.TextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: true,
+ Table: userprofile.TextureTable,
+ Columns: userprofile.TexturePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := upu.mutation.TextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: true,
+ Table: userprofile.TextureTable,
+ Columns: userprofile.TexturePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if upu.mutation.UsertextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: userprofile.UsertextureTable,
+ Columns: []string{userprofile.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := upu.mutation.RemovedUsertextureIDs(); len(nodes) > 0 && !upu.mutation.UsertextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: userprofile.UsertextureTable,
+ Columns: []string{userprofile.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := upu.mutation.UsertextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: userprofile.UsertextureTable,
+ Columns: []string{userprofile.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if n, err = sqlgraph.UpdateNodes(ctx, upu.driver, _spec); err != nil {
+ if _, ok := err.(*sqlgraph.NotFoundError); ok {
+ err = &NotFoundError{userprofile.Label}
+ } else if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return 0, err
+ }
+ upu.mutation.done = true
+ return n, nil
+}
+
+// UserProfileUpdateOne is the builder for updating a single UserProfile entity.
+type UserProfileUpdateOne struct {
+ config
+ fields []string
+ hooks []Hook
+ mutation *UserProfileMutation
+}
+
+// SetName sets the "name" field.
+func (upuo *UserProfileUpdateOne) SetName(s string) *UserProfileUpdateOne {
+ upuo.mutation.SetName(s)
+ return upuo
+}
+
+// SetUUID sets the "uuid" field.
+func (upuo *UserProfileUpdateOne) SetUUID(s string) *UserProfileUpdateOne {
+ upuo.mutation.SetUUID(s)
+ return upuo
+}
+
+// SetUserID sets the "user" edge to the User entity by ID.
+func (upuo *UserProfileUpdateOne) SetUserID(id int) *UserProfileUpdateOne {
+ upuo.mutation.SetUserID(id)
+ return upuo
+}
+
+// SetUser sets the "user" edge to the User entity.
+func (upuo *UserProfileUpdateOne) SetUser(u *User) *UserProfileUpdateOne {
+ return upuo.SetUserID(u.ID)
+}
+
+// AddTextureIDs adds the "texture" edge to the Texture entity by IDs.
+func (upuo *UserProfileUpdateOne) AddTextureIDs(ids ...int) *UserProfileUpdateOne {
+ upuo.mutation.AddTextureIDs(ids...)
+ return upuo
+}
+
+// AddTexture adds the "texture" edges to the Texture entity.
+func (upuo *UserProfileUpdateOne) AddTexture(t ...*Texture) *UserProfileUpdateOne {
+ ids := make([]int, len(t))
+ for i := range t {
+ ids[i] = t[i].ID
+ }
+ return upuo.AddTextureIDs(ids...)
+}
+
+// AddUsertextureIDs adds the "usertexture" edge to the UserTexture entity by IDs.
+func (upuo *UserProfileUpdateOne) AddUsertextureIDs(ids ...int) *UserProfileUpdateOne {
+ upuo.mutation.AddUsertextureIDs(ids...)
+ return upuo
+}
+
+// AddUsertexture adds the "usertexture" edges to the UserTexture entity.
+func (upuo *UserProfileUpdateOne) AddUsertexture(u ...*UserTexture) *UserProfileUpdateOne {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return upuo.AddUsertextureIDs(ids...)
+}
+
+// Mutation returns the UserProfileMutation object of the builder.
+func (upuo *UserProfileUpdateOne) Mutation() *UserProfileMutation {
+ return upuo.mutation
+}
+
+// ClearUser clears the "user" edge to the User entity.
+func (upuo *UserProfileUpdateOne) ClearUser() *UserProfileUpdateOne {
+ upuo.mutation.ClearUser()
+ return upuo
+}
+
+// ClearTexture clears all "texture" edges to the Texture entity.
+func (upuo *UserProfileUpdateOne) ClearTexture() *UserProfileUpdateOne {
+ upuo.mutation.ClearTexture()
+ return upuo
+}
+
+// RemoveTextureIDs removes the "texture" edge to Texture entities by IDs.
+func (upuo *UserProfileUpdateOne) RemoveTextureIDs(ids ...int) *UserProfileUpdateOne {
+ upuo.mutation.RemoveTextureIDs(ids...)
+ return upuo
+}
+
+// RemoveTexture removes "texture" edges to Texture entities.
+func (upuo *UserProfileUpdateOne) RemoveTexture(t ...*Texture) *UserProfileUpdateOne {
+ ids := make([]int, len(t))
+ for i := range t {
+ ids[i] = t[i].ID
+ }
+ return upuo.RemoveTextureIDs(ids...)
+}
+
+// ClearUsertexture clears all "usertexture" edges to the UserTexture entity.
+func (upuo *UserProfileUpdateOne) ClearUsertexture() *UserProfileUpdateOne {
+ upuo.mutation.ClearUsertexture()
+ return upuo
+}
+
+// RemoveUsertextureIDs removes the "usertexture" edge to UserTexture entities by IDs.
+func (upuo *UserProfileUpdateOne) RemoveUsertextureIDs(ids ...int) *UserProfileUpdateOne {
+ upuo.mutation.RemoveUsertextureIDs(ids...)
+ return upuo
+}
+
+// RemoveUsertexture removes "usertexture" edges to UserTexture entities.
+func (upuo *UserProfileUpdateOne) RemoveUsertexture(u ...*UserTexture) *UserProfileUpdateOne {
+ ids := make([]int, len(u))
+ for i := range u {
+ ids[i] = u[i].ID
+ }
+ return upuo.RemoveUsertextureIDs(ids...)
+}
+
+// Where appends a list predicates to the UserProfileUpdate builder.
+func (upuo *UserProfileUpdateOne) Where(ps ...predicate.UserProfile) *UserProfileUpdateOne {
+ upuo.mutation.Where(ps...)
+ return upuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (upuo *UserProfileUpdateOne) Select(field string, fields ...string) *UserProfileUpdateOne {
+ upuo.fields = append([]string{field}, fields...)
+ return upuo
+}
+
+// Save executes the query and returns the updated UserProfile entity.
+func (upuo *UserProfileUpdateOne) Save(ctx context.Context) (*UserProfile, error) {
+ return withHooks(ctx, upuo.sqlSave, upuo.mutation, upuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (upuo *UserProfileUpdateOne) SaveX(ctx context.Context) *UserProfile {
+ node, err := upuo.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return node
+}
+
+// Exec executes the query on the entity.
+func (upuo *UserProfileUpdateOne) Exec(ctx context.Context) error {
+ _, err := upuo.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (upuo *UserProfileUpdateOne) ExecX(ctx context.Context) {
+ if err := upuo.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (upuo *UserProfileUpdateOne) check() error {
+ if _, ok := upuo.mutation.UserID(); upuo.mutation.UserCleared() && !ok {
+ return errors.New(`ent: clearing a required unique edge "UserProfile.user"`)
+ }
+ return nil
+}
+
+func (upuo *UserProfileUpdateOne) sqlSave(ctx context.Context) (_node *UserProfile, err error) {
+ if err := upuo.check(); err != nil {
+ return _node, err
+ }
+ _spec := sqlgraph.NewUpdateSpec(userprofile.Table, userprofile.Columns, sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt))
+ id, ok := upuo.mutation.ID()
+ if !ok {
+ return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "UserProfile.id" for update`)}
+ }
+ _spec.Node.ID.Value = id
+ if fields := upuo.fields; len(fields) > 0 {
+ _spec.Node.Columns = make([]string, 0, len(fields))
+ _spec.Node.Columns = append(_spec.Node.Columns, userprofile.FieldID)
+ for _, f := range fields {
+ if !userprofile.ValidColumn(f) {
+ return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+ }
+ if f != userprofile.FieldID {
+ _spec.Node.Columns = append(_spec.Node.Columns, f)
+ }
+ }
+ }
+ if ps := upuo.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if value, ok := upuo.mutation.Name(); ok {
+ _spec.SetField(userprofile.FieldName, field.TypeString, value)
+ }
+ if value, ok := upuo.mutation.UUID(); ok {
+ _spec.SetField(userprofile.FieldUUID, field.TypeString, value)
+ }
+ if upuo.mutation.UserCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: true,
+ Table: userprofile.UserTable,
+ Columns: []string{userprofile.UserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := upuo.mutation.UserIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: true,
+ Table: userprofile.UserTable,
+ Columns: []string{userprofile.UserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if upuo.mutation.TextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: true,
+ Table: userprofile.TextureTable,
+ Columns: userprofile.TexturePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := upuo.mutation.RemovedTextureIDs(); len(nodes) > 0 && !upuo.mutation.TextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: true,
+ Table: userprofile.TextureTable,
+ Columns: userprofile.TexturePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := upuo.mutation.TextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2M,
+ Inverse: true,
+ Table: userprofile.TextureTable,
+ Columns: userprofile.TexturePrimaryKey,
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if upuo.mutation.UsertextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: userprofile.UsertextureTable,
+ Columns: []string{userprofile.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := upuo.mutation.RemovedUsertextureIDs(); len(nodes) > 0 && !upuo.mutation.UsertextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: userprofile.UsertextureTable,
+ Columns: []string{userprofile.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := upuo.mutation.UsertextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2M,
+ Inverse: true,
+ Table: userprofile.UsertextureTable,
+ Columns: []string{userprofile.UsertextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ _node = &UserProfile{config: upuo.config}
+ _spec.Assign = _node.assignValues
+ _spec.ScanValues = _node.scanValues
+ if err = sqlgraph.UpdateNode(ctx, upuo.driver, _spec); err != nil {
+ if _, ok := err.(*sqlgraph.NotFoundError); ok {
+ err = &NotFoundError{userprofile.Label}
+ } else if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return nil, err
+ }
+ upuo.mutation.done = true
+ return _node, nil
+}
diff --git a/db/ent/usertexture.go b/db/ent/usertexture.go
new file mode 100644
index 0000000..d792079
--- /dev/null
+++ b/db/ent/usertexture.go
@@ -0,0 +1,188 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "fmt"
+ "strings"
+
+ "entgo.io/ent"
+ "entgo.io/ent/dialect/sql"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+)
+
+// UserTexture is the model entity for the UserTexture schema.
+type UserTexture struct {
+ config `json:"-"`
+ // ID of the ent.
+ ID int `json:"id,omitempty"`
+ // UserProfileID holds the value of the "user_profile_id" field.
+ UserProfileID int `json:"user_profile_id,omitempty"`
+ // TextureID holds the value of the "texture_id" field.
+ TextureID int `json:"texture_id,omitempty"`
+ // Type holds the value of the "type" field.
+ Type string `json:"type,omitempty"`
+ // Variant holds the value of the "variant" field.
+ Variant string `json:"variant,omitempty"`
+ // Edges holds the relations/edges for other nodes in the graph.
+ // The values are being populated by the UserTextureQuery when eager-loading is set.
+ Edges UserTextureEdges `json:"edges"`
+ selectValues sql.SelectValues
+}
+
+// UserTextureEdges holds the relations/edges for other nodes in the graph.
+type UserTextureEdges struct {
+ // UserProfile holds the value of the user_profile edge.
+ UserProfile *UserProfile `json:"user_profile,omitempty"`
+ // Texture holds the value of the texture edge.
+ Texture *Texture `json:"texture,omitempty"`
+ // loadedTypes holds the information for reporting if a
+ // type was loaded (or requested) in eager-loading or not.
+ loadedTypes [2]bool
+}
+
+// UserProfileOrErr returns the UserProfile value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e UserTextureEdges) UserProfileOrErr() (*UserProfile, error) {
+ if e.loadedTypes[0] {
+ if e.UserProfile == nil {
+ // Edge was loaded but was not found.
+ return nil, &NotFoundError{label: userprofile.Label}
+ }
+ return e.UserProfile, nil
+ }
+ return nil, &NotLoadedError{edge: "user_profile"}
+}
+
+// TextureOrErr returns the Texture value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e UserTextureEdges) TextureOrErr() (*Texture, error) {
+ if e.loadedTypes[1] {
+ if e.Texture == nil {
+ // Edge was loaded but was not found.
+ return nil, &NotFoundError{label: texture.Label}
+ }
+ return e.Texture, nil
+ }
+ return nil, &NotLoadedError{edge: "texture"}
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*UserTexture) scanValues(columns []string) ([]any, error) {
+ values := make([]any, len(columns))
+ for i := range columns {
+ switch columns[i] {
+ case usertexture.FieldID, usertexture.FieldUserProfileID, usertexture.FieldTextureID:
+ values[i] = new(sql.NullInt64)
+ case usertexture.FieldType, usertexture.FieldVariant:
+ values[i] = new(sql.NullString)
+ default:
+ values[i] = new(sql.UnknownType)
+ }
+ }
+ return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the UserTexture fields.
+func (ut *UserTexture) assignValues(columns []string, values []any) error {
+ if m, n := len(values), len(columns); m < n {
+ return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+ }
+ for i := range columns {
+ switch columns[i] {
+ case usertexture.FieldID:
+ value, ok := values[i].(*sql.NullInt64)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field id", value)
+ }
+ ut.ID = int(value.Int64)
+ case usertexture.FieldUserProfileID:
+ if value, ok := values[i].(*sql.NullInt64); !ok {
+ return fmt.Errorf("unexpected type %T for field user_profile_id", values[i])
+ } else if value.Valid {
+ ut.UserProfileID = int(value.Int64)
+ }
+ case usertexture.FieldTextureID:
+ if value, ok := values[i].(*sql.NullInt64); !ok {
+ return fmt.Errorf("unexpected type %T for field texture_id", values[i])
+ } else if value.Valid {
+ ut.TextureID = int(value.Int64)
+ }
+ case usertexture.FieldType:
+ if value, ok := values[i].(*sql.NullString); !ok {
+ return fmt.Errorf("unexpected type %T for field type", values[i])
+ } else if value.Valid {
+ ut.Type = value.String
+ }
+ case usertexture.FieldVariant:
+ if value, ok := values[i].(*sql.NullString); !ok {
+ return fmt.Errorf("unexpected type %T for field variant", values[i])
+ } else if value.Valid {
+ ut.Variant = value.String
+ }
+ default:
+ ut.selectValues.Set(columns[i], values[i])
+ }
+ }
+ return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the UserTexture.
+// This includes values selected through modifiers, order, etc.
+func (ut *UserTexture) Value(name string) (ent.Value, error) {
+ return ut.selectValues.Get(name)
+}
+
+// QueryUserProfile queries the "user_profile" edge of the UserTexture entity.
+func (ut *UserTexture) QueryUserProfile() *UserProfileQuery {
+ return NewUserTextureClient(ut.config).QueryUserProfile(ut)
+}
+
+// QueryTexture queries the "texture" edge of the UserTexture entity.
+func (ut *UserTexture) QueryTexture() *TextureQuery {
+ return NewUserTextureClient(ut.config).QueryTexture(ut)
+}
+
+// Update returns a builder for updating this UserTexture.
+// Note that you need to call UserTexture.Unwrap() before calling this method if this UserTexture
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (ut *UserTexture) Update() *UserTextureUpdateOne {
+ return NewUserTextureClient(ut.config).UpdateOne(ut)
+}
+
+// Unwrap unwraps the UserTexture entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (ut *UserTexture) Unwrap() *UserTexture {
+ _tx, ok := ut.config.driver.(*txDriver)
+ if !ok {
+ panic("ent: UserTexture is not a transactional entity")
+ }
+ ut.config.driver = _tx.drv
+ return ut
+}
+
+// String implements the fmt.Stringer.
+func (ut *UserTexture) String() string {
+ var builder strings.Builder
+ builder.WriteString("UserTexture(")
+ builder.WriteString(fmt.Sprintf("id=%v, ", ut.ID))
+ builder.WriteString("user_profile_id=")
+ builder.WriteString(fmt.Sprintf("%v", ut.UserProfileID))
+ builder.WriteString(", ")
+ builder.WriteString("texture_id=")
+ builder.WriteString(fmt.Sprintf("%v", ut.TextureID))
+ builder.WriteString(", ")
+ builder.WriteString("type=")
+ builder.WriteString(ut.Type)
+ builder.WriteString(", ")
+ builder.WriteString("variant=")
+ builder.WriteString(ut.Variant)
+ builder.WriteByte(')')
+ return builder.String()
+}
+
+// UserTextures is a parsable slice of UserTexture.
+type UserTextures []*UserTexture
diff --git a/db/ent/usertexture/usertexture.go b/db/ent/usertexture/usertexture.go
new file mode 100644
index 0000000..6c8c797
--- /dev/null
+++ b/db/ent/usertexture/usertexture.go
@@ -0,0 +1,118 @@
+// Code generated by ent, DO NOT EDIT.
+
+package usertexture
+
+import (
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+const (
+ // Label holds the string label denoting the usertexture type in the database.
+ Label = "user_texture"
+ // FieldID holds the string denoting the id field in the database.
+ FieldID = "id"
+ // FieldUserProfileID holds the string denoting the user_profile_id field in the database.
+ FieldUserProfileID = "user_profile_id"
+ // FieldTextureID holds the string denoting the texture_id field in the database.
+ FieldTextureID = "texture_id"
+ // FieldType holds the string denoting the type field in the database.
+ FieldType = "type"
+ // FieldVariant holds the string denoting the variant field in the database.
+ FieldVariant = "variant"
+ // EdgeUserProfile holds the string denoting the user_profile edge name in mutations.
+ EdgeUserProfile = "user_profile"
+ // EdgeTexture holds the string denoting the texture edge name in mutations.
+ EdgeTexture = "texture"
+ // Table holds the table name of the usertexture in the database.
+ Table = "user_textures"
+ // UserProfileTable is the table that holds the user_profile relation/edge.
+ UserProfileTable = "user_textures"
+ // UserProfileInverseTable is the table name for the UserProfile entity.
+ // It exists in this package in order to avoid circular dependency with the "userprofile" package.
+ UserProfileInverseTable = "user_profiles"
+ // UserProfileColumn is the table column denoting the user_profile relation/edge.
+ UserProfileColumn = "user_profile_id"
+ // TextureTable is the table that holds the texture relation/edge.
+ TextureTable = "user_textures"
+ // TextureInverseTable is the table name for the Texture entity.
+ // It exists in this package in order to avoid circular dependency with the "texture" package.
+ TextureInverseTable = "textures"
+ // TextureColumn is the table column denoting the texture relation/edge.
+ TextureColumn = "texture_id"
+)
+
+// Columns holds all SQL columns for usertexture fields.
+var Columns = []string{
+ FieldID,
+ FieldUserProfileID,
+ FieldTextureID,
+ FieldType,
+ FieldVariant,
+}
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+ for i := range Columns {
+ if column == Columns[i] {
+ return true
+ }
+ }
+ return false
+}
+
+// OrderOption defines the ordering options for the UserTexture queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByUserProfileID orders the results by the user_profile_id field.
+func ByUserProfileID(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldUserProfileID, opts...).ToFunc()
+}
+
+// ByTextureID orders the results by the texture_id field.
+func ByTextureID(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldTextureID, opts...).ToFunc()
+}
+
+// ByType orders the results by the type field.
+func ByType(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldType, opts...).ToFunc()
+}
+
+// ByVariant orders the results by the variant field.
+func ByVariant(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldVariant, opts...).ToFunc()
+}
+
+// ByUserProfileField orders the results by user_profile field.
+func ByUserProfileField(field string, opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newUserProfileStep(), sql.OrderByField(field, opts...))
+ }
+}
+
+// ByTextureField orders the results by texture field.
+func ByTextureField(field string, opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newTextureStep(), sql.OrderByField(field, opts...))
+ }
+}
+func newUserProfileStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(UserProfileInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, UserProfileTable, UserProfileColumn),
+ )
+}
+func newTextureStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(TextureInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, TextureTable, TextureColumn),
+ )
+}
diff --git a/db/ent/usertexture/where.go b/db/ent/usertexture/where.go
new file mode 100644
index 0000000..19ff4cf
--- /dev/null
+++ b/db/ent/usertexture/where.go
@@ -0,0 +1,322 @@
+// Code generated by ent, DO NOT EDIT.
+
+package usertexture
+
+import (
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldLTE(FieldID, id))
+}
+
+// UserProfileID applies equality check predicate on the "user_profile_id" field. It's identical to UserProfileIDEQ.
+func UserProfileID(v int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEQ(FieldUserProfileID, v))
+}
+
+// TextureID applies equality check predicate on the "texture_id" field. It's identical to TextureIDEQ.
+func TextureID(v int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEQ(FieldTextureID, v))
+}
+
+// Type applies equality check predicate on the "type" field. It's identical to TypeEQ.
+func Type(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEQ(FieldType, v))
+}
+
+// Variant applies equality check predicate on the "variant" field. It's identical to VariantEQ.
+func Variant(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEQ(FieldVariant, v))
+}
+
+// UserProfileIDEQ applies the EQ predicate on the "user_profile_id" field.
+func UserProfileIDEQ(v int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEQ(FieldUserProfileID, v))
+}
+
+// UserProfileIDNEQ applies the NEQ predicate on the "user_profile_id" field.
+func UserProfileIDNEQ(v int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldNEQ(FieldUserProfileID, v))
+}
+
+// UserProfileIDIn applies the In predicate on the "user_profile_id" field.
+func UserProfileIDIn(vs ...int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldIn(FieldUserProfileID, vs...))
+}
+
+// UserProfileIDNotIn applies the NotIn predicate on the "user_profile_id" field.
+func UserProfileIDNotIn(vs ...int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldNotIn(FieldUserProfileID, vs...))
+}
+
+// TextureIDEQ applies the EQ predicate on the "texture_id" field.
+func TextureIDEQ(v int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEQ(FieldTextureID, v))
+}
+
+// TextureIDNEQ applies the NEQ predicate on the "texture_id" field.
+func TextureIDNEQ(v int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldNEQ(FieldTextureID, v))
+}
+
+// TextureIDIn applies the In predicate on the "texture_id" field.
+func TextureIDIn(vs ...int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldIn(FieldTextureID, vs...))
+}
+
+// TextureIDNotIn applies the NotIn predicate on the "texture_id" field.
+func TextureIDNotIn(vs ...int) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldNotIn(FieldTextureID, vs...))
+}
+
+// TypeEQ applies the EQ predicate on the "type" field.
+func TypeEQ(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEQ(FieldType, v))
+}
+
+// TypeNEQ applies the NEQ predicate on the "type" field.
+func TypeNEQ(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldNEQ(FieldType, v))
+}
+
+// TypeIn applies the In predicate on the "type" field.
+func TypeIn(vs ...string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldIn(FieldType, vs...))
+}
+
+// TypeNotIn applies the NotIn predicate on the "type" field.
+func TypeNotIn(vs ...string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldNotIn(FieldType, vs...))
+}
+
+// TypeGT applies the GT predicate on the "type" field.
+func TypeGT(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldGT(FieldType, v))
+}
+
+// TypeGTE applies the GTE predicate on the "type" field.
+func TypeGTE(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldGTE(FieldType, v))
+}
+
+// TypeLT applies the LT predicate on the "type" field.
+func TypeLT(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldLT(FieldType, v))
+}
+
+// TypeLTE applies the LTE predicate on the "type" field.
+func TypeLTE(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldLTE(FieldType, v))
+}
+
+// TypeContains applies the Contains predicate on the "type" field.
+func TypeContains(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldContains(FieldType, v))
+}
+
+// TypeHasPrefix applies the HasPrefix predicate on the "type" field.
+func TypeHasPrefix(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldHasPrefix(FieldType, v))
+}
+
+// TypeHasSuffix applies the HasSuffix predicate on the "type" field.
+func TypeHasSuffix(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldHasSuffix(FieldType, v))
+}
+
+// TypeEqualFold applies the EqualFold predicate on the "type" field.
+func TypeEqualFold(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEqualFold(FieldType, v))
+}
+
+// TypeContainsFold applies the ContainsFold predicate on the "type" field.
+func TypeContainsFold(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldContainsFold(FieldType, v))
+}
+
+// VariantEQ applies the EQ predicate on the "variant" field.
+func VariantEQ(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEQ(FieldVariant, v))
+}
+
+// VariantNEQ applies the NEQ predicate on the "variant" field.
+func VariantNEQ(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldNEQ(FieldVariant, v))
+}
+
+// VariantIn applies the In predicate on the "variant" field.
+func VariantIn(vs ...string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldIn(FieldVariant, vs...))
+}
+
+// VariantNotIn applies the NotIn predicate on the "variant" field.
+func VariantNotIn(vs ...string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldNotIn(FieldVariant, vs...))
+}
+
+// VariantGT applies the GT predicate on the "variant" field.
+func VariantGT(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldGT(FieldVariant, v))
+}
+
+// VariantGTE applies the GTE predicate on the "variant" field.
+func VariantGTE(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldGTE(FieldVariant, v))
+}
+
+// VariantLT applies the LT predicate on the "variant" field.
+func VariantLT(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldLT(FieldVariant, v))
+}
+
+// VariantLTE applies the LTE predicate on the "variant" field.
+func VariantLTE(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldLTE(FieldVariant, v))
+}
+
+// VariantContains applies the Contains predicate on the "variant" field.
+func VariantContains(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldContains(FieldVariant, v))
+}
+
+// VariantHasPrefix applies the HasPrefix predicate on the "variant" field.
+func VariantHasPrefix(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldHasPrefix(FieldVariant, v))
+}
+
+// VariantHasSuffix applies the HasSuffix predicate on the "variant" field.
+func VariantHasSuffix(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldHasSuffix(FieldVariant, v))
+}
+
+// VariantEqualFold applies the EqualFold predicate on the "variant" field.
+func VariantEqualFold(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldEqualFold(FieldVariant, v))
+}
+
+// VariantContainsFold applies the ContainsFold predicate on the "variant" field.
+func VariantContainsFold(v string) predicate.UserTexture {
+ return predicate.UserTexture(sql.FieldContainsFold(FieldVariant, v))
+}
+
+// HasUserProfile applies the HasEdge predicate on the "user_profile" edge.
+func HasUserProfile() predicate.UserTexture {
+ return predicate.UserTexture(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, UserProfileTable, UserProfileColumn),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasUserProfileWith applies the HasEdge predicate on the "user_profile" edge with a given conditions (other predicates).
+func HasUserProfileWith(preds ...predicate.UserProfile) predicate.UserTexture {
+ return predicate.UserTexture(func(s *sql.Selector) {
+ step := newUserProfileStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// HasTexture applies the HasEdge predicate on the "texture" edge.
+func HasTexture() predicate.UserTexture {
+ return predicate.UserTexture(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, TextureTable, TextureColumn),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasTextureWith applies the HasEdge predicate on the "texture" edge with a given conditions (other predicates).
+func HasTextureWith(preds ...predicate.Texture) predicate.UserTexture {
+ return predicate.UserTexture(func(s *sql.Selector) {
+ step := newTextureStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.UserTexture) predicate.UserTexture {
+ return predicate.UserTexture(func(s *sql.Selector) {
+ s1 := s.Clone().SetP(nil)
+ for _, p := range predicates {
+ p(s1)
+ }
+ s.Where(s1.P())
+ })
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.UserTexture) predicate.UserTexture {
+ return predicate.UserTexture(func(s *sql.Selector) {
+ s1 := s.Clone().SetP(nil)
+ for i, p := range predicates {
+ if i > 0 {
+ s1.Or()
+ }
+ p(s1)
+ }
+ s.Where(s1.P())
+ })
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.UserTexture) predicate.UserTexture {
+ return predicate.UserTexture(func(s *sql.Selector) {
+ p(s.Not())
+ })
+}
diff --git a/db/ent/usertexture_create.go b/db/ent/usertexture_create.go
new file mode 100644
index 0000000..accead8
--- /dev/null
+++ b/db/ent/usertexture_create.go
@@ -0,0 +1,262 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+)
+
+// UserTextureCreate is the builder for creating a UserTexture entity.
+type UserTextureCreate struct {
+ config
+ mutation *UserTextureMutation
+ hooks []Hook
+}
+
+// SetUserProfileID sets the "user_profile_id" field.
+func (utc *UserTextureCreate) SetUserProfileID(i int) *UserTextureCreate {
+ utc.mutation.SetUserProfileID(i)
+ return utc
+}
+
+// SetTextureID sets the "texture_id" field.
+func (utc *UserTextureCreate) SetTextureID(i int) *UserTextureCreate {
+ utc.mutation.SetTextureID(i)
+ return utc
+}
+
+// SetType sets the "type" field.
+func (utc *UserTextureCreate) SetType(s string) *UserTextureCreate {
+ utc.mutation.SetType(s)
+ return utc
+}
+
+// SetVariant sets the "variant" field.
+func (utc *UserTextureCreate) SetVariant(s string) *UserTextureCreate {
+ utc.mutation.SetVariant(s)
+ return utc
+}
+
+// SetUserProfile sets the "user_profile" edge to the UserProfile entity.
+func (utc *UserTextureCreate) SetUserProfile(u *UserProfile) *UserTextureCreate {
+ return utc.SetUserProfileID(u.ID)
+}
+
+// SetTexture sets the "texture" edge to the Texture entity.
+func (utc *UserTextureCreate) SetTexture(t *Texture) *UserTextureCreate {
+ return utc.SetTextureID(t.ID)
+}
+
+// Mutation returns the UserTextureMutation object of the builder.
+func (utc *UserTextureCreate) Mutation() *UserTextureMutation {
+ return utc.mutation
+}
+
+// Save creates the UserTexture in the database.
+func (utc *UserTextureCreate) Save(ctx context.Context) (*UserTexture, error) {
+ return withHooks(ctx, utc.sqlSave, utc.mutation, utc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (utc *UserTextureCreate) SaveX(ctx context.Context) *UserTexture {
+ v, err := utc.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Exec executes the query.
+func (utc *UserTextureCreate) Exec(ctx context.Context) error {
+ _, err := utc.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utc *UserTextureCreate) ExecX(ctx context.Context) {
+ if err := utc.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (utc *UserTextureCreate) check() error {
+ if _, ok := utc.mutation.UserProfileID(); !ok {
+ return &ValidationError{Name: "user_profile_id", err: errors.New(`ent: missing required field "UserTexture.user_profile_id"`)}
+ }
+ if _, ok := utc.mutation.TextureID(); !ok {
+ return &ValidationError{Name: "texture_id", err: errors.New(`ent: missing required field "UserTexture.texture_id"`)}
+ }
+ if _, ok := utc.mutation.GetType(); !ok {
+ return &ValidationError{Name: "type", err: errors.New(`ent: missing required field "UserTexture.type"`)}
+ }
+ if _, ok := utc.mutation.Variant(); !ok {
+ return &ValidationError{Name: "variant", err: errors.New(`ent: missing required field "UserTexture.variant"`)}
+ }
+ if _, ok := utc.mutation.UserProfileID(); !ok {
+ return &ValidationError{Name: "user_profile", err: errors.New(`ent: missing required edge "UserTexture.user_profile"`)}
+ }
+ if _, ok := utc.mutation.TextureID(); !ok {
+ return &ValidationError{Name: "texture", err: errors.New(`ent: missing required edge "UserTexture.texture"`)}
+ }
+ return nil
+}
+
+func (utc *UserTextureCreate) sqlSave(ctx context.Context) (*UserTexture, error) {
+ if err := utc.check(); err != nil {
+ return nil, err
+ }
+ _node, _spec := utc.createSpec()
+ if err := sqlgraph.CreateNode(ctx, utc.driver, _spec); err != nil {
+ if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return nil, err
+ }
+ id := _spec.ID.Value.(int64)
+ _node.ID = int(id)
+ utc.mutation.id = &_node.ID
+ utc.mutation.done = true
+ return _node, nil
+}
+
+func (utc *UserTextureCreate) createSpec() (*UserTexture, *sqlgraph.CreateSpec) {
+ var (
+ _node = &UserTexture{config: utc.config}
+ _spec = sqlgraph.NewCreateSpec(usertexture.Table, sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt))
+ )
+ if value, ok := utc.mutation.GetType(); ok {
+ _spec.SetField(usertexture.FieldType, field.TypeString, value)
+ _node.Type = value
+ }
+ if value, ok := utc.mutation.Variant(); ok {
+ _spec.SetField(usertexture.FieldVariant, field.TypeString, value)
+ _node.Variant = value
+ }
+ if nodes := utc.mutation.UserProfileIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: usertexture.UserProfileTable,
+ Columns: []string{usertexture.UserProfileColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _node.UserProfileID = nodes[0]
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ if nodes := utc.mutation.TextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: usertexture.TextureTable,
+ Columns: []string{usertexture.TextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _node.TextureID = nodes[0]
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ return _node, _spec
+}
+
+// UserTextureCreateBulk is the builder for creating many UserTexture entities in bulk.
+type UserTextureCreateBulk struct {
+ config
+ builders []*UserTextureCreate
+}
+
+// Save creates the UserTexture entities in the database.
+func (utcb *UserTextureCreateBulk) Save(ctx context.Context) ([]*UserTexture, error) {
+ specs := make([]*sqlgraph.CreateSpec, len(utcb.builders))
+ nodes := make([]*UserTexture, len(utcb.builders))
+ mutators := make([]Mutator, len(utcb.builders))
+ for i := range utcb.builders {
+ func(i int, root context.Context) {
+ builder := utcb.builders[i]
+ var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+ mutation, ok := m.(*UserTextureMutation)
+ if !ok {
+ return nil, fmt.Errorf("unexpected mutation type %T", m)
+ }
+ if err := builder.check(); err != nil {
+ return nil, err
+ }
+ builder.mutation = mutation
+ var err error
+ nodes[i], specs[i] = builder.createSpec()
+ if i < len(mutators)-1 {
+ _, err = mutators[i+1].Mutate(root, utcb.builders[i+1].mutation)
+ } else {
+ spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+ // Invoke the actual operation on the latest mutation in the chain.
+ if err = sqlgraph.BatchCreate(ctx, utcb.driver, spec); err != nil {
+ if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ mutation.id = &nodes[i].ID
+ if specs[i].ID.Value != nil {
+ id := specs[i].ID.Value.(int64)
+ nodes[i].ID = int(id)
+ }
+ mutation.done = true
+ return nodes[i], nil
+ })
+ for i := len(builder.hooks) - 1; i >= 0; i-- {
+ mut = builder.hooks[i](mut)
+ }
+ mutators[i] = mut
+ }(i, ctx)
+ }
+ if len(mutators) > 0 {
+ if _, err := mutators[0].Mutate(ctx, utcb.builders[0].mutation); err != nil {
+ return nil, err
+ }
+ }
+ return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (utcb *UserTextureCreateBulk) SaveX(ctx context.Context) []*UserTexture {
+ v, err := utcb.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Exec executes the query.
+func (utcb *UserTextureCreateBulk) Exec(ctx context.Context) error {
+ _, err := utcb.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utcb *UserTextureCreateBulk) ExecX(ctx context.Context) {
+ if err := utcb.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
diff --git a/db/ent/usertexture_delete.go b/db/ent/usertexture_delete.go
new file mode 100644
index 0000000..62b7bb0
--- /dev/null
+++ b/db/ent/usertexture_delete.go
@@ -0,0 +1,88 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+)
+
+// UserTextureDelete is the builder for deleting a UserTexture entity.
+type UserTextureDelete struct {
+ config
+ hooks []Hook
+ mutation *UserTextureMutation
+}
+
+// Where appends a list predicates to the UserTextureDelete builder.
+func (utd *UserTextureDelete) Where(ps ...predicate.UserTexture) *UserTextureDelete {
+ utd.mutation.Where(ps...)
+ return utd
+}
+
+// Exec executes the deletion query and returns how many vertices were deleted.
+func (utd *UserTextureDelete) Exec(ctx context.Context) (int, error) {
+ return withHooks(ctx, utd.sqlExec, utd.mutation, utd.hooks)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utd *UserTextureDelete) ExecX(ctx context.Context) int {
+ n, err := utd.Exec(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return n
+}
+
+func (utd *UserTextureDelete) sqlExec(ctx context.Context) (int, error) {
+ _spec := sqlgraph.NewDeleteSpec(usertexture.Table, sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt))
+ if ps := utd.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ affected, err := sqlgraph.DeleteNodes(ctx, utd.driver, _spec)
+ if err != nil && sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ utd.mutation.done = true
+ return affected, err
+}
+
+// UserTextureDeleteOne is the builder for deleting a single UserTexture entity.
+type UserTextureDeleteOne struct {
+ utd *UserTextureDelete
+}
+
+// Where appends a list predicates to the UserTextureDelete builder.
+func (utdo *UserTextureDeleteOne) Where(ps ...predicate.UserTexture) *UserTextureDeleteOne {
+ utdo.utd.mutation.Where(ps...)
+ return utdo
+}
+
+// Exec executes the deletion query.
+func (utdo *UserTextureDeleteOne) Exec(ctx context.Context) error {
+ n, err := utdo.utd.Exec(ctx)
+ switch {
+ case err != nil:
+ return err
+ case n == 0:
+ return &NotFoundError{usertexture.Label}
+ default:
+ return nil
+ }
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utdo *UserTextureDeleteOne) ExecX(ctx context.Context) {
+ if err := utdo.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
diff --git a/db/ent/usertexture_query.go b/db/ent/usertexture_query.go
new file mode 100644
index 0000000..4ce98f9
--- /dev/null
+++ b/db/ent/usertexture_query.go
@@ -0,0 +1,737 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "fmt"
+ "math"
+
+ "entgo.io/ent/dialect"
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+)
+
+// UserTextureQuery is the builder for querying UserTexture entities.
+type UserTextureQuery struct {
+ config
+ ctx *QueryContext
+ order []usertexture.OrderOption
+ inters []Interceptor
+ predicates []predicate.UserTexture
+ withUserProfile *UserProfileQuery
+ withTexture *TextureQuery
+ modifiers []func(*sql.Selector)
+ // intermediate query (i.e. traversal path).
+ sql *sql.Selector
+ path func(context.Context) (*sql.Selector, error)
+}
+
+// Where adds a new predicate for the UserTextureQuery builder.
+func (utq *UserTextureQuery) Where(ps ...predicate.UserTexture) *UserTextureQuery {
+ utq.predicates = append(utq.predicates, ps...)
+ return utq
+}
+
+// Limit the number of records to be returned by this query.
+func (utq *UserTextureQuery) Limit(limit int) *UserTextureQuery {
+ utq.ctx.Limit = &limit
+ return utq
+}
+
+// Offset to start from.
+func (utq *UserTextureQuery) Offset(offset int) *UserTextureQuery {
+ utq.ctx.Offset = &offset
+ return utq
+}
+
+// Unique configures the query builder to filter duplicate records on query.
+// By default, unique is set to true, and can be disabled using this method.
+func (utq *UserTextureQuery) Unique(unique bool) *UserTextureQuery {
+ utq.ctx.Unique = &unique
+ return utq
+}
+
+// Order specifies how the records should be ordered.
+func (utq *UserTextureQuery) Order(o ...usertexture.OrderOption) *UserTextureQuery {
+ utq.order = append(utq.order, o...)
+ return utq
+}
+
+// QueryUserProfile chains the current query on the "user_profile" edge.
+func (utq *UserTextureQuery) QueryUserProfile() *UserProfileQuery {
+ query := (&UserProfileClient{config: utq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := utq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := utq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(usertexture.Table, usertexture.FieldID, selector),
+ sqlgraph.To(userprofile.Table, userprofile.FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, usertexture.UserProfileTable, usertexture.UserProfileColumn),
+ )
+ fromU = sqlgraph.SetNeighbors(utq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// QueryTexture chains the current query on the "texture" edge.
+func (utq *UserTextureQuery) QueryTexture() *TextureQuery {
+ query := (&TextureClient{config: utq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := utq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := utq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(usertexture.Table, usertexture.FieldID, selector),
+ sqlgraph.To(texture.Table, texture.FieldID),
+ sqlgraph.Edge(sqlgraph.M2O, false, usertexture.TextureTable, usertexture.TextureColumn),
+ )
+ fromU = sqlgraph.SetNeighbors(utq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// First returns the first UserTexture entity from the query.
+// Returns a *NotFoundError when no UserTexture was found.
+func (utq *UserTextureQuery) First(ctx context.Context) (*UserTexture, error) {
+ nodes, err := utq.Limit(1).All(setContextOp(ctx, utq.ctx, "First"))
+ if err != nil {
+ return nil, err
+ }
+ if len(nodes) == 0 {
+ return nil, &NotFoundError{usertexture.Label}
+ }
+ return nodes[0], nil
+}
+
+// FirstX is like First, but panics if an error occurs.
+func (utq *UserTextureQuery) FirstX(ctx context.Context) *UserTexture {
+ node, err := utq.First(ctx)
+ if err != nil && !IsNotFound(err) {
+ panic(err)
+ }
+ return node
+}
+
+// FirstID returns the first UserTexture ID from the query.
+// Returns a *NotFoundError when no UserTexture ID was found.
+func (utq *UserTextureQuery) FirstID(ctx context.Context) (id int, err error) {
+ var ids []int
+ if ids, err = utq.Limit(1).IDs(setContextOp(ctx, utq.ctx, "FirstID")); err != nil {
+ return
+ }
+ if len(ids) == 0 {
+ err = &NotFoundError{usertexture.Label}
+ return
+ }
+ return ids[0], nil
+}
+
+// FirstIDX is like FirstID, but panics if an error occurs.
+func (utq *UserTextureQuery) FirstIDX(ctx context.Context) int {
+ id, err := utq.FirstID(ctx)
+ if err != nil && !IsNotFound(err) {
+ panic(err)
+ }
+ return id
+}
+
+// Only returns a single UserTexture entity found by the query, ensuring it only returns one.
+// Returns a *NotSingularError when more than one UserTexture entity is found.
+// Returns a *NotFoundError when no UserTexture entities are found.
+func (utq *UserTextureQuery) Only(ctx context.Context) (*UserTexture, error) {
+ nodes, err := utq.Limit(2).All(setContextOp(ctx, utq.ctx, "Only"))
+ if err != nil {
+ return nil, err
+ }
+ switch len(nodes) {
+ case 1:
+ return nodes[0], nil
+ case 0:
+ return nil, &NotFoundError{usertexture.Label}
+ default:
+ return nil, &NotSingularError{usertexture.Label}
+ }
+}
+
+// OnlyX is like Only, but panics if an error occurs.
+func (utq *UserTextureQuery) OnlyX(ctx context.Context) *UserTexture {
+ node, err := utq.Only(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return node
+}
+
+// OnlyID is like Only, but returns the only UserTexture ID in the query.
+// Returns a *NotSingularError when more than one UserTexture ID is found.
+// Returns a *NotFoundError when no entities are found.
+func (utq *UserTextureQuery) OnlyID(ctx context.Context) (id int, err error) {
+ var ids []int
+ if ids, err = utq.Limit(2).IDs(setContextOp(ctx, utq.ctx, "OnlyID")); err != nil {
+ return
+ }
+ switch len(ids) {
+ case 1:
+ id = ids[0]
+ case 0:
+ err = &NotFoundError{usertexture.Label}
+ default:
+ err = &NotSingularError{usertexture.Label}
+ }
+ return
+}
+
+// OnlyIDX is like OnlyID, but panics if an error occurs.
+func (utq *UserTextureQuery) OnlyIDX(ctx context.Context) int {
+ id, err := utq.OnlyID(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
+// All executes the query and returns a list of UserTextures.
+func (utq *UserTextureQuery) All(ctx context.Context) ([]*UserTexture, error) {
+ ctx = setContextOp(ctx, utq.ctx, "All")
+ if err := utq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ qr := querierAll[[]*UserTexture, *UserTextureQuery]()
+ return withInterceptors[[]*UserTexture](ctx, utq, qr, utq.inters)
+}
+
+// AllX is like All, but panics if an error occurs.
+func (utq *UserTextureQuery) AllX(ctx context.Context) []*UserTexture {
+ nodes, err := utq.All(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return nodes
+}
+
+// IDs executes the query and returns a list of UserTexture IDs.
+func (utq *UserTextureQuery) IDs(ctx context.Context) (ids []int, err error) {
+ if utq.ctx.Unique == nil && utq.path != nil {
+ utq.Unique(true)
+ }
+ ctx = setContextOp(ctx, utq.ctx, "IDs")
+ if err = utq.Select(usertexture.FieldID).Scan(ctx, &ids); err != nil {
+ return nil, err
+ }
+ return ids, nil
+}
+
+// IDsX is like IDs, but panics if an error occurs.
+func (utq *UserTextureQuery) IDsX(ctx context.Context) []int {
+ ids, err := utq.IDs(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return ids
+}
+
+// Count returns the count of the given query.
+func (utq *UserTextureQuery) Count(ctx context.Context) (int, error) {
+ ctx = setContextOp(ctx, utq.ctx, "Count")
+ if err := utq.prepareQuery(ctx); err != nil {
+ return 0, err
+ }
+ return withInterceptors[int](ctx, utq, querierCount[*UserTextureQuery](), utq.inters)
+}
+
+// CountX is like Count, but panics if an error occurs.
+func (utq *UserTextureQuery) CountX(ctx context.Context) int {
+ count, err := utq.Count(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return count
+}
+
+// Exist returns true if the query has elements in the graph.
+func (utq *UserTextureQuery) Exist(ctx context.Context) (bool, error) {
+ ctx = setContextOp(ctx, utq.ctx, "Exist")
+ switch _, err := utq.FirstID(ctx); {
+ case IsNotFound(err):
+ return false, nil
+ case err != nil:
+ return false, fmt.Errorf("ent: check existence: %w", err)
+ default:
+ return true, nil
+ }
+}
+
+// ExistX is like Exist, but panics if an error occurs.
+func (utq *UserTextureQuery) ExistX(ctx context.Context) bool {
+ exist, err := utq.Exist(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return exist
+}
+
+// Clone returns a duplicate of the UserTextureQuery builder, including all associated steps. It can be
+// used to prepare common query builders and use them differently after the clone is made.
+func (utq *UserTextureQuery) Clone() *UserTextureQuery {
+ if utq == nil {
+ return nil
+ }
+ return &UserTextureQuery{
+ config: utq.config,
+ ctx: utq.ctx.Clone(),
+ order: append([]usertexture.OrderOption{}, utq.order...),
+ inters: append([]Interceptor{}, utq.inters...),
+ predicates: append([]predicate.UserTexture{}, utq.predicates...),
+ withUserProfile: utq.withUserProfile.Clone(),
+ withTexture: utq.withTexture.Clone(),
+ // clone intermediate query.
+ sql: utq.sql.Clone(),
+ path: utq.path,
+ }
+}
+
+// WithUserProfile tells the query-builder to eager-load the nodes that are connected to
+// the "user_profile" edge. The optional arguments are used to configure the query builder of the edge.
+func (utq *UserTextureQuery) WithUserProfile(opts ...func(*UserProfileQuery)) *UserTextureQuery {
+ query := (&UserProfileClient{config: utq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ utq.withUserProfile = query
+ return utq
+}
+
+// WithTexture tells the query-builder to eager-load the nodes that are connected to
+// the "texture" edge. The optional arguments are used to configure the query builder of the edge.
+func (utq *UserTextureQuery) WithTexture(opts ...func(*TextureQuery)) *UserTextureQuery {
+ query := (&TextureClient{config: utq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ utq.withTexture = query
+ return utq
+}
+
+// GroupBy is used to group vertices by one or more fields/columns.
+// It is often used with aggregate functions, like: count, max, mean, min, sum.
+//
+// Example:
+//
+// var v []struct {
+// UserProfileID int `json:"user_profile_id,omitempty"`
+// Count int `json:"count,omitempty"`
+// }
+//
+// client.UserTexture.Query().
+// GroupBy(usertexture.FieldUserProfileID).
+// Aggregate(ent.Count()).
+// Scan(ctx, &v)
+func (utq *UserTextureQuery) GroupBy(field string, fields ...string) *UserTextureGroupBy {
+ utq.ctx.Fields = append([]string{field}, fields...)
+ grbuild := &UserTextureGroupBy{build: utq}
+ grbuild.flds = &utq.ctx.Fields
+ grbuild.label = usertexture.Label
+ grbuild.scan = grbuild.Scan
+ return grbuild
+}
+
+// Select allows the selection one or more fields/columns for the given query,
+// instead of selecting all fields in the entity.
+//
+// Example:
+//
+// var v []struct {
+// UserProfileID int `json:"user_profile_id,omitempty"`
+// }
+//
+// client.UserTexture.Query().
+// Select(usertexture.FieldUserProfileID).
+// Scan(ctx, &v)
+func (utq *UserTextureQuery) Select(fields ...string) *UserTextureSelect {
+ utq.ctx.Fields = append(utq.ctx.Fields, fields...)
+ sbuild := &UserTextureSelect{UserTextureQuery: utq}
+ sbuild.label = usertexture.Label
+ sbuild.flds, sbuild.scan = &utq.ctx.Fields, sbuild.Scan
+ return sbuild
+}
+
+// Aggregate returns a UserTextureSelect configured with the given aggregations.
+func (utq *UserTextureQuery) Aggregate(fns ...AggregateFunc) *UserTextureSelect {
+ return utq.Select().Aggregate(fns...)
+}
+
+func (utq *UserTextureQuery) prepareQuery(ctx context.Context) error {
+ for _, inter := range utq.inters {
+ if inter == nil {
+ return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
+ }
+ if trv, ok := inter.(Traverser); ok {
+ if err := trv.Traverse(ctx, utq); err != nil {
+ return err
+ }
+ }
+ }
+ for _, f := range utq.ctx.Fields {
+ if !usertexture.ValidColumn(f) {
+ return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+ }
+ }
+ if utq.path != nil {
+ prev, err := utq.path(ctx)
+ if err != nil {
+ return err
+ }
+ utq.sql = prev
+ }
+ return nil
+}
+
+func (utq *UserTextureQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*UserTexture, error) {
+ var (
+ nodes = []*UserTexture{}
+ _spec = utq.querySpec()
+ loadedTypes = [2]bool{
+ utq.withUserProfile != nil,
+ utq.withTexture != nil,
+ }
+ )
+ _spec.ScanValues = func(columns []string) ([]any, error) {
+ return (*UserTexture).scanValues(nil, columns)
+ }
+ _spec.Assign = func(columns []string, values []any) error {
+ node := &UserTexture{config: utq.config}
+ nodes = append(nodes, node)
+ node.Edges.loadedTypes = loadedTypes
+ return node.assignValues(columns, values)
+ }
+ if len(utq.modifiers) > 0 {
+ _spec.Modifiers = utq.modifiers
+ }
+ for i := range hooks {
+ hooks[i](ctx, _spec)
+ }
+ if err := sqlgraph.QueryNodes(ctx, utq.driver, _spec); err != nil {
+ return nil, err
+ }
+ if len(nodes) == 0 {
+ return nodes, nil
+ }
+ if query := utq.withUserProfile; query != nil {
+ if err := utq.loadUserProfile(ctx, query, nodes, nil,
+ func(n *UserTexture, e *UserProfile) { n.Edges.UserProfile = e }); err != nil {
+ return nil, err
+ }
+ }
+ if query := utq.withTexture; query != nil {
+ if err := utq.loadTexture(ctx, query, nodes, nil,
+ func(n *UserTexture, e *Texture) { n.Edges.Texture = e }); err != nil {
+ return nil, err
+ }
+ }
+ return nodes, nil
+}
+
+func (utq *UserTextureQuery) loadUserProfile(ctx context.Context, query *UserProfileQuery, nodes []*UserTexture, init func(*UserTexture), assign func(*UserTexture, *UserProfile)) error {
+ ids := make([]int, 0, len(nodes))
+ nodeids := make(map[int][]*UserTexture)
+ for i := range nodes {
+ fk := nodes[i].UserProfileID
+ if _, ok := nodeids[fk]; !ok {
+ ids = append(ids, fk)
+ }
+ nodeids[fk] = append(nodeids[fk], nodes[i])
+ }
+ if len(ids) == 0 {
+ return nil
+ }
+ query.Where(userprofile.IDIn(ids...))
+ neighbors, err := query.All(ctx)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ nodes, ok := nodeids[n.ID]
+ if !ok {
+ return fmt.Errorf(`unexpected foreign-key "user_profile_id" returned %v`, n.ID)
+ }
+ for i := range nodes {
+ assign(nodes[i], n)
+ }
+ }
+ return nil
+}
+func (utq *UserTextureQuery) loadTexture(ctx context.Context, query *TextureQuery, nodes []*UserTexture, init func(*UserTexture), assign func(*UserTexture, *Texture)) error {
+ ids := make([]int, 0, len(nodes))
+ nodeids := make(map[int][]*UserTexture)
+ for i := range nodes {
+ fk := nodes[i].TextureID
+ if _, ok := nodeids[fk]; !ok {
+ ids = append(ids, fk)
+ }
+ nodeids[fk] = append(nodeids[fk], nodes[i])
+ }
+ if len(ids) == 0 {
+ return nil
+ }
+ query.Where(texture.IDIn(ids...))
+ neighbors, err := query.All(ctx)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ nodes, ok := nodeids[n.ID]
+ if !ok {
+ return fmt.Errorf(`unexpected foreign-key "texture_id" returned %v`, n.ID)
+ }
+ for i := range nodes {
+ assign(nodes[i], n)
+ }
+ }
+ return nil
+}
+
+func (utq *UserTextureQuery) sqlCount(ctx context.Context) (int, error) {
+ _spec := utq.querySpec()
+ if len(utq.modifiers) > 0 {
+ _spec.Modifiers = utq.modifiers
+ }
+ _spec.Node.Columns = utq.ctx.Fields
+ if len(utq.ctx.Fields) > 0 {
+ _spec.Unique = utq.ctx.Unique != nil && *utq.ctx.Unique
+ }
+ return sqlgraph.CountNodes(ctx, utq.driver, _spec)
+}
+
+func (utq *UserTextureQuery) querySpec() *sqlgraph.QuerySpec {
+ _spec := sqlgraph.NewQuerySpec(usertexture.Table, usertexture.Columns, sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt))
+ _spec.From = utq.sql
+ if unique := utq.ctx.Unique; unique != nil {
+ _spec.Unique = *unique
+ } else if utq.path != nil {
+ _spec.Unique = true
+ }
+ if fields := utq.ctx.Fields; len(fields) > 0 {
+ _spec.Node.Columns = make([]string, 0, len(fields))
+ _spec.Node.Columns = append(_spec.Node.Columns, usertexture.FieldID)
+ for i := range fields {
+ if fields[i] != usertexture.FieldID {
+ _spec.Node.Columns = append(_spec.Node.Columns, fields[i])
+ }
+ }
+ if utq.withUserProfile != nil {
+ _spec.Node.AddColumnOnce(usertexture.FieldUserProfileID)
+ }
+ if utq.withTexture != nil {
+ _spec.Node.AddColumnOnce(usertexture.FieldTextureID)
+ }
+ }
+ if ps := utq.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if limit := utq.ctx.Limit; limit != nil {
+ _spec.Limit = *limit
+ }
+ if offset := utq.ctx.Offset; offset != nil {
+ _spec.Offset = *offset
+ }
+ if ps := utq.order; len(ps) > 0 {
+ _spec.Order = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ return _spec
+}
+
+func (utq *UserTextureQuery) sqlQuery(ctx context.Context) *sql.Selector {
+ builder := sql.Dialect(utq.driver.Dialect())
+ t1 := builder.Table(usertexture.Table)
+ columns := utq.ctx.Fields
+ if len(columns) == 0 {
+ columns = usertexture.Columns
+ }
+ selector := builder.Select(t1.Columns(columns...)...).From(t1)
+ if utq.sql != nil {
+ selector = utq.sql
+ selector.Select(selector.Columns(columns...)...)
+ }
+ if utq.ctx.Unique != nil && *utq.ctx.Unique {
+ selector.Distinct()
+ }
+ for _, m := range utq.modifiers {
+ m(selector)
+ }
+ for _, p := range utq.predicates {
+ p(selector)
+ }
+ for _, p := range utq.order {
+ p(selector)
+ }
+ if offset := utq.ctx.Offset; offset != nil {
+ // limit is mandatory for offset clause. We start
+ // with default value, and override it below if needed.
+ selector.Offset(*offset).Limit(math.MaxInt32)
+ }
+ if limit := utq.ctx.Limit; limit != nil {
+ selector.Limit(*limit)
+ }
+ return selector
+}
+
+// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
+// updated, deleted or "selected ... for update" by other sessions, until the transaction is
+// either committed or rolled-back.
+func (utq *UserTextureQuery) ForUpdate(opts ...sql.LockOption) *UserTextureQuery {
+ if utq.driver.Dialect() == dialect.Postgres {
+ utq.Unique(false)
+ }
+ utq.modifiers = append(utq.modifiers, func(s *sql.Selector) {
+ s.ForUpdate(opts...)
+ })
+ return utq
+}
+
+// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
+// on any rows that are read. Other sessions can read the rows, but cannot modify them
+// until your transaction commits.
+func (utq *UserTextureQuery) ForShare(opts ...sql.LockOption) *UserTextureQuery {
+ if utq.driver.Dialect() == dialect.Postgres {
+ utq.Unique(false)
+ }
+ utq.modifiers = append(utq.modifiers, func(s *sql.Selector) {
+ s.ForShare(opts...)
+ })
+ return utq
+}
+
+// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
+// updated, deleted or "selected ... for update" by other sessions, until the transaction is
+// either committed or rolled-back.
+func (utq *UserTextureQuery) ForUpdateA(opts ...sql.LockOption) *UserTextureQuery {
+ if utq.driver.Dialect() == dialect.SQLite {
+ return utq
+ }
+ return utq.ForUpdate(opts...)
+}
+
+// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
+// on any rows that are read. Other sessions can read the rows, but cannot modify them
+// until your transaction commits.
+func (utq *UserTextureQuery) ForShareA(opts ...sql.LockOption) *UserTextureQuery {
+ if utq.driver.Dialect() == dialect.SQLite {
+ return utq
+ }
+ return utq.ForShare(opts...)
+}
+
+// UserTextureGroupBy is the group-by builder for UserTexture entities.
+type UserTextureGroupBy struct {
+ selector
+ build *UserTextureQuery
+}
+
+// Aggregate adds the given aggregation functions to the group-by query.
+func (utgb *UserTextureGroupBy) Aggregate(fns ...AggregateFunc) *UserTextureGroupBy {
+ utgb.fns = append(utgb.fns, fns...)
+ return utgb
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (utgb *UserTextureGroupBy) Scan(ctx context.Context, v any) error {
+ ctx = setContextOp(ctx, utgb.build.ctx, "GroupBy")
+ if err := utgb.build.prepareQuery(ctx); err != nil {
+ return err
+ }
+ return scanWithInterceptors[*UserTextureQuery, *UserTextureGroupBy](ctx, utgb.build, utgb, utgb.build.inters, v)
+}
+
+func (utgb *UserTextureGroupBy) sqlScan(ctx context.Context, root *UserTextureQuery, v any) error {
+ selector := root.sqlQuery(ctx).Select()
+ aggregation := make([]string, 0, len(utgb.fns))
+ for _, fn := range utgb.fns {
+ aggregation = append(aggregation, fn(selector))
+ }
+ if len(selector.SelectedColumns()) == 0 {
+ columns := make([]string, 0, len(*utgb.flds)+len(utgb.fns))
+ for _, f := range *utgb.flds {
+ columns = append(columns, selector.C(f))
+ }
+ columns = append(columns, aggregation...)
+ selector.Select(columns...)
+ }
+ selector.GroupBy(selector.Columns(*utgb.flds...)...)
+ if err := selector.Err(); err != nil {
+ return err
+ }
+ rows := &sql.Rows{}
+ query, args := selector.Query()
+ if err := utgb.build.driver.Query(ctx, query, args, rows); err != nil {
+ return err
+ }
+ defer rows.Close()
+ return sql.ScanSlice(rows, v)
+}
+
+// UserTextureSelect is the builder for selecting fields of UserTexture entities.
+type UserTextureSelect struct {
+ *UserTextureQuery
+ selector
+}
+
+// Aggregate adds the given aggregation functions to the selector query.
+func (uts *UserTextureSelect) Aggregate(fns ...AggregateFunc) *UserTextureSelect {
+ uts.fns = append(uts.fns, fns...)
+ return uts
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (uts *UserTextureSelect) Scan(ctx context.Context, v any) error {
+ ctx = setContextOp(ctx, uts.ctx, "Select")
+ if err := uts.prepareQuery(ctx); err != nil {
+ return err
+ }
+ return scanWithInterceptors[*UserTextureQuery, *UserTextureSelect](ctx, uts.UserTextureQuery, uts, uts.inters, v)
+}
+
+func (uts *UserTextureSelect) sqlScan(ctx context.Context, root *UserTextureQuery, v any) error {
+ selector := root.sqlQuery(ctx)
+ aggregation := make([]string, 0, len(uts.fns))
+ for _, fn := range uts.fns {
+ aggregation = append(aggregation, fn(selector))
+ }
+ switch n := len(*uts.selector.flds); {
+ case n == 0 && len(aggregation) > 0:
+ selector.Select(aggregation...)
+ case n != 0 && len(aggregation) > 0:
+ selector.AppendSelect(aggregation...)
+ }
+ rows := &sql.Rows{}
+ query, args := selector.Query()
+ if err := uts.driver.Query(ctx, query, args, rows); err != nil {
+ return err
+ }
+ defer rows.Close()
+ return sql.ScanSlice(rows, v)
+}
diff --git a/db/ent/usertexture_update.go b/db/ent/usertexture_update.go
new file mode 100644
index 0000000..5d6c474
--- /dev/null
+++ b/db/ent/usertexture_update.go
@@ -0,0 +1,425 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/texture"
+ "github.com/xmdhs/authlib-skin/db/ent/userprofile"
+ "github.com/xmdhs/authlib-skin/db/ent/usertexture"
+)
+
+// UserTextureUpdate is the builder for updating UserTexture entities.
+type UserTextureUpdate struct {
+ config
+ hooks []Hook
+ mutation *UserTextureMutation
+}
+
+// Where appends a list predicates to the UserTextureUpdate builder.
+func (utu *UserTextureUpdate) Where(ps ...predicate.UserTexture) *UserTextureUpdate {
+ utu.mutation.Where(ps...)
+ return utu
+}
+
+// SetUserProfileID sets the "user_profile_id" field.
+func (utu *UserTextureUpdate) SetUserProfileID(i int) *UserTextureUpdate {
+ utu.mutation.SetUserProfileID(i)
+ return utu
+}
+
+// SetTextureID sets the "texture_id" field.
+func (utu *UserTextureUpdate) SetTextureID(i int) *UserTextureUpdate {
+ utu.mutation.SetTextureID(i)
+ return utu
+}
+
+// SetType sets the "type" field.
+func (utu *UserTextureUpdate) SetType(s string) *UserTextureUpdate {
+ utu.mutation.SetType(s)
+ return utu
+}
+
+// SetVariant sets the "variant" field.
+func (utu *UserTextureUpdate) SetVariant(s string) *UserTextureUpdate {
+ utu.mutation.SetVariant(s)
+ return utu
+}
+
+// SetUserProfile sets the "user_profile" edge to the UserProfile entity.
+func (utu *UserTextureUpdate) SetUserProfile(u *UserProfile) *UserTextureUpdate {
+ return utu.SetUserProfileID(u.ID)
+}
+
+// SetTexture sets the "texture" edge to the Texture entity.
+func (utu *UserTextureUpdate) SetTexture(t *Texture) *UserTextureUpdate {
+ return utu.SetTextureID(t.ID)
+}
+
+// Mutation returns the UserTextureMutation object of the builder.
+func (utu *UserTextureUpdate) Mutation() *UserTextureMutation {
+ return utu.mutation
+}
+
+// ClearUserProfile clears the "user_profile" edge to the UserProfile entity.
+func (utu *UserTextureUpdate) ClearUserProfile() *UserTextureUpdate {
+ utu.mutation.ClearUserProfile()
+ return utu
+}
+
+// ClearTexture clears the "texture" edge to the Texture entity.
+func (utu *UserTextureUpdate) ClearTexture() *UserTextureUpdate {
+ utu.mutation.ClearTexture()
+ return utu
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (utu *UserTextureUpdate) Save(ctx context.Context) (int, error) {
+ return withHooks(ctx, utu.sqlSave, utu.mutation, utu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (utu *UserTextureUpdate) SaveX(ctx context.Context) int {
+ affected, err := utu.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return affected
+}
+
+// Exec executes the query.
+func (utu *UserTextureUpdate) Exec(ctx context.Context) error {
+ _, err := utu.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utu *UserTextureUpdate) ExecX(ctx context.Context) {
+ if err := utu.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (utu *UserTextureUpdate) check() error {
+ if _, ok := utu.mutation.UserProfileID(); utu.mutation.UserProfileCleared() && !ok {
+ return errors.New(`ent: clearing a required unique edge "UserTexture.user_profile"`)
+ }
+ if _, ok := utu.mutation.TextureID(); utu.mutation.TextureCleared() && !ok {
+ return errors.New(`ent: clearing a required unique edge "UserTexture.texture"`)
+ }
+ return nil
+}
+
+func (utu *UserTextureUpdate) sqlSave(ctx context.Context) (n int, err error) {
+ if err := utu.check(); err != nil {
+ return n, err
+ }
+ _spec := sqlgraph.NewUpdateSpec(usertexture.Table, usertexture.Columns, sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt))
+ if ps := utu.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if value, ok := utu.mutation.GetType(); ok {
+ _spec.SetField(usertexture.FieldType, field.TypeString, value)
+ }
+ if value, ok := utu.mutation.Variant(); ok {
+ _spec.SetField(usertexture.FieldVariant, field.TypeString, value)
+ }
+ if utu.mutation.UserProfileCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: usertexture.UserProfileTable,
+ Columns: []string{usertexture.UserProfileColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := utu.mutation.UserProfileIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: usertexture.UserProfileTable,
+ Columns: []string{usertexture.UserProfileColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if utu.mutation.TextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: usertexture.TextureTable,
+ Columns: []string{usertexture.TextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := utu.mutation.TextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: usertexture.TextureTable,
+ Columns: []string{usertexture.TextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if n, err = sqlgraph.UpdateNodes(ctx, utu.driver, _spec); err != nil {
+ if _, ok := err.(*sqlgraph.NotFoundError); ok {
+ err = &NotFoundError{usertexture.Label}
+ } else if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return 0, err
+ }
+ utu.mutation.done = true
+ return n, nil
+}
+
+// UserTextureUpdateOne is the builder for updating a single UserTexture entity.
+type UserTextureUpdateOne struct {
+ config
+ fields []string
+ hooks []Hook
+ mutation *UserTextureMutation
+}
+
+// SetUserProfileID sets the "user_profile_id" field.
+func (utuo *UserTextureUpdateOne) SetUserProfileID(i int) *UserTextureUpdateOne {
+ utuo.mutation.SetUserProfileID(i)
+ return utuo
+}
+
+// SetTextureID sets the "texture_id" field.
+func (utuo *UserTextureUpdateOne) SetTextureID(i int) *UserTextureUpdateOne {
+ utuo.mutation.SetTextureID(i)
+ return utuo
+}
+
+// SetType sets the "type" field.
+func (utuo *UserTextureUpdateOne) SetType(s string) *UserTextureUpdateOne {
+ utuo.mutation.SetType(s)
+ return utuo
+}
+
+// SetVariant sets the "variant" field.
+func (utuo *UserTextureUpdateOne) SetVariant(s string) *UserTextureUpdateOne {
+ utuo.mutation.SetVariant(s)
+ return utuo
+}
+
+// SetUserProfile sets the "user_profile" edge to the UserProfile entity.
+func (utuo *UserTextureUpdateOne) SetUserProfile(u *UserProfile) *UserTextureUpdateOne {
+ return utuo.SetUserProfileID(u.ID)
+}
+
+// SetTexture sets the "texture" edge to the Texture entity.
+func (utuo *UserTextureUpdateOne) SetTexture(t *Texture) *UserTextureUpdateOne {
+ return utuo.SetTextureID(t.ID)
+}
+
+// Mutation returns the UserTextureMutation object of the builder.
+func (utuo *UserTextureUpdateOne) Mutation() *UserTextureMutation {
+ return utuo.mutation
+}
+
+// ClearUserProfile clears the "user_profile" edge to the UserProfile entity.
+func (utuo *UserTextureUpdateOne) ClearUserProfile() *UserTextureUpdateOne {
+ utuo.mutation.ClearUserProfile()
+ return utuo
+}
+
+// ClearTexture clears the "texture" edge to the Texture entity.
+func (utuo *UserTextureUpdateOne) ClearTexture() *UserTextureUpdateOne {
+ utuo.mutation.ClearTexture()
+ return utuo
+}
+
+// Where appends a list predicates to the UserTextureUpdate builder.
+func (utuo *UserTextureUpdateOne) Where(ps ...predicate.UserTexture) *UserTextureUpdateOne {
+ utuo.mutation.Where(ps...)
+ return utuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (utuo *UserTextureUpdateOne) Select(field string, fields ...string) *UserTextureUpdateOne {
+ utuo.fields = append([]string{field}, fields...)
+ return utuo
+}
+
+// Save executes the query and returns the updated UserTexture entity.
+func (utuo *UserTextureUpdateOne) Save(ctx context.Context) (*UserTexture, error) {
+ return withHooks(ctx, utuo.sqlSave, utuo.mutation, utuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (utuo *UserTextureUpdateOne) SaveX(ctx context.Context) *UserTexture {
+ node, err := utuo.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return node
+}
+
+// Exec executes the query on the entity.
+func (utuo *UserTextureUpdateOne) Exec(ctx context.Context) error {
+ _, err := utuo.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utuo *UserTextureUpdateOne) ExecX(ctx context.Context) {
+ if err := utuo.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (utuo *UserTextureUpdateOne) check() error {
+ if _, ok := utuo.mutation.UserProfileID(); utuo.mutation.UserProfileCleared() && !ok {
+ return errors.New(`ent: clearing a required unique edge "UserTexture.user_profile"`)
+ }
+ if _, ok := utuo.mutation.TextureID(); utuo.mutation.TextureCleared() && !ok {
+ return errors.New(`ent: clearing a required unique edge "UserTexture.texture"`)
+ }
+ return nil
+}
+
+func (utuo *UserTextureUpdateOne) sqlSave(ctx context.Context) (_node *UserTexture, err error) {
+ if err := utuo.check(); err != nil {
+ return _node, err
+ }
+ _spec := sqlgraph.NewUpdateSpec(usertexture.Table, usertexture.Columns, sqlgraph.NewFieldSpec(usertexture.FieldID, field.TypeInt))
+ id, ok := utuo.mutation.ID()
+ if !ok {
+ return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "UserTexture.id" for update`)}
+ }
+ _spec.Node.ID.Value = id
+ if fields := utuo.fields; len(fields) > 0 {
+ _spec.Node.Columns = make([]string, 0, len(fields))
+ _spec.Node.Columns = append(_spec.Node.Columns, usertexture.FieldID)
+ for _, f := range fields {
+ if !usertexture.ValidColumn(f) {
+ return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+ }
+ if f != usertexture.FieldID {
+ _spec.Node.Columns = append(_spec.Node.Columns, f)
+ }
+ }
+ }
+ if ps := utuo.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if value, ok := utuo.mutation.GetType(); ok {
+ _spec.SetField(usertexture.FieldType, field.TypeString, value)
+ }
+ if value, ok := utuo.mutation.Variant(); ok {
+ _spec.SetField(usertexture.FieldVariant, field.TypeString, value)
+ }
+ if utuo.mutation.UserProfileCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: usertexture.UserProfileTable,
+ Columns: []string{usertexture.UserProfileColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := utuo.mutation.UserProfileIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: usertexture.UserProfileTable,
+ Columns: []string{usertexture.UserProfileColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(userprofile.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if utuo.mutation.TextureCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: usertexture.TextureTable,
+ Columns: []string{usertexture.TextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := utuo.mutation.TextureIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.M2O,
+ Inverse: false,
+ Table: usertexture.TextureTable,
+ Columns: []string{usertexture.TextureColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(texture.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ _node = &UserTexture{config: utuo.config}
+ _spec.Assign = _node.assignValues
+ _spec.ScanValues = _node.scanValues
+ if err = sqlgraph.UpdateNode(ctx, utuo.driver, _spec); err != nil {
+ if _, ok := err.(*sqlgraph.NotFoundError); ok {
+ err = &NotFoundError{usertexture.Label}
+ } else if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return nil, err
+ }
+ utuo.mutation.done = true
+ return _node, nil
+}
diff --git a/db/ent/usertoken.go b/db/ent/usertoken.go
new file mode 100644
index 0000000..c944538
--- /dev/null
+++ b/db/ent/usertoken.go
@@ -0,0 +1,142 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "fmt"
+ "strings"
+
+ "entgo.io/ent"
+ "entgo.io/ent/dialect/sql"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+// UserToken is the model entity for the UserToken schema.
+type UserToken struct {
+ config `json:"-"`
+ // ID of the ent.
+ ID int `json:"id,omitempty"`
+ // TokenID holds the value of the "token_id" field.
+ TokenID uint64 `json:"token_id,omitempty"`
+ // Edges holds the relations/edges for other nodes in the graph.
+ // The values are being populated by the UserTokenQuery when eager-loading is set.
+ Edges UserTokenEdges `json:"edges"`
+ user_token *int
+ selectValues sql.SelectValues
+}
+
+// UserTokenEdges holds the relations/edges for other nodes in the graph.
+type UserTokenEdges struct {
+ // User holds the value of the user edge.
+ User *User `json:"user,omitempty"`
+ // loadedTypes holds the information for reporting if a
+ // type was loaded (or requested) in eager-loading or not.
+ loadedTypes [1]bool
+}
+
+// UserOrErr returns the User value or an error if the edge
+// was not loaded in eager-loading, or loaded but was not found.
+func (e UserTokenEdges) UserOrErr() (*User, error) {
+ if e.loadedTypes[0] {
+ if e.User == nil {
+ // Edge was loaded but was not found.
+ return nil, &NotFoundError{label: user.Label}
+ }
+ return e.User, nil
+ }
+ return nil, &NotLoadedError{edge: "user"}
+}
+
+// scanValues returns the types for scanning values from sql.Rows.
+func (*UserToken) scanValues(columns []string) ([]any, error) {
+ values := make([]any, len(columns))
+ for i := range columns {
+ switch columns[i] {
+ case usertoken.FieldID, usertoken.FieldTokenID:
+ values[i] = new(sql.NullInt64)
+ case usertoken.ForeignKeys[0]: // user_token
+ values[i] = new(sql.NullInt64)
+ default:
+ values[i] = new(sql.UnknownType)
+ }
+ }
+ return values, nil
+}
+
+// assignValues assigns the values that were returned from sql.Rows (after scanning)
+// to the UserToken fields.
+func (ut *UserToken) assignValues(columns []string, values []any) error {
+ if m, n := len(values), len(columns); m < n {
+ return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
+ }
+ for i := range columns {
+ switch columns[i] {
+ case usertoken.FieldID:
+ value, ok := values[i].(*sql.NullInt64)
+ if !ok {
+ return fmt.Errorf("unexpected type %T for field id", value)
+ }
+ ut.ID = int(value.Int64)
+ case usertoken.FieldTokenID:
+ if value, ok := values[i].(*sql.NullInt64); !ok {
+ return fmt.Errorf("unexpected type %T for field token_id", values[i])
+ } else if value.Valid {
+ ut.TokenID = uint64(value.Int64)
+ }
+ case usertoken.ForeignKeys[0]:
+ if value, ok := values[i].(*sql.NullInt64); !ok {
+ return fmt.Errorf("unexpected type %T for edge-field user_token", value)
+ } else if value.Valid {
+ ut.user_token = new(int)
+ *ut.user_token = int(value.Int64)
+ }
+ default:
+ ut.selectValues.Set(columns[i], values[i])
+ }
+ }
+ return nil
+}
+
+// Value returns the ent.Value that was dynamically selected and assigned to the UserToken.
+// This includes values selected through modifiers, order, etc.
+func (ut *UserToken) Value(name string) (ent.Value, error) {
+ return ut.selectValues.Get(name)
+}
+
+// QueryUser queries the "user" edge of the UserToken entity.
+func (ut *UserToken) QueryUser() *UserQuery {
+ return NewUserTokenClient(ut.config).QueryUser(ut)
+}
+
+// Update returns a builder for updating this UserToken.
+// Note that you need to call UserToken.Unwrap() before calling this method if this UserToken
+// was returned from a transaction, and the transaction was committed or rolled back.
+func (ut *UserToken) Update() *UserTokenUpdateOne {
+ return NewUserTokenClient(ut.config).UpdateOne(ut)
+}
+
+// Unwrap unwraps the UserToken entity that was returned from a transaction after it was closed,
+// so that all future queries will be executed through the driver which created the transaction.
+func (ut *UserToken) Unwrap() *UserToken {
+ _tx, ok := ut.config.driver.(*txDriver)
+ if !ok {
+ panic("ent: UserToken is not a transactional entity")
+ }
+ ut.config.driver = _tx.drv
+ return ut
+}
+
+// String implements the fmt.Stringer.
+func (ut *UserToken) String() string {
+ var builder strings.Builder
+ builder.WriteString("UserToken(")
+ builder.WriteString(fmt.Sprintf("id=%v, ", ut.ID))
+ builder.WriteString("token_id=")
+ builder.WriteString(fmt.Sprintf("%v", ut.TokenID))
+ builder.WriteByte(')')
+ return builder.String()
+}
+
+// UserTokens is a parsable slice of UserToken.
+type UserTokens []*UserToken
diff --git a/db/ent/usertoken/usertoken.go b/db/ent/usertoken/usertoken.go
new file mode 100644
index 0000000..a9d8958
--- /dev/null
+++ b/db/ent/usertoken/usertoken.go
@@ -0,0 +1,82 @@
+// Code generated by ent, DO NOT EDIT.
+
+package usertoken
+
+import (
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+)
+
+const (
+ // Label holds the string label denoting the usertoken type in the database.
+ Label = "user_token"
+ // FieldID holds the string denoting the id field in the database.
+ FieldID = "id"
+ // FieldTokenID holds the string denoting the token_id field in the database.
+ FieldTokenID = "token_id"
+ // EdgeUser holds the string denoting the user edge name in mutations.
+ EdgeUser = "user"
+ // Table holds the table name of the usertoken in the database.
+ Table = "user_tokens"
+ // UserTable is the table that holds the user relation/edge.
+ UserTable = "user_tokens"
+ // UserInverseTable is the table name for the User entity.
+ // It exists in this package in order to avoid circular dependency with the "user" package.
+ UserInverseTable = "users"
+ // UserColumn is the table column denoting the user relation/edge.
+ UserColumn = "user_token"
+)
+
+// Columns holds all SQL columns for usertoken fields.
+var Columns = []string{
+ FieldID,
+ FieldTokenID,
+}
+
+// ForeignKeys holds the SQL foreign-keys that are owned by the "user_tokens"
+// table and are not defined as standalone fields in the schema.
+var ForeignKeys = []string{
+ "user_token",
+}
+
+// ValidColumn reports if the column name is valid (part of the table columns).
+func ValidColumn(column string) bool {
+ for i := range Columns {
+ if column == Columns[i] {
+ return true
+ }
+ }
+ for i := range ForeignKeys {
+ if column == ForeignKeys[i] {
+ return true
+ }
+ }
+ return false
+}
+
+// OrderOption defines the ordering options for the UserToken queries.
+type OrderOption func(*sql.Selector)
+
+// ByID orders the results by the id field.
+func ByID(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldID, opts...).ToFunc()
+}
+
+// ByTokenID orders the results by the token_id field.
+func ByTokenID(opts ...sql.OrderTermOption) OrderOption {
+ return sql.OrderByField(FieldTokenID, opts...).ToFunc()
+}
+
+// ByUserField orders the results by user field.
+func ByUserField(field string, opts ...sql.OrderTermOption) OrderOption {
+ return func(s *sql.Selector) {
+ sqlgraph.OrderByNeighborTerms(s, newUserStep(), sql.OrderByField(field, opts...))
+ }
+}
+func newUserStep() *sqlgraph.Step {
+ return sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.To(UserInverseTable, FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, true, UserTable, UserColumn),
+ )
+}
diff --git a/db/ent/usertoken/where.go b/db/ent/usertoken/where.go
new file mode 100644
index 0000000..fb39a0f
--- /dev/null
+++ b/db/ent/usertoken/where.go
@@ -0,0 +1,154 @@
+// Code generated by ent, DO NOT EDIT.
+
+package usertoken
+
+import (
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+)
+
+// ID filters vertices based on their ID field.
+func ID(id int) predicate.UserToken {
+ return predicate.UserToken(sql.FieldEQ(FieldID, id))
+}
+
+// IDEQ applies the EQ predicate on the ID field.
+func IDEQ(id int) predicate.UserToken {
+ return predicate.UserToken(sql.FieldEQ(FieldID, id))
+}
+
+// IDNEQ applies the NEQ predicate on the ID field.
+func IDNEQ(id int) predicate.UserToken {
+ return predicate.UserToken(sql.FieldNEQ(FieldID, id))
+}
+
+// IDIn applies the In predicate on the ID field.
+func IDIn(ids ...int) predicate.UserToken {
+ return predicate.UserToken(sql.FieldIn(FieldID, ids...))
+}
+
+// IDNotIn applies the NotIn predicate on the ID field.
+func IDNotIn(ids ...int) predicate.UserToken {
+ return predicate.UserToken(sql.FieldNotIn(FieldID, ids...))
+}
+
+// IDGT applies the GT predicate on the ID field.
+func IDGT(id int) predicate.UserToken {
+ return predicate.UserToken(sql.FieldGT(FieldID, id))
+}
+
+// IDGTE applies the GTE predicate on the ID field.
+func IDGTE(id int) predicate.UserToken {
+ return predicate.UserToken(sql.FieldGTE(FieldID, id))
+}
+
+// IDLT applies the LT predicate on the ID field.
+func IDLT(id int) predicate.UserToken {
+ return predicate.UserToken(sql.FieldLT(FieldID, id))
+}
+
+// IDLTE applies the LTE predicate on the ID field.
+func IDLTE(id int) predicate.UserToken {
+ return predicate.UserToken(sql.FieldLTE(FieldID, id))
+}
+
+// TokenID applies equality check predicate on the "token_id" field. It's identical to TokenIDEQ.
+func TokenID(v uint64) predicate.UserToken {
+ return predicate.UserToken(sql.FieldEQ(FieldTokenID, v))
+}
+
+// TokenIDEQ applies the EQ predicate on the "token_id" field.
+func TokenIDEQ(v uint64) predicate.UserToken {
+ return predicate.UserToken(sql.FieldEQ(FieldTokenID, v))
+}
+
+// TokenIDNEQ applies the NEQ predicate on the "token_id" field.
+func TokenIDNEQ(v uint64) predicate.UserToken {
+ return predicate.UserToken(sql.FieldNEQ(FieldTokenID, v))
+}
+
+// TokenIDIn applies the In predicate on the "token_id" field.
+func TokenIDIn(vs ...uint64) predicate.UserToken {
+ return predicate.UserToken(sql.FieldIn(FieldTokenID, vs...))
+}
+
+// TokenIDNotIn applies the NotIn predicate on the "token_id" field.
+func TokenIDNotIn(vs ...uint64) predicate.UserToken {
+ return predicate.UserToken(sql.FieldNotIn(FieldTokenID, vs...))
+}
+
+// TokenIDGT applies the GT predicate on the "token_id" field.
+func TokenIDGT(v uint64) predicate.UserToken {
+ return predicate.UserToken(sql.FieldGT(FieldTokenID, v))
+}
+
+// TokenIDGTE applies the GTE predicate on the "token_id" field.
+func TokenIDGTE(v uint64) predicate.UserToken {
+ return predicate.UserToken(sql.FieldGTE(FieldTokenID, v))
+}
+
+// TokenIDLT applies the LT predicate on the "token_id" field.
+func TokenIDLT(v uint64) predicate.UserToken {
+ return predicate.UserToken(sql.FieldLT(FieldTokenID, v))
+}
+
+// TokenIDLTE applies the LTE predicate on the "token_id" field.
+func TokenIDLTE(v uint64) predicate.UserToken {
+ return predicate.UserToken(sql.FieldLTE(FieldTokenID, v))
+}
+
+// HasUser applies the HasEdge predicate on the "user" edge.
+func HasUser() predicate.UserToken {
+ return predicate.UserToken(func(s *sql.Selector) {
+ step := sqlgraph.NewStep(
+ sqlgraph.From(Table, FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, true, UserTable, UserColumn),
+ )
+ sqlgraph.HasNeighbors(s, step)
+ })
+}
+
+// HasUserWith applies the HasEdge predicate on the "user" edge with a given conditions (other predicates).
+func HasUserWith(preds ...predicate.User) predicate.UserToken {
+ return predicate.UserToken(func(s *sql.Selector) {
+ step := newUserStep()
+ sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
+ for _, p := range preds {
+ p(s)
+ }
+ })
+ })
+}
+
+// And groups predicates with the AND operator between them.
+func And(predicates ...predicate.UserToken) predicate.UserToken {
+ return predicate.UserToken(func(s *sql.Selector) {
+ s1 := s.Clone().SetP(nil)
+ for _, p := range predicates {
+ p(s1)
+ }
+ s.Where(s1.P())
+ })
+}
+
+// Or groups predicates with the OR operator between them.
+func Or(predicates ...predicate.UserToken) predicate.UserToken {
+ return predicate.UserToken(func(s *sql.Selector) {
+ s1 := s.Clone().SetP(nil)
+ for i, p := range predicates {
+ if i > 0 {
+ s1.Or()
+ }
+ p(s1)
+ }
+ s.Where(s1.P())
+ })
+}
+
+// Not applies the not operator on the given predicate.
+func Not(p predicate.UserToken) predicate.UserToken {
+ return predicate.UserToken(func(s *sql.Selector) {
+ p(s.Not())
+ })
+}
diff --git a/db/ent/usertoken_create.go b/db/ent/usertoken_create.go
new file mode 100644
index 0000000..3bf2219
--- /dev/null
+++ b/db/ent/usertoken_create.go
@@ -0,0 +1,216 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+// UserTokenCreate is the builder for creating a UserToken entity.
+type UserTokenCreate struct {
+ config
+ mutation *UserTokenMutation
+ hooks []Hook
+}
+
+// SetTokenID sets the "token_id" field.
+func (utc *UserTokenCreate) SetTokenID(u uint64) *UserTokenCreate {
+ utc.mutation.SetTokenID(u)
+ return utc
+}
+
+// SetUserID sets the "user" edge to the User entity by ID.
+func (utc *UserTokenCreate) SetUserID(id int) *UserTokenCreate {
+ utc.mutation.SetUserID(id)
+ return utc
+}
+
+// SetNillableUserID sets the "user" edge to the User entity by ID if the given value is not nil.
+func (utc *UserTokenCreate) SetNillableUserID(id *int) *UserTokenCreate {
+ if id != nil {
+ utc = utc.SetUserID(*id)
+ }
+ return utc
+}
+
+// SetUser sets the "user" edge to the User entity.
+func (utc *UserTokenCreate) SetUser(u *User) *UserTokenCreate {
+ return utc.SetUserID(u.ID)
+}
+
+// Mutation returns the UserTokenMutation object of the builder.
+func (utc *UserTokenCreate) Mutation() *UserTokenMutation {
+ return utc.mutation
+}
+
+// Save creates the UserToken in the database.
+func (utc *UserTokenCreate) Save(ctx context.Context) (*UserToken, error) {
+ return withHooks(ctx, utc.sqlSave, utc.mutation, utc.hooks)
+}
+
+// SaveX calls Save and panics if Save returns an error.
+func (utc *UserTokenCreate) SaveX(ctx context.Context) *UserToken {
+ v, err := utc.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Exec executes the query.
+func (utc *UserTokenCreate) Exec(ctx context.Context) error {
+ _, err := utc.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utc *UserTokenCreate) ExecX(ctx context.Context) {
+ if err := utc.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+// check runs all checks and user-defined validators on the builder.
+func (utc *UserTokenCreate) check() error {
+ if _, ok := utc.mutation.TokenID(); !ok {
+ return &ValidationError{Name: "token_id", err: errors.New(`ent: missing required field "UserToken.token_id"`)}
+ }
+ return nil
+}
+
+func (utc *UserTokenCreate) sqlSave(ctx context.Context) (*UserToken, error) {
+ if err := utc.check(); err != nil {
+ return nil, err
+ }
+ _node, _spec := utc.createSpec()
+ if err := sqlgraph.CreateNode(ctx, utc.driver, _spec); err != nil {
+ if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return nil, err
+ }
+ id := _spec.ID.Value.(int64)
+ _node.ID = int(id)
+ utc.mutation.id = &_node.ID
+ utc.mutation.done = true
+ return _node, nil
+}
+
+func (utc *UserTokenCreate) createSpec() (*UserToken, *sqlgraph.CreateSpec) {
+ var (
+ _node = &UserToken{config: utc.config}
+ _spec = sqlgraph.NewCreateSpec(usertoken.Table, sqlgraph.NewFieldSpec(usertoken.FieldID, field.TypeInt))
+ )
+ if value, ok := utc.mutation.TokenID(); ok {
+ _spec.SetField(usertoken.FieldTokenID, field.TypeUint64, value)
+ _node.TokenID = value
+ }
+ if nodes := utc.mutation.UserIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: true,
+ Table: usertoken.UserTable,
+ Columns: []string{usertoken.UserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _node.user_token = &nodes[0]
+ _spec.Edges = append(_spec.Edges, edge)
+ }
+ return _node, _spec
+}
+
+// UserTokenCreateBulk is the builder for creating many UserToken entities in bulk.
+type UserTokenCreateBulk struct {
+ config
+ builders []*UserTokenCreate
+}
+
+// Save creates the UserToken entities in the database.
+func (utcb *UserTokenCreateBulk) Save(ctx context.Context) ([]*UserToken, error) {
+ specs := make([]*sqlgraph.CreateSpec, len(utcb.builders))
+ nodes := make([]*UserToken, len(utcb.builders))
+ mutators := make([]Mutator, len(utcb.builders))
+ for i := range utcb.builders {
+ func(i int, root context.Context) {
+ builder := utcb.builders[i]
+ var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
+ mutation, ok := m.(*UserTokenMutation)
+ if !ok {
+ return nil, fmt.Errorf("unexpected mutation type %T", m)
+ }
+ if err := builder.check(); err != nil {
+ return nil, err
+ }
+ builder.mutation = mutation
+ var err error
+ nodes[i], specs[i] = builder.createSpec()
+ if i < len(mutators)-1 {
+ _, err = mutators[i+1].Mutate(root, utcb.builders[i+1].mutation)
+ } else {
+ spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
+ // Invoke the actual operation on the latest mutation in the chain.
+ if err = sqlgraph.BatchCreate(ctx, utcb.driver, spec); err != nil {
+ if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ mutation.id = &nodes[i].ID
+ if specs[i].ID.Value != nil {
+ id := specs[i].ID.Value.(int64)
+ nodes[i].ID = int(id)
+ }
+ mutation.done = true
+ return nodes[i], nil
+ })
+ for i := len(builder.hooks) - 1; i >= 0; i-- {
+ mut = builder.hooks[i](mut)
+ }
+ mutators[i] = mut
+ }(i, ctx)
+ }
+ if len(mutators) > 0 {
+ if _, err := mutators[0].Mutate(ctx, utcb.builders[0].mutation); err != nil {
+ return nil, err
+ }
+ }
+ return nodes, nil
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (utcb *UserTokenCreateBulk) SaveX(ctx context.Context) []*UserToken {
+ v, err := utcb.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
+// Exec executes the query.
+func (utcb *UserTokenCreateBulk) Exec(ctx context.Context) error {
+ _, err := utcb.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utcb *UserTokenCreateBulk) ExecX(ctx context.Context) {
+ if err := utcb.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
diff --git a/db/ent/usertoken_delete.go b/db/ent/usertoken_delete.go
new file mode 100644
index 0000000..1f6a2ba
--- /dev/null
+++ b/db/ent/usertoken_delete.go
@@ -0,0 +1,88 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+// UserTokenDelete is the builder for deleting a UserToken entity.
+type UserTokenDelete struct {
+ config
+ hooks []Hook
+ mutation *UserTokenMutation
+}
+
+// Where appends a list predicates to the UserTokenDelete builder.
+func (utd *UserTokenDelete) Where(ps ...predicate.UserToken) *UserTokenDelete {
+ utd.mutation.Where(ps...)
+ return utd
+}
+
+// Exec executes the deletion query and returns how many vertices were deleted.
+func (utd *UserTokenDelete) Exec(ctx context.Context) (int, error) {
+ return withHooks(ctx, utd.sqlExec, utd.mutation, utd.hooks)
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utd *UserTokenDelete) ExecX(ctx context.Context) int {
+ n, err := utd.Exec(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return n
+}
+
+func (utd *UserTokenDelete) sqlExec(ctx context.Context) (int, error) {
+ _spec := sqlgraph.NewDeleteSpec(usertoken.Table, sqlgraph.NewFieldSpec(usertoken.FieldID, field.TypeInt))
+ if ps := utd.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ affected, err := sqlgraph.DeleteNodes(ctx, utd.driver, _spec)
+ if err != nil && sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ utd.mutation.done = true
+ return affected, err
+}
+
+// UserTokenDeleteOne is the builder for deleting a single UserToken entity.
+type UserTokenDeleteOne struct {
+ utd *UserTokenDelete
+}
+
+// Where appends a list predicates to the UserTokenDelete builder.
+func (utdo *UserTokenDeleteOne) Where(ps ...predicate.UserToken) *UserTokenDeleteOne {
+ utdo.utd.mutation.Where(ps...)
+ return utdo
+}
+
+// Exec executes the deletion query.
+func (utdo *UserTokenDeleteOne) Exec(ctx context.Context) error {
+ n, err := utdo.utd.Exec(ctx)
+ switch {
+ case err != nil:
+ return err
+ case n == 0:
+ return &NotFoundError{usertoken.Label}
+ default:
+ return nil
+ }
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utdo *UserTokenDeleteOne) ExecX(ctx context.Context) {
+ if err := utdo.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
diff --git a/db/ent/usertoken_query.go b/db/ent/usertoken_query.go
new file mode 100644
index 0000000..6a6bc9d
--- /dev/null
+++ b/db/ent/usertoken_query.go
@@ -0,0 +1,670 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "fmt"
+ "math"
+
+ "entgo.io/ent/dialect"
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+// UserTokenQuery is the builder for querying UserToken entities.
+type UserTokenQuery struct {
+ config
+ ctx *QueryContext
+ order []usertoken.OrderOption
+ inters []Interceptor
+ predicates []predicate.UserToken
+ withUser *UserQuery
+ withFKs bool
+ modifiers []func(*sql.Selector)
+ // intermediate query (i.e. traversal path).
+ sql *sql.Selector
+ path func(context.Context) (*sql.Selector, error)
+}
+
+// Where adds a new predicate for the UserTokenQuery builder.
+func (utq *UserTokenQuery) Where(ps ...predicate.UserToken) *UserTokenQuery {
+ utq.predicates = append(utq.predicates, ps...)
+ return utq
+}
+
+// Limit the number of records to be returned by this query.
+func (utq *UserTokenQuery) Limit(limit int) *UserTokenQuery {
+ utq.ctx.Limit = &limit
+ return utq
+}
+
+// Offset to start from.
+func (utq *UserTokenQuery) Offset(offset int) *UserTokenQuery {
+ utq.ctx.Offset = &offset
+ return utq
+}
+
+// Unique configures the query builder to filter duplicate records on query.
+// By default, unique is set to true, and can be disabled using this method.
+func (utq *UserTokenQuery) Unique(unique bool) *UserTokenQuery {
+ utq.ctx.Unique = &unique
+ return utq
+}
+
+// Order specifies how the records should be ordered.
+func (utq *UserTokenQuery) Order(o ...usertoken.OrderOption) *UserTokenQuery {
+ utq.order = append(utq.order, o...)
+ return utq
+}
+
+// QueryUser chains the current query on the "user" edge.
+func (utq *UserTokenQuery) QueryUser() *UserQuery {
+ query := (&UserClient{config: utq.config}).Query()
+ query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
+ if err := utq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ selector := utq.sqlQuery(ctx)
+ if err := selector.Err(); err != nil {
+ return nil, err
+ }
+ step := sqlgraph.NewStep(
+ sqlgraph.From(usertoken.Table, usertoken.FieldID, selector),
+ sqlgraph.To(user.Table, user.FieldID),
+ sqlgraph.Edge(sqlgraph.O2O, true, usertoken.UserTable, usertoken.UserColumn),
+ )
+ fromU = sqlgraph.SetNeighbors(utq.driver.Dialect(), step)
+ return fromU, nil
+ }
+ return query
+}
+
+// First returns the first UserToken entity from the query.
+// Returns a *NotFoundError when no UserToken was found.
+func (utq *UserTokenQuery) First(ctx context.Context) (*UserToken, error) {
+ nodes, err := utq.Limit(1).All(setContextOp(ctx, utq.ctx, "First"))
+ if err != nil {
+ return nil, err
+ }
+ if len(nodes) == 0 {
+ return nil, &NotFoundError{usertoken.Label}
+ }
+ return nodes[0], nil
+}
+
+// FirstX is like First, but panics if an error occurs.
+func (utq *UserTokenQuery) FirstX(ctx context.Context) *UserToken {
+ node, err := utq.First(ctx)
+ if err != nil && !IsNotFound(err) {
+ panic(err)
+ }
+ return node
+}
+
+// FirstID returns the first UserToken ID from the query.
+// Returns a *NotFoundError when no UserToken ID was found.
+func (utq *UserTokenQuery) FirstID(ctx context.Context) (id int, err error) {
+ var ids []int
+ if ids, err = utq.Limit(1).IDs(setContextOp(ctx, utq.ctx, "FirstID")); err != nil {
+ return
+ }
+ if len(ids) == 0 {
+ err = &NotFoundError{usertoken.Label}
+ return
+ }
+ return ids[0], nil
+}
+
+// FirstIDX is like FirstID, but panics if an error occurs.
+func (utq *UserTokenQuery) FirstIDX(ctx context.Context) int {
+ id, err := utq.FirstID(ctx)
+ if err != nil && !IsNotFound(err) {
+ panic(err)
+ }
+ return id
+}
+
+// Only returns a single UserToken entity found by the query, ensuring it only returns one.
+// Returns a *NotSingularError when more than one UserToken entity is found.
+// Returns a *NotFoundError when no UserToken entities are found.
+func (utq *UserTokenQuery) Only(ctx context.Context) (*UserToken, error) {
+ nodes, err := utq.Limit(2).All(setContextOp(ctx, utq.ctx, "Only"))
+ if err != nil {
+ return nil, err
+ }
+ switch len(nodes) {
+ case 1:
+ return nodes[0], nil
+ case 0:
+ return nil, &NotFoundError{usertoken.Label}
+ default:
+ return nil, &NotSingularError{usertoken.Label}
+ }
+}
+
+// OnlyX is like Only, but panics if an error occurs.
+func (utq *UserTokenQuery) OnlyX(ctx context.Context) *UserToken {
+ node, err := utq.Only(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return node
+}
+
+// OnlyID is like Only, but returns the only UserToken ID in the query.
+// Returns a *NotSingularError when more than one UserToken ID is found.
+// Returns a *NotFoundError when no entities are found.
+func (utq *UserTokenQuery) OnlyID(ctx context.Context) (id int, err error) {
+ var ids []int
+ if ids, err = utq.Limit(2).IDs(setContextOp(ctx, utq.ctx, "OnlyID")); err != nil {
+ return
+ }
+ switch len(ids) {
+ case 1:
+ id = ids[0]
+ case 0:
+ err = &NotFoundError{usertoken.Label}
+ default:
+ err = &NotSingularError{usertoken.Label}
+ }
+ return
+}
+
+// OnlyIDX is like OnlyID, but panics if an error occurs.
+func (utq *UserTokenQuery) OnlyIDX(ctx context.Context) int {
+ id, err := utq.OnlyID(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return id
+}
+
+// All executes the query and returns a list of UserTokens.
+func (utq *UserTokenQuery) All(ctx context.Context) ([]*UserToken, error) {
+ ctx = setContextOp(ctx, utq.ctx, "All")
+ if err := utq.prepareQuery(ctx); err != nil {
+ return nil, err
+ }
+ qr := querierAll[[]*UserToken, *UserTokenQuery]()
+ return withInterceptors[[]*UserToken](ctx, utq, qr, utq.inters)
+}
+
+// AllX is like All, but panics if an error occurs.
+func (utq *UserTokenQuery) AllX(ctx context.Context) []*UserToken {
+ nodes, err := utq.All(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return nodes
+}
+
+// IDs executes the query and returns a list of UserToken IDs.
+func (utq *UserTokenQuery) IDs(ctx context.Context) (ids []int, err error) {
+ if utq.ctx.Unique == nil && utq.path != nil {
+ utq.Unique(true)
+ }
+ ctx = setContextOp(ctx, utq.ctx, "IDs")
+ if err = utq.Select(usertoken.FieldID).Scan(ctx, &ids); err != nil {
+ return nil, err
+ }
+ return ids, nil
+}
+
+// IDsX is like IDs, but panics if an error occurs.
+func (utq *UserTokenQuery) IDsX(ctx context.Context) []int {
+ ids, err := utq.IDs(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return ids
+}
+
+// Count returns the count of the given query.
+func (utq *UserTokenQuery) Count(ctx context.Context) (int, error) {
+ ctx = setContextOp(ctx, utq.ctx, "Count")
+ if err := utq.prepareQuery(ctx); err != nil {
+ return 0, err
+ }
+ return withInterceptors[int](ctx, utq, querierCount[*UserTokenQuery](), utq.inters)
+}
+
+// CountX is like Count, but panics if an error occurs.
+func (utq *UserTokenQuery) CountX(ctx context.Context) int {
+ count, err := utq.Count(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return count
+}
+
+// Exist returns true if the query has elements in the graph.
+func (utq *UserTokenQuery) Exist(ctx context.Context) (bool, error) {
+ ctx = setContextOp(ctx, utq.ctx, "Exist")
+ switch _, err := utq.FirstID(ctx); {
+ case IsNotFound(err):
+ return false, nil
+ case err != nil:
+ return false, fmt.Errorf("ent: check existence: %w", err)
+ default:
+ return true, nil
+ }
+}
+
+// ExistX is like Exist, but panics if an error occurs.
+func (utq *UserTokenQuery) ExistX(ctx context.Context) bool {
+ exist, err := utq.Exist(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return exist
+}
+
+// Clone returns a duplicate of the UserTokenQuery builder, including all associated steps. It can be
+// used to prepare common query builders and use them differently after the clone is made.
+func (utq *UserTokenQuery) Clone() *UserTokenQuery {
+ if utq == nil {
+ return nil
+ }
+ return &UserTokenQuery{
+ config: utq.config,
+ ctx: utq.ctx.Clone(),
+ order: append([]usertoken.OrderOption{}, utq.order...),
+ inters: append([]Interceptor{}, utq.inters...),
+ predicates: append([]predicate.UserToken{}, utq.predicates...),
+ withUser: utq.withUser.Clone(),
+ // clone intermediate query.
+ sql: utq.sql.Clone(),
+ path: utq.path,
+ }
+}
+
+// WithUser tells the query-builder to eager-load the nodes that are connected to
+// the "user" edge. The optional arguments are used to configure the query builder of the edge.
+func (utq *UserTokenQuery) WithUser(opts ...func(*UserQuery)) *UserTokenQuery {
+ query := (&UserClient{config: utq.config}).Query()
+ for _, opt := range opts {
+ opt(query)
+ }
+ utq.withUser = query
+ return utq
+}
+
+// GroupBy is used to group vertices by one or more fields/columns.
+// It is often used with aggregate functions, like: count, max, mean, min, sum.
+//
+// Example:
+//
+// var v []struct {
+// TokenID uint64 `json:"token_id,omitempty"`
+// Count int `json:"count,omitempty"`
+// }
+//
+// client.UserToken.Query().
+// GroupBy(usertoken.FieldTokenID).
+// Aggregate(ent.Count()).
+// Scan(ctx, &v)
+func (utq *UserTokenQuery) GroupBy(field string, fields ...string) *UserTokenGroupBy {
+ utq.ctx.Fields = append([]string{field}, fields...)
+ grbuild := &UserTokenGroupBy{build: utq}
+ grbuild.flds = &utq.ctx.Fields
+ grbuild.label = usertoken.Label
+ grbuild.scan = grbuild.Scan
+ return grbuild
+}
+
+// Select allows the selection one or more fields/columns for the given query,
+// instead of selecting all fields in the entity.
+//
+// Example:
+//
+// var v []struct {
+// TokenID uint64 `json:"token_id,omitempty"`
+// }
+//
+// client.UserToken.Query().
+// Select(usertoken.FieldTokenID).
+// Scan(ctx, &v)
+func (utq *UserTokenQuery) Select(fields ...string) *UserTokenSelect {
+ utq.ctx.Fields = append(utq.ctx.Fields, fields...)
+ sbuild := &UserTokenSelect{UserTokenQuery: utq}
+ sbuild.label = usertoken.Label
+ sbuild.flds, sbuild.scan = &utq.ctx.Fields, sbuild.Scan
+ return sbuild
+}
+
+// Aggregate returns a UserTokenSelect configured with the given aggregations.
+func (utq *UserTokenQuery) Aggregate(fns ...AggregateFunc) *UserTokenSelect {
+ return utq.Select().Aggregate(fns...)
+}
+
+func (utq *UserTokenQuery) prepareQuery(ctx context.Context) error {
+ for _, inter := range utq.inters {
+ if inter == nil {
+ return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
+ }
+ if trv, ok := inter.(Traverser); ok {
+ if err := trv.Traverse(ctx, utq); err != nil {
+ return err
+ }
+ }
+ }
+ for _, f := range utq.ctx.Fields {
+ if !usertoken.ValidColumn(f) {
+ return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+ }
+ }
+ if utq.path != nil {
+ prev, err := utq.path(ctx)
+ if err != nil {
+ return err
+ }
+ utq.sql = prev
+ }
+ return nil
+}
+
+func (utq *UserTokenQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*UserToken, error) {
+ var (
+ nodes = []*UserToken{}
+ withFKs = utq.withFKs
+ _spec = utq.querySpec()
+ loadedTypes = [1]bool{
+ utq.withUser != nil,
+ }
+ )
+ if utq.withUser != nil {
+ withFKs = true
+ }
+ if withFKs {
+ _spec.Node.Columns = append(_spec.Node.Columns, usertoken.ForeignKeys...)
+ }
+ _spec.ScanValues = func(columns []string) ([]any, error) {
+ return (*UserToken).scanValues(nil, columns)
+ }
+ _spec.Assign = func(columns []string, values []any) error {
+ node := &UserToken{config: utq.config}
+ nodes = append(nodes, node)
+ node.Edges.loadedTypes = loadedTypes
+ return node.assignValues(columns, values)
+ }
+ if len(utq.modifiers) > 0 {
+ _spec.Modifiers = utq.modifiers
+ }
+ for i := range hooks {
+ hooks[i](ctx, _spec)
+ }
+ if err := sqlgraph.QueryNodes(ctx, utq.driver, _spec); err != nil {
+ return nil, err
+ }
+ if len(nodes) == 0 {
+ return nodes, nil
+ }
+ if query := utq.withUser; query != nil {
+ if err := utq.loadUser(ctx, query, nodes, nil,
+ func(n *UserToken, e *User) { n.Edges.User = e }); err != nil {
+ return nil, err
+ }
+ }
+ return nodes, nil
+}
+
+func (utq *UserTokenQuery) loadUser(ctx context.Context, query *UserQuery, nodes []*UserToken, init func(*UserToken), assign func(*UserToken, *User)) error {
+ ids := make([]int, 0, len(nodes))
+ nodeids := make(map[int][]*UserToken)
+ for i := range nodes {
+ if nodes[i].user_token == nil {
+ continue
+ }
+ fk := *nodes[i].user_token
+ if _, ok := nodeids[fk]; !ok {
+ ids = append(ids, fk)
+ }
+ nodeids[fk] = append(nodeids[fk], nodes[i])
+ }
+ if len(ids) == 0 {
+ return nil
+ }
+ query.Where(user.IDIn(ids...))
+ neighbors, err := query.All(ctx)
+ if err != nil {
+ return err
+ }
+ for _, n := range neighbors {
+ nodes, ok := nodeids[n.ID]
+ if !ok {
+ return fmt.Errorf(`unexpected foreign-key "user_token" returned %v`, n.ID)
+ }
+ for i := range nodes {
+ assign(nodes[i], n)
+ }
+ }
+ return nil
+}
+
+func (utq *UserTokenQuery) sqlCount(ctx context.Context) (int, error) {
+ _spec := utq.querySpec()
+ if len(utq.modifiers) > 0 {
+ _spec.Modifiers = utq.modifiers
+ }
+ _spec.Node.Columns = utq.ctx.Fields
+ if len(utq.ctx.Fields) > 0 {
+ _spec.Unique = utq.ctx.Unique != nil && *utq.ctx.Unique
+ }
+ return sqlgraph.CountNodes(ctx, utq.driver, _spec)
+}
+
+func (utq *UserTokenQuery) querySpec() *sqlgraph.QuerySpec {
+ _spec := sqlgraph.NewQuerySpec(usertoken.Table, usertoken.Columns, sqlgraph.NewFieldSpec(usertoken.FieldID, field.TypeInt))
+ _spec.From = utq.sql
+ if unique := utq.ctx.Unique; unique != nil {
+ _spec.Unique = *unique
+ } else if utq.path != nil {
+ _spec.Unique = true
+ }
+ if fields := utq.ctx.Fields; len(fields) > 0 {
+ _spec.Node.Columns = make([]string, 0, len(fields))
+ _spec.Node.Columns = append(_spec.Node.Columns, usertoken.FieldID)
+ for i := range fields {
+ if fields[i] != usertoken.FieldID {
+ _spec.Node.Columns = append(_spec.Node.Columns, fields[i])
+ }
+ }
+ }
+ if ps := utq.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if limit := utq.ctx.Limit; limit != nil {
+ _spec.Limit = *limit
+ }
+ if offset := utq.ctx.Offset; offset != nil {
+ _spec.Offset = *offset
+ }
+ if ps := utq.order; len(ps) > 0 {
+ _spec.Order = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ return _spec
+}
+
+func (utq *UserTokenQuery) sqlQuery(ctx context.Context) *sql.Selector {
+ builder := sql.Dialect(utq.driver.Dialect())
+ t1 := builder.Table(usertoken.Table)
+ columns := utq.ctx.Fields
+ if len(columns) == 0 {
+ columns = usertoken.Columns
+ }
+ selector := builder.Select(t1.Columns(columns...)...).From(t1)
+ if utq.sql != nil {
+ selector = utq.sql
+ selector.Select(selector.Columns(columns...)...)
+ }
+ if utq.ctx.Unique != nil && *utq.ctx.Unique {
+ selector.Distinct()
+ }
+ for _, m := range utq.modifiers {
+ m(selector)
+ }
+ for _, p := range utq.predicates {
+ p(selector)
+ }
+ for _, p := range utq.order {
+ p(selector)
+ }
+ if offset := utq.ctx.Offset; offset != nil {
+ // limit is mandatory for offset clause. We start
+ // with default value, and override it below if needed.
+ selector.Offset(*offset).Limit(math.MaxInt32)
+ }
+ if limit := utq.ctx.Limit; limit != nil {
+ selector.Limit(*limit)
+ }
+ return selector
+}
+
+// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
+// updated, deleted or "selected ... for update" by other sessions, until the transaction is
+// either committed or rolled-back.
+func (utq *UserTokenQuery) ForUpdate(opts ...sql.LockOption) *UserTokenQuery {
+ if utq.driver.Dialect() == dialect.Postgres {
+ utq.Unique(false)
+ }
+ utq.modifiers = append(utq.modifiers, func(s *sql.Selector) {
+ s.ForUpdate(opts...)
+ })
+ return utq
+}
+
+// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
+// on any rows that are read. Other sessions can read the rows, but cannot modify them
+// until your transaction commits.
+func (utq *UserTokenQuery) ForShare(opts ...sql.LockOption) *UserTokenQuery {
+ if utq.driver.Dialect() == dialect.Postgres {
+ utq.Unique(false)
+ }
+ utq.modifiers = append(utq.modifiers, func(s *sql.Selector) {
+ s.ForShare(opts...)
+ })
+ return utq
+}
+
+// ForUpdate locks the selected rows against concurrent updates, and prevent them from being
+// updated, deleted or "selected ... for update" by other sessions, until the transaction is
+// either committed or rolled-back.
+func (utq *UserTokenQuery) ForUpdateA(opts ...sql.LockOption) *UserTokenQuery {
+ if utq.driver.Dialect() == dialect.SQLite {
+ return utq
+ }
+ return utq.ForUpdate(opts...)
+}
+
+// ForShare behaves similarly to ForUpdate, except that it acquires a shared mode lock
+// on any rows that are read. Other sessions can read the rows, but cannot modify them
+// until your transaction commits.
+func (utq *UserTokenQuery) ForShareA(opts ...sql.LockOption) *UserTokenQuery {
+ if utq.driver.Dialect() == dialect.SQLite {
+ return utq
+ }
+ return utq.ForShare(opts...)
+}
+
+// UserTokenGroupBy is the group-by builder for UserToken entities.
+type UserTokenGroupBy struct {
+ selector
+ build *UserTokenQuery
+}
+
+// Aggregate adds the given aggregation functions to the group-by query.
+func (utgb *UserTokenGroupBy) Aggregate(fns ...AggregateFunc) *UserTokenGroupBy {
+ utgb.fns = append(utgb.fns, fns...)
+ return utgb
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (utgb *UserTokenGroupBy) Scan(ctx context.Context, v any) error {
+ ctx = setContextOp(ctx, utgb.build.ctx, "GroupBy")
+ if err := utgb.build.prepareQuery(ctx); err != nil {
+ return err
+ }
+ return scanWithInterceptors[*UserTokenQuery, *UserTokenGroupBy](ctx, utgb.build, utgb, utgb.build.inters, v)
+}
+
+func (utgb *UserTokenGroupBy) sqlScan(ctx context.Context, root *UserTokenQuery, v any) error {
+ selector := root.sqlQuery(ctx).Select()
+ aggregation := make([]string, 0, len(utgb.fns))
+ for _, fn := range utgb.fns {
+ aggregation = append(aggregation, fn(selector))
+ }
+ if len(selector.SelectedColumns()) == 0 {
+ columns := make([]string, 0, len(*utgb.flds)+len(utgb.fns))
+ for _, f := range *utgb.flds {
+ columns = append(columns, selector.C(f))
+ }
+ columns = append(columns, aggregation...)
+ selector.Select(columns...)
+ }
+ selector.GroupBy(selector.Columns(*utgb.flds...)...)
+ if err := selector.Err(); err != nil {
+ return err
+ }
+ rows := &sql.Rows{}
+ query, args := selector.Query()
+ if err := utgb.build.driver.Query(ctx, query, args, rows); err != nil {
+ return err
+ }
+ defer rows.Close()
+ return sql.ScanSlice(rows, v)
+}
+
+// UserTokenSelect is the builder for selecting fields of UserToken entities.
+type UserTokenSelect struct {
+ *UserTokenQuery
+ selector
+}
+
+// Aggregate adds the given aggregation functions to the selector query.
+func (uts *UserTokenSelect) Aggregate(fns ...AggregateFunc) *UserTokenSelect {
+ uts.fns = append(uts.fns, fns...)
+ return uts
+}
+
+// Scan applies the selector query and scans the result into the given value.
+func (uts *UserTokenSelect) Scan(ctx context.Context, v any) error {
+ ctx = setContextOp(ctx, uts.ctx, "Select")
+ if err := uts.prepareQuery(ctx); err != nil {
+ return err
+ }
+ return scanWithInterceptors[*UserTokenQuery, *UserTokenSelect](ctx, uts.UserTokenQuery, uts, uts.inters, v)
+}
+
+func (uts *UserTokenSelect) sqlScan(ctx context.Context, root *UserTokenQuery, v any) error {
+ selector := root.sqlQuery(ctx)
+ aggregation := make([]string, 0, len(uts.fns))
+ for _, fn := range uts.fns {
+ aggregation = append(aggregation, fn(selector))
+ }
+ switch n := len(*uts.selector.flds); {
+ case n == 0 && len(aggregation) > 0:
+ selector.Select(aggregation...)
+ case n != 0 && len(aggregation) > 0:
+ selector.AppendSelect(aggregation...)
+ }
+ rows := &sql.Rows{}
+ query, args := selector.Query()
+ if err := uts.driver.Query(ctx, query, args, rows); err != nil {
+ return err
+ }
+ defer rows.Close()
+ return sql.ScanSlice(rows, v)
+}
diff --git a/db/ent/usertoken_update.go b/db/ent/usertoken_update.go
new file mode 100644
index 0000000..457eeeb
--- /dev/null
+++ b/db/ent/usertoken_update.go
@@ -0,0 +1,322 @@
+// Code generated by ent, DO NOT EDIT.
+
+package ent
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "entgo.io/ent/dialect/sql"
+ "entgo.io/ent/dialect/sql/sqlgraph"
+ "entgo.io/ent/schema/field"
+ "github.com/xmdhs/authlib-skin/db/ent/predicate"
+ "github.com/xmdhs/authlib-skin/db/ent/user"
+ "github.com/xmdhs/authlib-skin/db/ent/usertoken"
+)
+
+// UserTokenUpdate is the builder for updating UserToken entities.
+type UserTokenUpdate struct {
+ config
+ hooks []Hook
+ mutation *UserTokenMutation
+}
+
+// Where appends a list predicates to the UserTokenUpdate builder.
+func (utu *UserTokenUpdate) Where(ps ...predicate.UserToken) *UserTokenUpdate {
+ utu.mutation.Where(ps...)
+ return utu
+}
+
+// SetTokenID sets the "token_id" field.
+func (utu *UserTokenUpdate) SetTokenID(u uint64) *UserTokenUpdate {
+ utu.mutation.ResetTokenID()
+ utu.mutation.SetTokenID(u)
+ return utu
+}
+
+// AddTokenID adds u to the "token_id" field.
+func (utu *UserTokenUpdate) AddTokenID(u int64) *UserTokenUpdate {
+ utu.mutation.AddTokenID(u)
+ return utu
+}
+
+// SetUserID sets the "user" edge to the User entity by ID.
+func (utu *UserTokenUpdate) SetUserID(id int) *UserTokenUpdate {
+ utu.mutation.SetUserID(id)
+ return utu
+}
+
+// SetNillableUserID sets the "user" edge to the User entity by ID if the given value is not nil.
+func (utu *UserTokenUpdate) SetNillableUserID(id *int) *UserTokenUpdate {
+ if id != nil {
+ utu = utu.SetUserID(*id)
+ }
+ return utu
+}
+
+// SetUser sets the "user" edge to the User entity.
+func (utu *UserTokenUpdate) SetUser(u *User) *UserTokenUpdate {
+ return utu.SetUserID(u.ID)
+}
+
+// Mutation returns the UserTokenMutation object of the builder.
+func (utu *UserTokenUpdate) Mutation() *UserTokenMutation {
+ return utu.mutation
+}
+
+// ClearUser clears the "user" edge to the User entity.
+func (utu *UserTokenUpdate) ClearUser() *UserTokenUpdate {
+ utu.mutation.ClearUser()
+ return utu
+}
+
+// Save executes the query and returns the number of nodes affected by the update operation.
+func (utu *UserTokenUpdate) Save(ctx context.Context) (int, error) {
+ return withHooks(ctx, utu.sqlSave, utu.mutation, utu.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (utu *UserTokenUpdate) SaveX(ctx context.Context) int {
+ affected, err := utu.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return affected
+}
+
+// Exec executes the query.
+func (utu *UserTokenUpdate) Exec(ctx context.Context) error {
+ _, err := utu.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utu *UserTokenUpdate) ExecX(ctx context.Context) {
+ if err := utu.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+func (utu *UserTokenUpdate) sqlSave(ctx context.Context) (n int, err error) {
+ _spec := sqlgraph.NewUpdateSpec(usertoken.Table, usertoken.Columns, sqlgraph.NewFieldSpec(usertoken.FieldID, field.TypeInt))
+ if ps := utu.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if value, ok := utu.mutation.TokenID(); ok {
+ _spec.SetField(usertoken.FieldTokenID, field.TypeUint64, value)
+ }
+ if value, ok := utu.mutation.AddedTokenID(); ok {
+ _spec.AddField(usertoken.FieldTokenID, field.TypeUint64, value)
+ }
+ if utu.mutation.UserCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: true,
+ Table: usertoken.UserTable,
+ Columns: []string{usertoken.UserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := utu.mutation.UserIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: true,
+ Table: usertoken.UserTable,
+ Columns: []string{usertoken.UserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ if n, err = sqlgraph.UpdateNodes(ctx, utu.driver, _spec); err != nil {
+ if _, ok := err.(*sqlgraph.NotFoundError); ok {
+ err = &NotFoundError{usertoken.Label}
+ } else if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return 0, err
+ }
+ utu.mutation.done = true
+ return n, nil
+}
+
+// UserTokenUpdateOne is the builder for updating a single UserToken entity.
+type UserTokenUpdateOne struct {
+ config
+ fields []string
+ hooks []Hook
+ mutation *UserTokenMutation
+}
+
+// SetTokenID sets the "token_id" field.
+func (utuo *UserTokenUpdateOne) SetTokenID(u uint64) *UserTokenUpdateOne {
+ utuo.mutation.ResetTokenID()
+ utuo.mutation.SetTokenID(u)
+ return utuo
+}
+
+// AddTokenID adds u to the "token_id" field.
+func (utuo *UserTokenUpdateOne) AddTokenID(u int64) *UserTokenUpdateOne {
+ utuo.mutation.AddTokenID(u)
+ return utuo
+}
+
+// SetUserID sets the "user" edge to the User entity by ID.
+func (utuo *UserTokenUpdateOne) SetUserID(id int) *UserTokenUpdateOne {
+ utuo.mutation.SetUserID(id)
+ return utuo
+}
+
+// SetNillableUserID sets the "user" edge to the User entity by ID if the given value is not nil.
+func (utuo *UserTokenUpdateOne) SetNillableUserID(id *int) *UserTokenUpdateOne {
+ if id != nil {
+ utuo = utuo.SetUserID(*id)
+ }
+ return utuo
+}
+
+// SetUser sets the "user" edge to the User entity.
+func (utuo *UserTokenUpdateOne) SetUser(u *User) *UserTokenUpdateOne {
+ return utuo.SetUserID(u.ID)
+}
+
+// Mutation returns the UserTokenMutation object of the builder.
+func (utuo *UserTokenUpdateOne) Mutation() *UserTokenMutation {
+ return utuo.mutation
+}
+
+// ClearUser clears the "user" edge to the User entity.
+func (utuo *UserTokenUpdateOne) ClearUser() *UserTokenUpdateOne {
+ utuo.mutation.ClearUser()
+ return utuo
+}
+
+// Where appends a list predicates to the UserTokenUpdate builder.
+func (utuo *UserTokenUpdateOne) Where(ps ...predicate.UserToken) *UserTokenUpdateOne {
+ utuo.mutation.Where(ps...)
+ return utuo
+}
+
+// Select allows selecting one or more fields (columns) of the returned entity.
+// The default is selecting all fields defined in the entity schema.
+func (utuo *UserTokenUpdateOne) Select(field string, fields ...string) *UserTokenUpdateOne {
+ utuo.fields = append([]string{field}, fields...)
+ return utuo
+}
+
+// Save executes the query and returns the updated UserToken entity.
+func (utuo *UserTokenUpdateOne) Save(ctx context.Context) (*UserToken, error) {
+ return withHooks(ctx, utuo.sqlSave, utuo.mutation, utuo.hooks)
+}
+
+// SaveX is like Save, but panics if an error occurs.
+func (utuo *UserTokenUpdateOne) SaveX(ctx context.Context) *UserToken {
+ node, err := utuo.Save(ctx)
+ if err != nil {
+ panic(err)
+ }
+ return node
+}
+
+// Exec executes the query on the entity.
+func (utuo *UserTokenUpdateOne) Exec(ctx context.Context) error {
+ _, err := utuo.Save(ctx)
+ return err
+}
+
+// ExecX is like Exec, but panics if an error occurs.
+func (utuo *UserTokenUpdateOne) ExecX(ctx context.Context) {
+ if err := utuo.Exec(ctx); err != nil {
+ panic(err)
+ }
+}
+
+func (utuo *UserTokenUpdateOne) sqlSave(ctx context.Context) (_node *UserToken, err error) {
+ _spec := sqlgraph.NewUpdateSpec(usertoken.Table, usertoken.Columns, sqlgraph.NewFieldSpec(usertoken.FieldID, field.TypeInt))
+ id, ok := utuo.mutation.ID()
+ if !ok {
+ return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "UserToken.id" for update`)}
+ }
+ _spec.Node.ID.Value = id
+ if fields := utuo.fields; len(fields) > 0 {
+ _spec.Node.Columns = make([]string, 0, len(fields))
+ _spec.Node.Columns = append(_spec.Node.Columns, usertoken.FieldID)
+ for _, f := range fields {
+ if !usertoken.ValidColumn(f) {
+ return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
+ }
+ if f != usertoken.FieldID {
+ _spec.Node.Columns = append(_spec.Node.Columns, f)
+ }
+ }
+ }
+ if ps := utuo.mutation.predicates; len(ps) > 0 {
+ _spec.Predicate = func(selector *sql.Selector) {
+ for i := range ps {
+ ps[i](selector)
+ }
+ }
+ }
+ if value, ok := utuo.mutation.TokenID(); ok {
+ _spec.SetField(usertoken.FieldTokenID, field.TypeUint64, value)
+ }
+ if value, ok := utuo.mutation.AddedTokenID(); ok {
+ _spec.AddField(usertoken.FieldTokenID, field.TypeUint64, value)
+ }
+ if utuo.mutation.UserCleared() {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: true,
+ Table: usertoken.UserTable,
+ Columns: []string{usertoken.UserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ _spec.Edges.Clear = append(_spec.Edges.Clear, edge)
+ }
+ if nodes := utuo.mutation.UserIDs(); len(nodes) > 0 {
+ edge := &sqlgraph.EdgeSpec{
+ Rel: sqlgraph.O2O,
+ Inverse: true,
+ Table: usertoken.UserTable,
+ Columns: []string{usertoken.UserColumn},
+ Bidi: false,
+ Target: &sqlgraph.EdgeTarget{
+ IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeInt),
+ },
+ }
+ for _, k := range nodes {
+ edge.Target.Nodes = append(edge.Target.Nodes, k)
+ }
+ _spec.Edges.Add = append(_spec.Edges.Add, edge)
+ }
+ _node = &UserToken{config: utuo.config}
+ _spec.Assign = _node.assignValues
+ _spec.ScanValues = _node.scanValues
+ if err = sqlgraph.UpdateNode(ctx, utuo.driver, _spec); err != nil {
+ if _, ok := err.(*sqlgraph.NotFoundError); ok {
+ err = &NotFoundError{usertoken.Label}
+ } else if sqlgraph.IsConstraintError(err) {
+ err = &ConstraintError{msg: err.Error(), wrap: err}
+ }
+ return nil, err
+ }
+ utuo.mutation.done = true
+ return _node, nil
+}
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..e28dc2b
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,23 @@
+version: "3.9"
+
+networks:
+ traefik:
+ name: traefik
+ external: true
+
+
+services:
+ authlib-skin:
+ build: .
+ container_name: authlib-skin
+ volumes:
+ - /srv/server/authlib-skin:/app/config
+ restart: always
+ labels:
+ - traefik.enable=true
+ - traefik.http.routers.authlib-skin.rule=Host(`auth.hfbz.net`)
+ - traefik.http.routers.authlib-skin.entrypoints=web,websecure
+ - traefik.http.routers.authlib-skin.middlewares=CORS@file
+ - traefik.http.services.authlib-skin.loadbalancer.server.port=8080
+ networks:
+ - traefik
diff --git a/frontend/.env b/frontend/.env
new file mode 100644
index 0000000..44c88d6
--- /dev/null
+++ b/frontend/.env
@@ -0,0 +1 @@
+VITE_APIADDR = ''
\ No newline at end of file
diff --git a/frontend/.env.development b/frontend/.env.development
new file mode 100644
index 0000000..120f8ea
--- /dev/null
+++ b/frontend/.env.development
@@ -0,0 +1 @@
+VITE_APIADDR = 'http://127.0.0.1:8080'
\ No newline at end of file
diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs
new file mode 100644
index 0000000..d6c9537
--- /dev/null
+++ b/frontend/.eslintrc.cjs
@@ -0,0 +1,18 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:react-hooks/recommended',
+ ],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parser: '@typescript-eslint/parser',
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+}
diff --git a/frontend/.gitignore b/frontend/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/frontend/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/frontend/README.md b/frontend/README.md
new file mode 100644
index 0000000..1ebe379
--- /dev/null
+++ b/frontend/README.md
@@ -0,0 +1,27 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+ parserOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ project: ['./tsconfig.json', './tsconfig.node.json'],
+ tsconfigRootDir: __dirname,
+ },
+```
+
+- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
+- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
diff --git a/frontend/index.html b/frontend/index.html
new file mode 100644
index 0000000..d3c14a6
--- /dev/null
+++ b/frontend/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ 皮肤站
+
+
+
+
+
+
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 0000000..32a53fb
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "@xmdhs/authlib-skin",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@emotion/react": "^11.13.3",
+ "@emotion/styled": "^11.13.0",
+ "@marsidev/react-turnstile": "^1.0.2",
+ "@mui/icons-material": "^6.1.7",
+ "@mui/material": "^6.1.7",
+ "ahooks": "^3.8.1",
+ "immer": "^10.1.1",
+ "jotai": "^2.10.2",
+ "mui-file-input": "^6.0.0",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "react-router-dom": "^6.28.0",
+ "skinview3d": "^3.1.0",
+ "tilg": "^0.1.1"
+ },
+ "devDependencies": {
+ "@types/node": "^20.17.6",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
+ "@vitejs/plugin-legacy": "^5.4.3",
+ "@vitejs/plugin-react": "^4.3.3",
+ "@vitejs/plugin-react-swc": "^3.7.1",
+ "terser": "^5.36.0",
+ "typescript": "^5.6.3",
+ "vite": "^5.4.11"
+ }
+}
\ No newline at end of file
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
new file mode 100644
index 0000000..ff61268
--- /dev/null
+++ b/frontend/pnpm-lock.yaml
@@ -0,0 +1,3195 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@emotion/react':
+ specifier: ^11.13.3
+ version: 11.13.3(@types/react@18.3.12)(react@18.3.1)
+ '@emotion/styled':
+ specifier: ^11.13.0
+ version: 11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+ '@marsidev/react-turnstile':
+ specifier: ^1.0.2
+ version: 1.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@mui/icons-material':
+ specifier: ^6.1.7
+ version: 6.1.7(@mui/material@6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+ '@mui/material':
+ specifier: ^6.1.7
+ version: 6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ ahooks:
+ specifier: ^3.8.1
+ version: 3.8.1(react@18.3.1)
+ immer:
+ specifier: ^10.1.1
+ version: 10.1.1
+ jotai:
+ specifier: ^2.10.2
+ version: 2.10.2(@types/react@18.3.12)(react@18.3.1)
+ mui-file-input:
+ specifier: ^6.0.0
+ version: 6.0.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/material@6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react:
+ specifier: ^18.3.1
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.3.1
+ version: 18.3.1(react@18.3.1)
+ react-router-dom:
+ specifier: ^6.28.0
+ version: 6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ skinview3d:
+ specifier: ^3.1.0
+ version: 3.1.0
+ tilg:
+ specifier: ^0.1.1
+ version: 0.1.1(react@18.3.1)
+ devDependencies:
+ '@types/node':
+ specifier: ^20.17.6
+ version: 20.17.6
+ '@types/react':
+ specifier: ^18.3.12
+ version: 18.3.12
+ '@types/react-dom':
+ specifier: ^18.3.1
+ version: 18.3.1
+ '@vitejs/plugin-legacy':
+ specifier: ^5.4.3
+ version: 5.4.3(terser@5.36.0)(vite@5.4.11(@types/node@20.17.6)(terser@5.36.0))
+ '@vitejs/plugin-react':
+ specifier: ^4.3.3
+ version: 4.3.3(vite@5.4.11(@types/node@20.17.6)(terser@5.36.0))
+ '@vitejs/plugin-react-swc':
+ specifier: ^3.7.1
+ version: 3.7.1(vite@5.4.11(@types/node@20.17.6)(terser@5.36.0))
+ terser:
+ specifier: ^5.36.0
+ version: 5.36.0
+ typescript:
+ specifier: ^5.6.3
+ version: 5.6.3
+ vite:
+ specifier: ^5.4.11
+ version: 5.4.11(@types/node@20.17.6)(terser@5.36.0)
+
+packages:
+
+ '@ampproject/remapping@2.3.0':
+ resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
+ engines: {node: '>=6.0.0'}
+
+ '@babel/code-frame@7.26.2':
+ resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.26.2':
+ resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.26.0':
+ resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.26.2':
+ resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-annotate-as-pure@7.25.9':
+ resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-builder-binary-assignment-operator-visitor@7.25.9':
+ resolution: {integrity: sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.25.9':
+ resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-create-class-features-plugin@7.25.9':
+ resolution: {integrity: sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-create-regexp-features-plugin@7.25.9':
+ resolution: {integrity: sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-define-polyfill-provider@0.6.3':
+ resolution: {integrity: sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
+ '@babel/helper-member-expression-to-functions@7.25.9':
+ resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.25.9':
+ resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.26.0':
+ resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-optimise-call-expression@7.25.9':
+ resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-plugin-utils@7.25.9':
+ resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-remap-async-to-generator@7.25.9':
+ resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-replace-supers@7.25.9':
+ resolution: {integrity: sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-simple-access@7.25.9':
+ resolution: {integrity: sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-skip-transparent-expression-wrappers@7.25.9':
+ resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-string-parser@7.25.9':
+ resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.25.9':
+ resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.25.9':
+ resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-wrap-function@7.25.9':
+ resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.26.0':
+ resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.26.2':
+ resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9':
+ resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9':
+ resolution: {integrity: sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9':
+ resolution: {integrity: sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9':
+ resolution: {integrity: sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.13.0
+
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9':
+ resolution: {integrity: sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2':
+ resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-import-assertions@7.26.0':
+ resolution: {integrity: sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-import-attributes@7.26.0':
+ resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-unicode-sets-regex@7.18.6':
+ resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-transform-arrow-functions@7.25.9':
+ resolution: {integrity: sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-async-generator-functions@7.25.9':
+ resolution: {integrity: sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-async-to-generator@7.25.9':
+ resolution: {integrity: sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-block-scoped-functions@7.25.9':
+ resolution: {integrity: sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-block-scoping@7.25.9':
+ resolution: {integrity: sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-class-properties@7.25.9':
+ resolution: {integrity: sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-class-static-block@7.26.0':
+ resolution: {integrity: sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.12.0
+
+ '@babel/plugin-transform-classes@7.25.9':
+ resolution: {integrity: sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-computed-properties@7.25.9':
+ resolution: {integrity: sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-destructuring@7.25.9':
+ resolution: {integrity: sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-dotall-regex@7.25.9':
+ resolution: {integrity: sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-duplicate-keys@7.25.9':
+ resolution: {integrity: sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9':
+ resolution: {integrity: sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-transform-dynamic-import@7.25.9':
+ resolution: {integrity: sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-exponentiation-operator@7.25.9':
+ resolution: {integrity: sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-export-namespace-from@7.25.9':
+ resolution: {integrity: sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-for-of@7.25.9':
+ resolution: {integrity: sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-function-name@7.25.9':
+ resolution: {integrity: sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-json-strings@7.25.9':
+ resolution: {integrity: sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-literals@7.25.9':
+ resolution: {integrity: sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-logical-assignment-operators@7.25.9':
+ resolution: {integrity: sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-member-expression-literals@7.25.9':
+ resolution: {integrity: sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-modules-amd@7.25.9':
+ resolution: {integrity: sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-modules-commonjs@7.25.9':
+ resolution: {integrity: sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-modules-systemjs@7.25.9':
+ resolution: {integrity: sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-modules-umd@7.25.9':
+ resolution: {integrity: sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-named-capturing-groups-regex@7.25.9':
+ resolution: {integrity: sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-transform-new-target@7.25.9':
+ resolution: {integrity: sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-nullish-coalescing-operator@7.25.9':
+ resolution: {integrity: sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-numeric-separator@7.25.9':
+ resolution: {integrity: sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-object-rest-spread@7.25.9':
+ resolution: {integrity: sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-object-super@7.25.9':
+ resolution: {integrity: sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-optional-catch-binding@7.25.9':
+ resolution: {integrity: sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-optional-chaining@7.25.9':
+ resolution: {integrity: sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-parameters@7.25.9':
+ resolution: {integrity: sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-private-methods@7.25.9':
+ resolution: {integrity: sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-private-property-in-object@7.25.9':
+ resolution: {integrity: sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-property-literals@7.25.9':
+ resolution: {integrity: sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-self@7.25.9':
+ resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-source@7.25.9':
+ resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-regenerator@7.25.9':
+ resolution: {integrity: sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-regexp-modifiers@7.26.0':
+ resolution: {integrity: sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/plugin-transform-reserved-words@7.25.9':
+ resolution: {integrity: sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-shorthand-properties@7.25.9':
+ resolution: {integrity: sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-spread@7.25.9':
+ resolution: {integrity: sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-sticky-regex@7.25.9':
+ resolution: {integrity: sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-template-literals@7.25.9':
+ resolution: {integrity: sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-typeof-symbol@7.25.9':
+ resolution: {integrity: sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-unicode-escapes@7.25.9':
+ resolution: {integrity: sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-unicode-property-regex@7.25.9':
+ resolution: {integrity: sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-unicode-regex@7.25.9':
+ resolution: {integrity: sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-unicode-sets-regex@7.25.9':
+ resolution: {integrity: sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/preset-env@7.26.0':
+ resolution: {integrity: sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/preset-modules@0.1.6-no-external-plugins':
+ resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0
+
+ '@babel/runtime@7.26.0':
+ resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/template@7.25.9':
+ resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.25.9':
+ resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.26.0':
+ resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==}
+ engines: {node: '>=6.9.0'}
+
+ '@emotion/babel-plugin@11.12.0':
+ resolution: {integrity: sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==}
+
+ '@emotion/cache@11.13.1':
+ resolution: {integrity: sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==}
+
+ '@emotion/hash@0.9.2':
+ resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==}
+
+ '@emotion/is-prop-valid@1.3.1':
+ resolution: {integrity: sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==}
+
+ '@emotion/memoize@0.9.0':
+ resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==}
+
+ '@emotion/react@11.13.3':
+ resolution: {integrity: sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: '>=16.8.0'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@emotion/serialize@1.3.2':
+ resolution: {integrity: sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==}
+
+ '@emotion/sheet@1.4.0':
+ resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==}
+
+ '@emotion/styled@11.13.0':
+ resolution: {integrity: sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==}
+ peerDependencies:
+ '@emotion/react': ^11.0.0-rc.0
+ '@types/react': '*'
+ react: '>=16.8.0'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@emotion/unitless@0.10.0':
+ resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==}
+
+ '@emotion/use-insertion-effect-with-fallbacks@1.1.0':
+ resolution: {integrity: sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==}
+ peerDependencies:
+ react: '>=16.8.0'
+
+ '@emotion/utils@1.4.1':
+ resolution: {integrity: sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==}
+
+ '@emotion/weak-memoize@0.4.0':
+ resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==}
+
+ '@esbuild/aix-ppc64@0.21.5':
+ resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.21.5':
+ resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.21.5':
+ resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.21.5':
+ resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.21.5':
+ resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.21.5':
+ resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.21.5':
+ resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.21.5':
+ resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.21.5':
+ resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.21.5':
+ resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.21.5':
+ resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.21.5':
+ resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.21.5':
+ resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.21.5':
+ resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.21.5':
+ resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.21.5':
+ resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.21.5':
+ resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-x64@0.21.5':
+ resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-x64@0.21.5':
+ resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/sunos-x64@0.21.5':
+ resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.21.5':
+ resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.21.5':
+ resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.21.5':
+ resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
+ '@jridgewell/gen-mapping@0.3.5':
+ resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/set-array@1.2.1':
+ resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/source-map@0.3.6':
+ resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==}
+
+ '@jridgewell/sourcemap-codec@1.5.0':
+ resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
+
+ '@jridgewell/trace-mapping@0.3.25':
+ resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+
+ '@marsidev/react-turnstile@1.0.2':
+ resolution: {integrity: sha512-YkCtJVaCzZ1kcmhPsiFTmTXVughoNzEMRsNHcmTG0K5OdbCQfAG67Q6d5Ze+A72vrHbvVZkvcLgUbldeGcbRjQ==}
+ peerDependencies:
+ react: ^17.0.2 || ^18.0.0
+ react-dom: ^17.0.2 || ^18.0.0
+
+ '@mui/core-downloads-tracker@6.1.7':
+ resolution: {integrity: sha512-POuIBi80BZBogQkG4PQKIGwy4QFwB+kOr+OI4k7Znh7LqMAIhwB9OC00l6M+w1GrZJYj3T8R5WX8G6QAIvoVEw==}
+
+ '@mui/icons-material@6.1.7':
+ resolution: {integrity: sha512-RGzkeHNArIVy5ZQ12bq/8VYNeICEyngngsFskTJ/2hYKhIeIII3iRGtaZaSvLpXh7h3Fg3VKTulT+QU0w5K4XQ==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ '@mui/material': ^6.1.7
+ '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
+ react: ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@mui/material@6.1.7':
+ resolution: {integrity: sha512-KsjujQL/A2hLd1PV3QboF+W6SSL5QqH6ZlSuQoeYz9r69+TnyBFIevbYLxdjJcJmGBjigL5pfpn7hTGop+vhSg==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ '@emotion/react': ^11.5.0
+ '@emotion/styled': ^11.3.0
+ '@mui/material-pigment-css': ^6.1.7
+ '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
+ react: ^17.0.0 || ^18.0.0 || ^19.0.0
+ react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@emotion/react':
+ optional: true
+ '@emotion/styled':
+ optional: true
+ '@mui/material-pigment-css':
+ optional: true
+ '@types/react':
+ optional: true
+
+ '@mui/private-theming@6.1.7':
+ resolution: {integrity: sha512-uLbfUSsug5K0LVkv0PI6Flste3le8+6WSL2omdTiYde93P89Qr7pKr8TA6d2yXfr+Bm+SvD8/fGnkaRwFkryuQ==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
+ react: ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@mui/styled-engine@6.1.7':
+ resolution: {integrity: sha512-Ou4CxN7MQmwrfG1Pu6EYjPgPChQXxPDJrwgizLXlRPOad5qAq4gYXRuzrGQ2DfGjjwmJhjI8T6A0SeapAZPGig==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ '@emotion/react': ^11.4.1
+ '@emotion/styled': ^11.3.0
+ react: ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@emotion/react':
+ optional: true
+ '@emotion/styled':
+ optional: true
+
+ '@mui/system@6.1.7':
+ resolution: {integrity: sha512-qbMGgcC/FodpuRSfjXlEDdbNQaW++eATh0vNBcPUv2/YXSpReoOpoT9FhogxEBNks+aQViDXBRZKh6HX2fVmwg==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ '@emotion/react': ^11.5.0
+ '@emotion/styled': ^11.3.0
+ '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
+ react: ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@emotion/react':
+ optional: true
+ '@emotion/styled':
+ optional: true
+ '@types/react':
+ optional: true
+
+ '@mui/types@7.2.19':
+ resolution: {integrity: sha512-6XpZEM/Q3epK9RN8ENoXuygnqUQxE+siN/6rGRi2iwJPgBUR25mphYQ9ZI87plGh58YoZ5pp40bFvKYOCDJ3tA==}
+ peerDependencies:
+ '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@mui/utils@6.1.7':
+ resolution: {integrity: sha512-Gr7cRZxBoZ0BIa3Xqf/2YaUrBLyNPJvXPQH3OsD9WMZukI/TutibbQBVqLYpgqJn8pKSjbD50Yq2auG0wI1xOw==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
+ react: ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@popperjs/core@2.11.8':
+ resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
+
+ '@remix-run/router@1.21.0':
+ resolution: {integrity: sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==}
+ engines: {node: '>=14.0.0'}
+
+ '@rollup/rollup-android-arm-eabi@4.27.2':
+ resolution: {integrity: sha512-Tj+j7Pyzd15wAdSJswvs5CJzJNV+qqSUcr/aCD+jpQSBtXvGnV0pnrjoc8zFTe9fcKCatkpFpOO7yAzpO998HA==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.27.2':
+ resolution: {integrity: sha512-xsPeJgh2ThBpUqlLgRfiVYBEf/P1nWlWvReG+aBWfNv3XEBpa6ZCmxSVnxJgLgkNz4IbxpLy64h2gCmAAQLneQ==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.27.2':
+ resolution: {integrity: sha512-KnXU4m9MywuZFedL35Z3PuwiTSn/yqRIhrEA9j+7OSkji39NzVkgxuxTYg5F8ryGysq4iFADaU5osSizMXhU2A==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.27.2':
+ resolution: {integrity: sha512-Hj77A3yTvUeCIx/Vi+4d4IbYhyTwtHj07lVzUgpUq9YpJSEiGJj4vXMKwzJ3w5zp5v3PFvpJNgc/J31smZey6g==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.27.2':
+ resolution: {integrity: sha512-RjgKf5C3xbn8gxvCm5VgKZ4nn0pRAIe90J0/fdHUsgztd3+Zesb2lm2+r6uX4prV2eUByuxJNdt647/1KPRq5g==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.27.2':
+ resolution: {integrity: sha512-duq21FoXwQtuws+V9H6UZ+eCBc7fxSpMK1GQINKn3fAyd9DFYKPJNcUhdIKOrMFjLEJgQskoMoiuizMt+dl20g==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.27.2':
+ resolution: {integrity: sha512-6npqOKEPRZkLrMcvyC/32OzJ2srdPzCylJjiTJT2c0bwwSGm7nz2F9mNQ1WrAqCBZROcQn91Fno+khFhVijmFA==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.27.2':
+ resolution: {integrity: sha512-V9Xg6eXtgBtHq2jnuQwM/jr2mwe2EycnopO8cbOvpzFuySCGtKlPCI3Hj9xup/pJK5Q0388qfZZy2DqV2J8ftw==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.27.2':
+ resolution: {integrity: sha512-uCFX9gtZJoQl2xDTpRdseYuNqyKkuMDtH6zSrBTA28yTfKyjN9hQ2B04N5ynR8ILCoSDOrG/Eg+J2TtJ1e/CSA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.27.2':
+ resolution: {integrity: sha512-/PU9P+7Rkz8JFYDHIi+xzHabOu9qEWR07L5nWLIUsvserrxegZExKCi2jhMZRd0ATdboKylu/K5yAXbp7fYFvA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.27.2':
+ resolution: {integrity: sha512-eCHmol/dT5odMYi/N0R0HC8V8QE40rEpkyje/ZAXJYNNoSfrObOvG/Mn+s1F/FJyB7co7UQZZf6FuWnN6a7f4g==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.27.2':
+ resolution: {integrity: sha512-DEP3Njr9/ADDln3kNi76PXonLMSSMiCir0VHXxmGSHxCxDfQ70oWjHcJGfiBugzaqmYdTC7Y+8Int6qbnxPBIQ==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.27.2':
+ resolution: {integrity: sha512-NHGo5i6IE/PtEPh5m0yw5OmPMpesFnzMIS/lzvN5vknnC1sXM5Z/id5VgcNPgpD+wHmIcuYYgW+Q53v+9s96lQ==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.27.2':
+ resolution: {integrity: sha512-PaW2DY5Tan+IFvNJGHDmUrORadbe/Ceh8tQxi8cmdQVCCYsLoQo2cuaSj+AU+YRX8M4ivS2vJ9UGaxfuNN7gmg==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.27.2':
+ resolution: {integrity: sha512-dOlWEMg2gI91Qx5I/HYqOD6iqlJspxLcS4Zlg3vjk1srE67z5T2Uz91yg/qA8sY0XcwQrFzWWiZhMNERylLrpQ==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-win32-arm64-msvc@4.27.2':
+ resolution: {integrity: sha512-euMIv/4x5Y2/ImlbGl88mwKNXDsvzbWUlT7DFky76z2keajCtcbAsN9LUdmk31hAoVmJJYSThgdA0EsPeTr1+w==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.27.2':
+ resolution: {integrity: sha512-RsnE6LQkUHlkC10RKngtHNLxb7scFykEbEwOFDjr3CeCMG+Rr+cKqlkKc2/wJ1u4u990urRHCbjz31x84PBrSQ==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.27.2':
+ resolution: {integrity: sha512-foJM5vv+z2KQmn7emYdDLyTbkoO5bkHZE1oth2tWbQNGW7mX32d46Hz6T0MqXdWS2vBZhaEtHqdy9WYwGfiliA==}
+ cpu: [x64]
+ os: [win32]
+
+ '@swc/core-darwin-arm64@1.9.1':
+ resolution: {integrity: sha512-2/ncHSCdAh5OHem1fMITrWEzzl97OdMK1PHc9CkxSJnphLjRubfxB5sbc5tDhcO68a5tVy+DxwaBgDec3PXnOg==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@swc/core-darwin-x64@1.9.1':
+ resolution: {integrity: sha512-4MDOFC5zmNqRJ9RGFOH95oYf27J9HniLVpB1pYm2gGeNHdl2QvDMtx2QTuMHQ6+OTn/3y1BHYuhBGp7d405oLA==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@swc/core-linux-arm-gnueabihf@1.9.1':
+ resolution: {integrity: sha512-eVW/BjRW8/HpLe3+1jRU7w7PdRLBgnEEYTkHJISU8805/EKT03xNZn6CfaBpKfeAloY4043hbGzE/NP9IahdpQ==}
+ engines: {node: '>=10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@swc/core-linux-arm64-gnu@1.9.1':
+ resolution: {integrity: sha512-8m3u1v8R8NgI/9+cHMkzk14w87blSy3OsQPWPfhOL+XPwhyLPvat+ahQJb2nZmltjTgkB4IbzKFSfbuA34LmNA==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@swc/core-linux-arm64-musl@1.9.1':
+ resolution: {integrity: sha512-hpT0sQAZnW8l02I289yeyFfT9llGO9PzKDxUq8pocKtioEHiElRqR53juCWoSmzuWi+6KX7zUJ0NKCBrc8pmDg==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@swc/core-linux-x64-gnu@1.9.1':
+ resolution: {integrity: sha512-sGFdpdAYusk/ropHiwtXom2JrdaKPxl8MqemRv6dvxZq1Gm/GdmOowxdXIPjCgBGMgoXVcgNviH6CgiO5q+UtA==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@swc/core-linux-x64-musl@1.9.1':
+ resolution: {integrity: sha512-YtNLNwIWs0Z2+XgBs6+LrCIGtfCDtNr4S4b6Q5HDOreEIGzSvhkef8eyBI5L+fJ2eGov4b7iEo61C4izDJS5RA==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@swc/core-win32-arm64-msvc@1.9.1':
+ resolution: {integrity: sha512-qSxD3uZW2vSiHqUt30vUi0PB92zDh9bjqh5YKpfhhVa7h1vt/xXhlid8yMvSNToTfzhRrTEffOAPUr7WVoyQUA==}
+ engines: {node: '>=10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@swc/core-win32-ia32-msvc@1.9.1':
+ resolution: {integrity: sha512-C3fPEwyX/WRPlX6zIToNykJuz1JkZX0sk8H1QH2vpnKuySUkt/Ur5K2FzLgSWzJdbfxstpgS151/es0VGAD+ZA==}
+ engines: {node: '>=10'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@swc/core-win32-x64-msvc@1.9.1':
+ resolution: {integrity: sha512-2XZ+U1AyVsOAXeH6WK1syDm7+gwTjA8fShs93WcbxnK7HV+NigDlvr4124CeJLTHyh3fMh1o7+CnQnaBJhlysQ==}
+ engines: {node: '>=10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@swc/core@1.9.1':
+ resolution: {integrity: sha512-OnPc+Kt5oy3xTvr/KCUOqE9ptJcWbyQgAUr1ydh9EmbBcmJTaO1kfQCxm/axzJi6sKeDTxL9rX5zvLOhoYIaQw==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ '@swc/helpers': '*'
+ peerDependenciesMeta:
+ '@swc/helpers':
+ optional: true
+
+ '@swc/counter@0.1.3':
+ resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
+
+ '@swc/types@0.1.14':
+ resolution: {integrity: sha512-PbSmTiYCN+GMrvfjrMo9bdY+f2COnwbdnoMw7rqU/PI5jXpKjxOGZ0qqZCImxnT81NkNsKnmEpvu+hRXLBeCJg==}
+
+ '@types/babel__core@7.20.5':
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+ '@types/babel__generator@7.6.8':
+ resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==}
+
+ '@types/babel__template@7.4.4':
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+ '@types/babel__traverse@7.20.6':
+ resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==}
+
+ '@types/estree@1.0.6':
+ resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
+
+ '@types/node@20.17.6':
+ resolution: {integrity: sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==}
+
+ '@types/parse-json@4.0.2':
+ resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
+
+ '@types/prop-types@15.7.13':
+ resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==}
+
+ '@types/react-dom@18.3.1':
+ resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==}
+
+ '@types/react-transition-group@4.4.11':
+ resolution: {integrity: sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==}
+
+ '@types/react@18.3.12':
+ resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==}
+
+ '@types/stats.js@0.17.3':
+ resolution: {integrity: sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==}
+
+ '@types/three@0.156.0':
+ resolution: {integrity: sha512-733bXDSRdlrxqOmQuOmfC1UBRuJ2pREPk8sWnx9MtIJEVDQMx8U0NQO5MVVaOrjzDPyLI+cFPim2X/ss9v0+LQ==}
+
+ '@types/webxr@0.5.20':
+ resolution: {integrity: sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==}
+
+ '@vitejs/plugin-legacy@5.4.3':
+ resolution: {integrity: sha512-wsyXK9mascyplcqvww1gA1xYiy29iRHfyciw+a0t7qRNdzX6PdfSWmOoCi74epr87DujM+5J+rnnSv+4PazqVg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ peerDependencies:
+ terser: ^5.4.0
+ vite: ^5.0.0
+
+ '@vitejs/plugin-react-swc@3.7.1':
+ resolution: {integrity: sha512-vgWOY0i1EROUK0Ctg1hwhtC3SdcDjZcdit4Ups4aPkDcB1jYhmo+RMYWY87cmXMhvtD5uf8lV89j2w16vkdSVg==}
+ peerDependencies:
+ vite: ^4 || ^5
+
+ '@vitejs/plugin-react@4.3.3':
+ resolution: {integrity: sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0
+
+ acorn@8.14.0:
+ resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ ahooks@3.8.1:
+ resolution: {integrity: sha512-JoP9+/RWO7MnI/uSKdvQ8WB10Y3oo1PjLv+4Sv4Vpm19Z86VUMdXh+RhWvMGxZZs06sq2p0xVtFk8Oh5ZObsoA==}
+ engines: {node: '>=8.0.0'}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+
+ babel-plugin-macros@3.1.0:
+ resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
+ engines: {node: '>=10', npm: '>=6'}
+
+ babel-plugin-polyfill-corejs2@0.4.12:
+ resolution: {integrity: sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
+ babel-plugin-polyfill-corejs3@0.10.6:
+ resolution: {integrity: sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
+ babel-plugin-polyfill-regenerator@0.6.3:
+ resolution: {integrity: sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+
+ browserslist-to-esbuild@2.1.1:
+ resolution: {integrity: sha512-KN+mty6C3e9AN8Z5dI1xeN15ExcRNeISoC3g7V0Kax/MMF9MSoYA2G7lkTTcVUFntiEjkpI0HNgqJC1NjdyNUw==}
+ engines: {node: '>=18'}
+ hasBin: true
+ peerDependencies:
+ browserslist: '*'
+
+ browserslist@4.24.2:
+ resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
+ buffer-from@1.1.2:
+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+
+ callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+
+ caniuse-lite@1.0.30001680:
+ resolution: {integrity: sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==}
+
+ clsx@2.1.1:
+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
+ engines: {node: '>=6'}
+
+ commander@2.20.3:
+ resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+
+ convert-source-map@1.9.0:
+ resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
+
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+ core-js-compat@3.39.0:
+ resolution: {integrity: sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==}
+
+ core-js@3.39.0:
+ resolution: {integrity: sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==}
+
+ cosmiconfig@7.1.0:
+ resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==}
+ engines: {node: '>=10'}
+
+ csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+ dayjs@1.11.13:
+ resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
+
+ debug@4.3.7:
+ resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ dom-helpers@5.2.1:
+ resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
+
+ electron-to-chromium@1.5.62:
+ resolution: {integrity: sha512-t8c+zLmJHa9dJy96yBZRXGQYoiCEnHYgFwn1asvSPZSUdVxnB62A4RASd7k41ytG3ErFBA0TpHlKg9D9SQBmLg==}
+
+ error-ex@1.3.2:
+ resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
+
+ esbuild@0.21.5:
+ resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+
+ esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+
+ fflate@0.6.10:
+ resolution: {integrity: sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==}
+
+ find-root@1.1.0:
+ resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
+ globals@11.12.0:
+ resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
+ engines: {node: '>=4'}
+
+ hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+
+ hoist-non-react-statics@3.3.2:
+ resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
+
+ immer@10.1.1:
+ resolution: {integrity: sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==}
+
+ import-fresh@3.3.0:
+ resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+ engines: {node: '>=6'}
+
+ intersection-observer@0.12.2:
+ resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==}
+
+ is-arrayish@0.2.1:
+ resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
+
+ is-core-module@2.15.1:
+ resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==}
+ engines: {node: '>= 0.4'}
+
+ jotai@2.10.2:
+ resolution: {integrity: sha512-DqsBTlRglIBviuJLfK6JxZzpd6vKfbuJ4IqRCz70RFEDeZf46Fcteb/FXxNr1UnoxR5oUy3oq7IE8BrEq0G5DQ==}
+ engines: {node: '>=12.20.0'}
+ peerDependencies:
+ '@types/react': '>=17.0.0'
+ react: '>=17.0.0'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ react:
+ optional: true
+
+ js-cookie@3.0.5:
+ resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==}
+ engines: {node: '>=14'}
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ jsesc@3.0.2:
+ resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ json-parse-even-better-errors@2.3.1:
+ resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
+
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
+ lodash.debounce@4.0.8:
+ resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
+
+ lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+ magic-string@0.30.12:
+ resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==}
+
+ meow@13.2.0:
+ resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==}
+ engines: {node: '>=18'}
+
+ meshoptimizer@0.18.1:
+ resolution: {integrity: sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ mui-file-input@6.0.0:
+ resolution: {integrity: sha512-obxuGvY2+SuafXUdKOq06jw/Ams3xPsYafkSb71wmnC2jz6k+DHeKomXlawqAUM7w6WbRy2J3mQ4yoRLZYMx3A==}
+ peerDependencies:
+ '@emotion/react': ^11.13.3
+ '@emotion/styled': ^11.13.0
+ '@mui/material': ^5.0.0 || ^6.0.0
+ '@types/react': ^18.0.0
+ react: ^18.0.0
+ react-dom: ^18.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ nanoid@3.3.7:
+ resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ node-releases@2.0.18:
+ resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+
+ parse-json@5.2.0:
+ resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
+ engines: {node: '>=8'}
+
+ path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+ path-type@4.0.0:
+ resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+ engines: {node: '>=8'}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ postcss@8.4.49:
+ resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ pretty-bytes@6.1.1:
+ resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
+ engines: {node: ^14.13.1 || >=16.0.0}
+
+ prop-types@15.8.1:
+ resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+
+ react-dom@18.3.1:
+ resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
+ peerDependencies:
+ react: ^18.3.1
+
+ react-fast-compare@3.2.2:
+ resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
+
+ react-is@16.13.1:
+ resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+
+ react-is@18.3.1:
+ resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+
+ react-refresh@0.14.2:
+ resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
+ engines: {node: '>=0.10.0'}
+
+ react-router-dom@6.28.0:
+ resolution: {integrity: sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ react: '>=16.8'
+ react-dom: '>=16.8'
+
+ react-router@6.28.0:
+ resolution: {integrity: sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ react: '>=16.8'
+
+ react-transition-group@4.4.5:
+ resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
+ peerDependencies:
+ react: '>=16.6.0'
+ react-dom: '>=16.6.0'
+
+ react@18.3.1:
+ resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
+ engines: {node: '>=0.10.0'}
+
+ regenerate-unicode-properties@10.2.0:
+ resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==}
+ engines: {node: '>=4'}
+
+ regenerate@1.4.2:
+ resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==}
+
+ regenerator-runtime@0.14.1:
+ resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
+
+ regenerator-transform@0.15.2:
+ resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==}
+
+ regexpu-core@6.1.1:
+ resolution: {integrity: sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==}
+ engines: {node: '>=4'}
+
+ regjsgen@0.8.0:
+ resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==}
+
+ regjsparser@0.11.2:
+ resolution: {integrity: sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==}
+ hasBin: true
+
+ resize-observer-polyfill@1.5.1:
+ resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
+
+ resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+
+ resolve@1.22.8:
+ resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+ hasBin: true
+
+ rollup@4.27.2:
+ resolution: {integrity: sha512-KreA+PzWmk2yaFmZVwe6GB2uBD86nXl86OsDkt1bJS9p3vqWuEQ6HnJJ+j/mZi/q0920P99/MVRlB4L3crpF5w==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ scheduler@0.23.2:
+ resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
+
+ screenfull@5.2.0:
+ resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==}
+ engines: {node: '>=0.10.0'}
+
+ semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+
+ skinview-utils@0.7.1:
+ resolution: {integrity: sha512-4eLrMqR526ehlZbsd8SuZ/CHpS9GiH0xUMoV+PYlJVi95ZFz5HJu7Spt5XYa72DRS7wgt5qquvHZf0XZJgmu9Q==}
+
+ skinview3d@3.1.0:
+ resolution: {integrity: sha512-L+HXXAP4qYjLcY3YHasXKie9KXQpv/mPTMxgLOEd+hVQRdQkPs5xdWaKuOmlZY8UnyZzecQM7yrWRzgT/e7HZw==}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ source-map-support@0.5.21:
+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+
+ source-map@0.5.7:
+ resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
+ engines: {node: '>=0.10.0'}
+
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
+ stylis@4.2.0:
+ resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==}
+
+ supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+
+ systemjs@6.15.1:
+ resolution: {integrity: sha512-Nk8c4lXvMB98MtbmjX7JwJRgJOL8fluecYCfCeYBznwmpOs8Bf15hLM6z4z71EDAhQVrQrI+wt1aLWSXZq+hXA==}
+
+ terser@5.36.0:
+ resolution: {integrity: sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ three@0.156.1:
+ resolution: {integrity: sha512-kP7H0FK9d/k6t/XvQ9FO6i+QrePoDcNhwl0I02+wmUJRNSLCUIDMcfObnzQvxb37/0Uc9TDT0T1HgsRRrO6SYQ==}
+
+ tilg@0.1.1:
+ resolution: {integrity: sha512-0uHyTAUM0tJL792LeviRPFkJtCbF6Za3/hbbnRmWGUaicOhbJ0IpvBViXiXTF7nk6R0L6vve2XLesQzn5jEVng==}
+ peerDependencies:
+ react: ^18.0.0 || ^17.0.0
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ typescript@5.6.3:
+ resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ undici-types@6.19.8:
+ resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
+
+ unicode-canonical-property-names-ecmascript@2.0.1:
+ resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==}
+ engines: {node: '>=4'}
+
+ unicode-match-property-ecmascript@2.0.0:
+ resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==}
+ engines: {node: '>=4'}
+
+ unicode-match-property-value-ecmascript@2.2.0:
+ resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==}
+ engines: {node: '>=4'}
+
+ unicode-property-aliases-ecmascript@2.1.0:
+ resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==}
+ engines: {node: '>=4'}
+
+ update-browserslist-db@1.1.1:
+ resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
+ vite@5.4.11:
+ resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
+ yaml@1.10.2:
+ resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
+ engines: {node: '>= 6'}
+
+snapshots:
+
+ '@ampproject/remapping@2.3.0':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.5
+ '@jridgewell/trace-mapping': 0.3.25
+
+ '@babel/code-frame@7.26.2':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.25.9
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.26.2': {}
+
+ '@babel/core@7.26.0':
+ dependencies:
+ '@ampproject/remapping': 2.3.0
+ '@babel/code-frame': 7.26.2
+ '@babel/generator': 7.26.2
+ '@babel/helper-compilation-targets': 7.25.9
+ '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
+ '@babel/helpers': 7.26.0
+ '@babel/parser': 7.26.2
+ '@babel/template': 7.25.9
+ '@babel/traverse': 7.25.9
+ '@babel/types': 7.26.0
+ convert-source-map: 2.0.0
+ debug: 4.3.7
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/generator@7.26.2':
+ dependencies:
+ '@babel/parser': 7.26.2
+ '@babel/types': 7.26.0
+ '@jridgewell/gen-mapping': 0.3.5
+ '@jridgewell/trace-mapping': 0.3.25
+ jsesc: 3.0.2
+
+ '@babel/helper-annotate-as-pure@7.25.9':
+ dependencies:
+ '@babel/types': 7.26.0
+
+ '@babel/helper-builder-binary-assignment-operator-visitor@7.25.9':
+ dependencies:
+ '@babel/traverse': 7.25.9
+ '@babel/types': 7.26.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-compilation-targets@7.25.9':
+ dependencies:
+ '@babel/compat-data': 7.26.2
+ '@babel/helper-validator-option': 7.25.9
+ browserslist: 4.24.2
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
+ '@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-annotate-as-pure': 7.25.9
+ '@babel/helper-member-expression-to-functions': 7.25.9
+ '@babel/helper-optimise-call-expression': 7.25.9
+ '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
+ '@babel/traverse': 7.25.9
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-create-regexp-features-plugin@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-annotate-as-pure': 7.25.9
+ regexpu-core: 6.1.1
+ semver: 6.3.1
+
+ '@babel/helper-define-polyfill-provider@0.6.3(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-compilation-targets': 7.25.9
+ '@babel/helper-plugin-utils': 7.25.9
+ debug: 4.3.7
+ lodash.debounce: 4.0.8
+ resolve: 1.22.8
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-member-expression-to-functions@7.25.9':
+ dependencies:
+ '@babel/traverse': 7.25.9
+ '@babel/types': 7.26.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-imports@7.25.9':
+ dependencies:
+ '@babel/traverse': 7.25.9
+ '@babel/types': 7.26.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-module-imports': 7.25.9
+ '@babel/helper-validator-identifier': 7.25.9
+ '@babel/traverse': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-optimise-call-expression@7.25.9':
+ dependencies:
+ '@babel/types': 7.26.0
+
+ '@babel/helper-plugin-utils@7.25.9': {}
+
+ '@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-annotate-as-pure': 7.25.9
+ '@babel/helper-wrap-function': 7.25.9
+ '@babel/traverse': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-replace-supers@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-member-expression-to-functions': 7.25.9
+ '@babel/helper-optimise-call-expression': 7.25.9
+ '@babel/traverse': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-simple-access@7.25.9':
+ dependencies:
+ '@babel/traverse': 7.25.9
+ '@babel/types': 7.26.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-skip-transparent-expression-wrappers@7.25.9':
+ dependencies:
+ '@babel/traverse': 7.25.9
+ '@babel/types': 7.26.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-string-parser@7.25.9': {}
+
+ '@babel/helper-validator-identifier@7.25.9': {}
+
+ '@babel/helper-validator-option@7.25.9': {}
+
+ '@babel/helper-wrap-function@7.25.9':
+ dependencies:
+ '@babel/template': 7.25.9
+ '@babel/traverse': 7.25.9
+ '@babel/types': 7.26.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helpers@7.26.0':
+ dependencies:
+ '@babel/template': 7.25.9
+ '@babel/types': 7.26.0
+
+ '@babel/parser@7.26.2':
+ dependencies:
+ '@babel/types': 7.26.0
+
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/traverse': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
+ '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/traverse': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+
+ '@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-async-generator-functions@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0)
+ '@babel/traverse': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-module-imports': 7.25.9
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-block-scoped-functions@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-class-static-block@7.26.0(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-classes@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-annotate-as-pure': 7.25.9
+ '@babel/helper-compilation-targets': 7.25.9
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0)
+ '@babel/traverse': 7.25.9
+ globals: 11.12.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/template': 7.25.9
+
+ '@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-exponentiation-operator@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-builder-binary-assignment-operator-visitor': 7.25.9
+ '@babel/helper-plugin-utils': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-for-of@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-compilation-targets': 7.25.9
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/traverse': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-modules-commonjs@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/helper-simple-access': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/helper-validator-identifier': 7.25.9
+ '@babel/traverse': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-nullish-coalescing-operator@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-compilation-targets': 7.25.9
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0)
+
+ '@babel/plugin-transform-object-super@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-parameters@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-annotate-as-pure': 7.25.9
+ '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+ regenerator-transform: 0.15.2
+
+ '@babel/plugin-transform-regexp-modifiers@7.26.0(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-template-literals@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-typeof-symbol@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
+ '@babel/helper-plugin-utils': 7.25.9
+
+ '@babel/preset-env@7.26.0(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/compat-data': 7.26.2
+ '@babel/core': 7.26.0
+ '@babel/helper-compilation-targets': 7.25.9
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/helper-validator-option': 7.25.9
+ '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0)
+ '@babel/plugin-syntax-import-assertions': 7.26.0(@babel/core@7.26.0)
+ '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.0)
+ '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.0)
+ '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-async-generator-functions': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-block-scoped-functions': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.0)
+ '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-dotall-regex': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-duplicate-keys': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-dynamic-import': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-exponentiation-operator': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-for-of': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-json-strings': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-member-expression-literals': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-modules-amd': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-modules-commonjs': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-modules-systemjs': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-nullish-coalescing-operator': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-regenerator': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-regexp-modifiers': 7.26.0(@babel/core@7.26.0)
+ '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-template-literals': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-typeof-symbol': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.26.0)
+ '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.0)
+ babel-plugin-polyfill-corejs2: 0.4.12(@babel/core@7.26.0)
+ babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.26.0)
+ babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.0)
+ core-js-compat: 3.39.0
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.0)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-plugin-utils': 7.25.9
+ '@babel/types': 7.26.0
+ esutils: 2.0.3
+
+ '@babel/runtime@7.26.0':
+ dependencies:
+ regenerator-runtime: 0.14.1
+
+ '@babel/template@7.25.9':
+ dependencies:
+ '@babel/code-frame': 7.26.2
+ '@babel/parser': 7.26.2
+ '@babel/types': 7.26.0
+
+ '@babel/traverse@7.25.9':
+ dependencies:
+ '@babel/code-frame': 7.26.2
+ '@babel/generator': 7.26.2
+ '@babel/parser': 7.26.2
+ '@babel/template': 7.25.9
+ '@babel/types': 7.26.0
+ debug: 4.3.7
+ globals: 11.12.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/types@7.26.0':
+ dependencies:
+ '@babel/helper-string-parser': 7.25.9
+ '@babel/helper-validator-identifier': 7.25.9
+
+ '@emotion/babel-plugin@11.12.0':
+ dependencies:
+ '@babel/helper-module-imports': 7.25.9
+ '@babel/runtime': 7.26.0
+ '@emotion/hash': 0.9.2
+ '@emotion/memoize': 0.9.0
+ '@emotion/serialize': 1.3.2
+ babel-plugin-macros: 3.1.0
+ convert-source-map: 1.9.0
+ escape-string-regexp: 4.0.0
+ find-root: 1.1.0
+ source-map: 0.5.7
+ stylis: 4.2.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@emotion/cache@11.13.1':
+ dependencies:
+ '@emotion/memoize': 0.9.0
+ '@emotion/sheet': 1.4.0
+ '@emotion/utils': 1.4.1
+ '@emotion/weak-memoize': 0.4.0
+ stylis: 4.2.0
+
+ '@emotion/hash@0.9.2': {}
+
+ '@emotion/is-prop-valid@1.3.1':
+ dependencies:
+ '@emotion/memoize': 0.9.0
+
+ '@emotion/memoize@0.9.0': {}
+
+ '@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1)':
+ dependencies:
+ '@babel/runtime': 7.26.0
+ '@emotion/babel-plugin': 11.12.0
+ '@emotion/cache': 11.13.1
+ '@emotion/serialize': 1.3.2
+ '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1)
+ '@emotion/utils': 1.4.1
+ '@emotion/weak-memoize': 0.4.0
+ hoist-non-react-statics: 3.3.2
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.12
+ transitivePeerDependencies:
+ - supports-color
+
+ '@emotion/serialize@1.3.2':
+ dependencies:
+ '@emotion/hash': 0.9.2
+ '@emotion/memoize': 0.9.0
+ '@emotion/unitless': 0.10.0
+ '@emotion/utils': 1.4.1
+ csstype: 3.1.3
+
+ '@emotion/sheet@1.4.0': {}
+
+ '@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)':
+ dependencies:
+ '@babel/runtime': 7.26.0
+ '@emotion/babel-plugin': 11.12.0
+ '@emotion/is-prop-valid': 1.3.1
+ '@emotion/react': 11.13.3(@types/react@18.3.12)(react@18.3.1)
+ '@emotion/serialize': 1.3.2
+ '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1)
+ '@emotion/utils': 1.4.1
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.12
+ transitivePeerDependencies:
+ - supports-color
+
+ '@emotion/unitless@0.10.0': {}
+
+ '@emotion/use-insertion-effect-with-fallbacks@1.1.0(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+
+ '@emotion/utils@1.4.1': {}
+
+ '@emotion/weak-memoize@0.4.0': {}
+
+ '@esbuild/aix-ppc64@0.21.5':
+ optional: true
+
+ '@esbuild/android-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/android-arm@0.21.5':
+ optional: true
+
+ '@esbuild/android-x64@0.21.5':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/darwin-x64@0.21.5':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-arm@0.21.5':
+ optional: true
+
+ '@esbuild/linux-ia32@0.21.5':
+ optional: true
+
+ '@esbuild/linux-loong64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.21.5':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-s390x@0.21.5':
+ optional: true
+
+ '@esbuild/linux-x64@0.21.5':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/sunos-x64@0.21.5':
+ optional: true
+
+ '@esbuild/win32-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/win32-ia32@0.21.5':
+ optional: true
+
+ '@esbuild/win32-x64@0.21.5':
+ optional: true
+
+ '@jridgewell/gen-mapping@0.3.5':
+ dependencies:
+ '@jridgewell/set-array': 1.2.1
+ '@jridgewell/sourcemap-codec': 1.5.0
+ '@jridgewell/trace-mapping': 0.3.25
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/set-array@1.2.1': {}
+
+ '@jridgewell/source-map@0.3.6':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.5
+ '@jridgewell/trace-mapping': 0.3.25
+
+ '@jridgewell/sourcemap-codec@1.5.0': {}
+
+ '@jridgewell/trace-mapping@0.3.25':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.0
+
+ '@marsidev/react-turnstile@1.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
+ '@mui/core-downloads-tracker@6.1.7': {}
+
+ '@mui/icons-material@6.1.7(@mui/material@6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)':
+ dependencies:
+ '@babel/runtime': 7.26.0
+ '@mui/material': 6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.12
+
+ '@mui/material@6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@babel/runtime': 7.26.0
+ '@mui/core-downloads-tracker': 6.1.7
+ '@mui/system': 6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+ '@mui/types': 7.2.19(@types/react@18.3.12)
+ '@mui/utils': 6.1.7(@types/react@18.3.12)(react@18.3.1)
+ '@popperjs/core': 2.11.8
+ '@types/react-transition-group': 4.4.11
+ clsx: 2.1.1
+ csstype: 3.1.3
+ prop-types: 15.8.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-is: 18.3.1
+ react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ optionalDependencies:
+ '@emotion/react': 11.13.3(@types/react@18.3.12)(react@18.3.1)
+ '@emotion/styled': 11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+ '@types/react': 18.3.12
+
+ '@mui/private-theming@6.1.7(@types/react@18.3.12)(react@18.3.1)':
+ dependencies:
+ '@babel/runtime': 7.26.0
+ '@mui/utils': 6.1.7(@types/react@18.3.12)(react@18.3.1)
+ prop-types: 15.8.1
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.12
+
+ '@mui/styled-engine@6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@babel/runtime': 7.26.0
+ '@emotion/cache': 11.13.1
+ '@emotion/serialize': 1.3.2
+ '@emotion/sheet': 1.4.0
+ csstype: 3.1.3
+ prop-types: 15.8.1
+ react: 18.3.1
+ optionalDependencies:
+ '@emotion/react': 11.13.3(@types/react@18.3.12)(react@18.3.1)
+ '@emotion/styled': 11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+
+ '@mui/system@6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)':
+ dependencies:
+ '@babel/runtime': 7.26.0
+ '@mui/private-theming': 6.1.7(@types/react@18.3.12)(react@18.3.1)
+ '@mui/styled-engine': 6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1)
+ '@mui/types': 7.2.19(@types/react@18.3.12)
+ '@mui/utils': 6.1.7(@types/react@18.3.12)(react@18.3.1)
+ clsx: 2.1.1
+ csstype: 3.1.3
+ prop-types: 15.8.1
+ react: 18.3.1
+ optionalDependencies:
+ '@emotion/react': 11.13.3(@types/react@18.3.12)(react@18.3.1)
+ '@emotion/styled': 11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+ '@types/react': 18.3.12
+
+ '@mui/types@7.2.19(@types/react@18.3.12)':
+ optionalDependencies:
+ '@types/react': 18.3.12
+
+ '@mui/utils@6.1.7(@types/react@18.3.12)(react@18.3.1)':
+ dependencies:
+ '@babel/runtime': 7.26.0
+ '@mui/types': 7.2.19(@types/react@18.3.12)
+ '@types/prop-types': 15.7.13
+ clsx: 2.1.1
+ prop-types: 15.8.1
+ react: 18.3.1
+ react-is: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.12
+
+ '@popperjs/core@2.11.8': {}
+
+ '@remix-run/router@1.21.0': {}
+
+ '@rollup/rollup-android-arm-eabi@4.27.2':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.27.2':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.27.2':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.27.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.27.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.27.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.27.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.27.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.27.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.27.2':
+ optional: true
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.27.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.27.2':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.27.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.27.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.27.2':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.27.2':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.27.2':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.27.2':
+ optional: true
+
+ '@swc/core-darwin-arm64@1.9.1':
+ optional: true
+
+ '@swc/core-darwin-x64@1.9.1':
+ optional: true
+
+ '@swc/core-linux-arm-gnueabihf@1.9.1':
+ optional: true
+
+ '@swc/core-linux-arm64-gnu@1.9.1':
+ optional: true
+
+ '@swc/core-linux-arm64-musl@1.9.1':
+ optional: true
+
+ '@swc/core-linux-x64-gnu@1.9.1':
+ optional: true
+
+ '@swc/core-linux-x64-musl@1.9.1':
+ optional: true
+
+ '@swc/core-win32-arm64-msvc@1.9.1':
+ optional: true
+
+ '@swc/core-win32-ia32-msvc@1.9.1':
+ optional: true
+
+ '@swc/core-win32-x64-msvc@1.9.1':
+ optional: true
+
+ '@swc/core@1.9.1':
+ dependencies:
+ '@swc/counter': 0.1.3
+ '@swc/types': 0.1.14
+ optionalDependencies:
+ '@swc/core-darwin-arm64': 1.9.1
+ '@swc/core-darwin-x64': 1.9.1
+ '@swc/core-linux-arm-gnueabihf': 1.9.1
+ '@swc/core-linux-arm64-gnu': 1.9.1
+ '@swc/core-linux-arm64-musl': 1.9.1
+ '@swc/core-linux-x64-gnu': 1.9.1
+ '@swc/core-linux-x64-musl': 1.9.1
+ '@swc/core-win32-arm64-msvc': 1.9.1
+ '@swc/core-win32-ia32-msvc': 1.9.1
+ '@swc/core-win32-x64-msvc': 1.9.1
+
+ '@swc/counter@0.1.3': {}
+
+ '@swc/types@0.1.14':
+ dependencies:
+ '@swc/counter': 0.1.3
+
+ '@types/babel__core@7.20.5':
+ dependencies:
+ '@babel/parser': 7.26.2
+ '@babel/types': 7.26.0
+ '@types/babel__generator': 7.6.8
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.20.6
+
+ '@types/babel__generator@7.6.8':
+ dependencies:
+ '@babel/types': 7.26.0
+
+ '@types/babel__template@7.4.4':
+ dependencies:
+ '@babel/parser': 7.26.2
+ '@babel/types': 7.26.0
+
+ '@types/babel__traverse@7.20.6':
+ dependencies:
+ '@babel/types': 7.26.0
+
+ '@types/estree@1.0.6': {}
+
+ '@types/node@20.17.6':
+ dependencies:
+ undici-types: 6.19.8
+
+ '@types/parse-json@4.0.2': {}
+
+ '@types/prop-types@15.7.13': {}
+
+ '@types/react-dom@18.3.1':
+ dependencies:
+ '@types/react': 18.3.12
+
+ '@types/react-transition-group@4.4.11':
+ dependencies:
+ '@types/react': 18.3.12
+
+ '@types/react@18.3.12':
+ dependencies:
+ '@types/prop-types': 15.7.13
+ csstype: 3.1.3
+
+ '@types/stats.js@0.17.3': {}
+
+ '@types/three@0.156.0':
+ dependencies:
+ '@types/stats.js': 0.17.3
+ '@types/webxr': 0.5.20
+ fflate: 0.6.10
+ meshoptimizer: 0.18.1
+
+ '@types/webxr@0.5.20': {}
+
+ '@vitejs/plugin-legacy@5.4.3(terser@5.36.0)(vite@5.4.11(@types/node@20.17.6)(terser@5.36.0))':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/preset-env': 7.26.0(@babel/core@7.26.0)
+ browserslist: 4.24.2
+ browserslist-to-esbuild: 2.1.1(browserslist@4.24.2)
+ core-js: 3.39.0
+ magic-string: 0.30.12
+ regenerator-runtime: 0.14.1
+ systemjs: 6.15.1
+ terser: 5.36.0
+ vite: 5.4.11(@types/node@20.17.6)(terser@5.36.0)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@vitejs/plugin-react-swc@3.7.1(vite@5.4.11(@types/node@20.17.6)(terser@5.36.0))':
+ dependencies:
+ '@swc/core': 1.9.1
+ vite: 5.4.11(@types/node@20.17.6)(terser@5.36.0)
+ transitivePeerDependencies:
+ - '@swc/helpers'
+
+ '@vitejs/plugin-react@4.3.3(vite@5.4.11(@types/node@20.17.6)(terser@5.36.0))':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0)
+ '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0)
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.14.2
+ vite: 5.4.11(@types/node@20.17.6)(terser@5.36.0)
+ transitivePeerDependencies:
+ - supports-color
+
+ acorn@8.14.0: {}
+
+ ahooks@3.8.1(react@18.3.1):
+ dependencies:
+ '@babel/runtime': 7.26.0
+ dayjs: 1.11.13
+ intersection-observer: 0.12.2
+ js-cookie: 3.0.5
+ lodash: 4.17.21
+ react: 18.3.1
+ react-fast-compare: 3.2.2
+ resize-observer-polyfill: 1.5.1
+ screenfull: 5.2.0
+ tslib: 2.8.1
+
+ babel-plugin-macros@3.1.0:
+ dependencies:
+ '@babel/runtime': 7.26.0
+ cosmiconfig: 7.1.0
+ resolve: 1.22.8
+
+ babel-plugin-polyfill-corejs2@0.4.12(@babel/core@7.26.0):
+ dependencies:
+ '@babel/compat-data': 7.26.2
+ '@babel/core': 7.26.0
+ '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.0)
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.26.0):
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.0)
+ core-js-compat: 3.39.0
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-polyfill-regenerator@0.6.3(@babel/core@7.26.0):
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.0)
+ transitivePeerDependencies:
+ - supports-color
+
+ browserslist-to-esbuild@2.1.1(browserslist@4.24.2):
+ dependencies:
+ browserslist: 4.24.2
+ meow: 13.2.0
+
+ browserslist@4.24.2:
+ dependencies:
+ caniuse-lite: 1.0.30001680
+ electron-to-chromium: 1.5.62
+ node-releases: 2.0.18
+ update-browserslist-db: 1.1.1(browserslist@4.24.2)
+
+ buffer-from@1.1.2: {}
+
+ callsites@3.1.0: {}
+
+ caniuse-lite@1.0.30001680: {}
+
+ clsx@2.1.1: {}
+
+ commander@2.20.3: {}
+
+ convert-source-map@1.9.0: {}
+
+ convert-source-map@2.0.0: {}
+
+ core-js-compat@3.39.0:
+ dependencies:
+ browserslist: 4.24.2
+
+ core-js@3.39.0: {}
+
+ cosmiconfig@7.1.0:
+ dependencies:
+ '@types/parse-json': 4.0.2
+ import-fresh: 3.3.0
+ parse-json: 5.2.0
+ path-type: 4.0.0
+ yaml: 1.10.2
+
+ csstype@3.1.3: {}
+
+ dayjs@1.11.13: {}
+
+ debug@4.3.7:
+ dependencies:
+ ms: 2.1.3
+
+ dom-helpers@5.2.1:
+ dependencies:
+ '@babel/runtime': 7.26.0
+ csstype: 3.1.3
+
+ electron-to-chromium@1.5.62: {}
+
+ error-ex@1.3.2:
+ dependencies:
+ is-arrayish: 0.2.1
+
+ esbuild@0.21.5:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.21.5
+ '@esbuild/android-arm': 0.21.5
+ '@esbuild/android-arm64': 0.21.5
+ '@esbuild/android-x64': 0.21.5
+ '@esbuild/darwin-arm64': 0.21.5
+ '@esbuild/darwin-x64': 0.21.5
+ '@esbuild/freebsd-arm64': 0.21.5
+ '@esbuild/freebsd-x64': 0.21.5
+ '@esbuild/linux-arm': 0.21.5
+ '@esbuild/linux-arm64': 0.21.5
+ '@esbuild/linux-ia32': 0.21.5
+ '@esbuild/linux-loong64': 0.21.5
+ '@esbuild/linux-mips64el': 0.21.5
+ '@esbuild/linux-ppc64': 0.21.5
+ '@esbuild/linux-riscv64': 0.21.5
+ '@esbuild/linux-s390x': 0.21.5
+ '@esbuild/linux-x64': 0.21.5
+ '@esbuild/netbsd-x64': 0.21.5
+ '@esbuild/openbsd-x64': 0.21.5
+ '@esbuild/sunos-x64': 0.21.5
+ '@esbuild/win32-arm64': 0.21.5
+ '@esbuild/win32-ia32': 0.21.5
+ '@esbuild/win32-x64': 0.21.5
+
+ escalade@3.2.0: {}
+
+ escape-string-regexp@4.0.0: {}
+
+ esutils@2.0.3: {}
+
+ fflate@0.6.10: {}
+
+ find-root@1.1.0: {}
+
+ fsevents@2.3.3:
+ optional: true
+
+ function-bind@1.1.2: {}
+
+ gensync@1.0.0-beta.2: {}
+
+ globals@11.12.0: {}
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ hoist-non-react-statics@3.3.2:
+ dependencies:
+ react-is: 16.13.1
+
+ immer@10.1.1: {}
+
+ import-fresh@3.3.0:
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+
+ intersection-observer@0.12.2: {}
+
+ is-arrayish@0.2.1: {}
+
+ is-core-module@2.15.1:
+ dependencies:
+ hasown: 2.0.2
+
+ jotai@2.10.2(@types/react@18.3.12)(react@18.3.1):
+ optionalDependencies:
+ '@types/react': 18.3.12
+ react: 18.3.1
+
+ js-cookie@3.0.5: {}
+
+ js-tokens@4.0.0: {}
+
+ jsesc@3.0.2: {}
+
+ json-parse-even-better-errors@2.3.1: {}
+
+ json5@2.2.3: {}
+
+ lines-and-columns@1.2.4: {}
+
+ lodash.debounce@4.0.8: {}
+
+ lodash@4.17.21: {}
+
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+
+ lru-cache@5.1.1:
+ dependencies:
+ yallist: 3.1.1
+
+ magic-string@0.30.12:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.0
+
+ meow@13.2.0: {}
+
+ meshoptimizer@0.18.1: {}
+
+ ms@2.1.3: {}
+
+ mui-file-input@6.0.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/material@6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@emotion/react': 11.13.3(@types/react@18.3.12)(react@18.3.1)
+ '@emotion/styled': 11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+ '@mui/material': 6.1.7(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ pretty-bytes: 6.1.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.12
+
+ nanoid@3.3.7: {}
+
+ node-releases@2.0.18: {}
+
+ object-assign@4.1.1: {}
+
+ parent-module@1.0.1:
+ dependencies:
+ callsites: 3.1.0
+
+ parse-json@5.2.0:
+ dependencies:
+ '@babel/code-frame': 7.26.2
+ error-ex: 1.3.2
+ json-parse-even-better-errors: 2.3.1
+ lines-and-columns: 1.2.4
+
+ path-parse@1.0.7: {}
+
+ path-type@4.0.0: {}
+
+ picocolors@1.1.1: {}
+
+ postcss@8.4.49:
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ pretty-bytes@6.1.1: {}
+
+ prop-types@15.8.1:
+ dependencies:
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ react-is: 16.13.1
+
+ react-dom@18.3.1(react@18.3.1):
+ dependencies:
+ loose-envify: 1.4.0
+ react: 18.3.1
+ scheduler: 0.23.2
+
+ react-fast-compare@3.2.2: {}
+
+ react-is@16.13.1: {}
+
+ react-is@18.3.1: {}
+
+ react-refresh@0.14.2: {}
+
+ react-router-dom@6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@remix-run/router': 1.21.0
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-router: 6.28.0(react@18.3.1)
+
+ react-router@6.28.0(react@18.3.1):
+ dependencies:
+ '@remix-run/router': 1.21.0
+ react: 18.3.1
+
+ react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@babel/runtime': 7.26.0
+ dom-helpers: 5.2.1
+ loose-envify: 1.4.0
+ prop-types: 15.8.1
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
+ react@18.3.1:
+ dependencies:
+ loose-envify: 1.4.0
+
+ regenerate-unicode-properties@10.2.0:
+ dependencies:
+ regenerate: 1.4.2
+
+ regenerate@1.4.2: {}
+
+ regenerator-runtime@0.14.1: {}
+
+ regenerator-transform@0.15.2:
+ dependencies:
+ '@babel/runtime': 7.26.0
+
+ regexpu-core@6.1.1:
+ dependencies:
+ regenerate: 1.4.2
+ regenerate-unicode-properties: 10.2.0
+ regjsgen: 0.8.0
+ regjsparser: 0.11.2
+ unicode-match-property-ecmascript: 2.0.0
+ unicode-match-property-value-ecmascript: 2.2.0
+
+ regjsgen@0.8.0: {}
+
+ regjsparser@0.11.2:
+ dependencies:
+ jsesc: 3.0.2
+
+ resize-observer-polyfill@1.5.1: {}
+
+ resolve-from@4.0.0: {}
+
+ resolve@1.22.8:
+ dependencies:
+ is-core-module: 2.15.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ rollup@4.27.2:
+ dependencies:
+ '@types/estree': 1.0.6
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.27.2
+ '@rollup/rollup-android-arm64': 4.27.2
+ '@rollup/rollup-darwin-arm64': 4.27.2
+ '@rollup/rollup-darwin-x64': 4.27.2
+ '@rollup/rollup-freebsd-arm64': 4.27.2
+ '@rollup/rollup-freebsd-x64': 4.27.2
+ '@rollup/rollup-linux-arm-gnueabihf': 4.27.2
+ '@rollup/rollup-linux-arm-musleabihf': 4.27.2
+ '@rollup/rollup-linux-arm64-gnu': 4.27.2
+ '@rollup/rollup-linux-arm64-musl': 4.27.2
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.27.2
+ '@rollup/rollup-linux-riscv64-gnu': 4.27.2
+ '@rollup/rollup-linux-s390x-gnu': 4.27.2
+ '@rollup/rollup-linux-x64-gnu': 4.27.2
+ '@rollup/rollup-linux-x64-musl': 4.27.2
+ '@rollup/rollup-win32-arm64-msvc': 4.27.2
+ '@rollup/rollup-win32-ia32-msvc': 4.27.2
+ '@rollup/rollup-win32-x64-msvc': 4.27.2
+ fsevents: 2.3.3
+
+ scheduler@0.23.2:
+ dependencies:
+ loose-envify: 1.4.0
+
+ screenfull@5.2.0: {}
+
+ semver@6.3.1: {}
+
+ skinview-utils@0.7.1: {}
+
+ skinview3d@3.1.0:
+ dependencies:
+ '@types/three': 0.156.0
+ skinview-utils: 0.7.1
+ three: 0.156.1
+
+ source-map-js@1.2.1: {}
+
+ source-map-support@0.5.21:
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+
+ source-map@0.5.7: {}
+
+ source-map@0.6.1: {}
+
+ stylis@4.2.0: {}
+
+ supports-preserve-symlinks-flag@1.0.0: {}
+
+ systemjs@6.15.1: {}
+
+ terser@5.36.0:
+ dependencies:
+ '@jridgewell/source-map': 0.3.6
+ acorn: 8.14.0
+ commander: 2.20.3
+ source-map-support: 0.5.21
+
+ three@0.156.1: {}
+
+ tilg@0.1.1(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+
+ tslib@2.8.1: {}
+
+ typescript@5.6.3: {}
+
+ undici-types@6.19.8: {}
+
+ unicode-canonical-property-names-ecmascript@2.0.1: {}
+
+ unicode-match-property-ecmascript@2.0.0:
+ dependencies:
+ unicode-canonical-property-names-ecmascript: 2.0.1
+ unicode-property-aliases-ecmascript: 2.1.0
+
+ unicode-match-property-value-ecmascript@2.2.0: {}
+
+ unicode-property-aliases-ecmascript@2.1.0: {}
+
+ update-browserslist-db@1.1.1(browserslist@4.24.2):
+ dependencies:
+ browserslist: 4.24.2
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
+ vite@5.4.11(@types/node@20.17.6)(terser@5.36.0):
+ dependencies:
+ esbuild: 0.21.5
+ postcss: 8.4.49
+ rollup: 4.27.2
+ optionalDependencies:
+ '@types/node': 20.17.6
+ fsevents: 2.3.3
+ terser: 5.36.0
+
+ yallist@3.1.1: {}
+
+ yaml@1.10.2: {}
diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/frontend/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
new file mode 100644
index 0000000..b25320c
--- /dev/null
+++ b/frontend/src/App.tsx
@@ -0,0 +1,13 @@
+import { PageRoute } from '@/Route'
+
+function App() {
+
+ return (
+ <>
+
+ >
+ )
+}
+
+
+export default App
diff --git a/frontend/src/Route.tsx b/frontend/src/Route.tsx
new file mode 100644
index 0000000..83a2f18
--- /dev/null
+++ b/frontend/src/Route.tsx
@@ -0,0 +1,58 @@
+import { Routes, Route, createBrowserRouter, RouterProvider, Outlet } from "react-router-dom";
+import { ScrollRestoration } from "react-router-dom";
+import Login from '@/views/Login'
+import Register from '@/views/Register'
+import Profile from '@/views/profile/Profile'
+import Textures from '@/views/profile/Textures'
+import Security from '@/views/profile/Security'
+import Layout from '@/views/Layout'
+import UserAdmin from "@/views/admin/UserAdmin";
+import NeedLogin from "@/components/NeedLogin";
+import Index from "@/views/Index";
+import SendEmail from "@/views/SendEmail";
+import { sendForgotEmail, sendRegEmail } from "@/apis/apis";
+import Forgot from "@/views/Forgot";
+
+const router = createBrowserRouter([
+ { path: "*", Component: Root },
+])
+
+function Root() {
+ return (
+ <>
+
+ }>
+ } />
+ 404
} />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+ }>
+ } />
+ } />
+ } />
+
+
+ }>
+ } />
+
+
+
+
+
+ >
+ )
+}
+
+
+export function PageRoute() {
+ return (
+ <>
+
+ >
+ )
+}
+
diff --git a/frontend/src/apis/apis.ts b/frontend/src/apis/apis.ts
new file mode 100644
index 0000000..b996595
--- /dev/null
+++ b/frontend/src/apis/apis.ts
@@ -0,0 +1,156 @@
+import type { tokenData, ApiUser, YggProfile, ApiConfig, List, UserInfo, EditUser } from '@/apis/model'
+import { apiGet } from '@/apis/utils'
+import root from '@/utils/root'
+
+export async function login(email: string, password: string, captchaToken: string) {
+ const v = await fetch(root() + "/api/v1/user/login", {
+ method: "POST",
+ body: JSON.stringify({
+ "email": email,
+ "password": password,
+ "CaptchaToken": captchaToken
+ })
+ })
+ return await apiGet(v)
+}
+
+export async function register(email: string, username: string, password: string, captchaToken: string, code: string) {
+ const v = await fetch(root() + "/api/v1/user/reg", {
+ method: "POST",
+ body: JSON.stringify({
+ "Email": email,
+ "Password": password,
+ "Name": username,
+ "CaptchaToken": captchaToken,
+ "EmailJwt": code,
+ })
+ })
+ return await apiGet(v)
+}
+
+export async function userInfo(token: string) {
+ if (token == "") return
+ const v = await fetch(root() + "/api/v1/user", {
+ headers: {
+ "Authorization": "Bearer " + token
+ }
+ })
+ return await apiGet(v)
+}
+
+export async function yggProfile(uuid: string) {
+ if (uuid == "") return
+ const v = await fetch(root() + "/api/yggdrasil/sessionserver/session/minecraft/profile/" + uuid)
+ const data = await v.json()
+ if (!v.ok) {
+ throw new Error(data?.errorMessage)
+ }
+ return data as YggProfile
+}
+
+export async function upTextures(token: string, textureType: 'skin' | 'cape', model: 'slim' | '', file: File) {
+ const f = new FormData()
+ f.set("file", file)
+ f.set("model", model)
+
+ const r = await fetch(root() + "/api/v1/user/skin/" + textureType, {
+ method: "PUT",
+ body: f,
+ headers: {
+ "Authorization": "Bearer " + token
+ }
+ })
+ return await apiGet(r)
+}
+
+export async function changePasswd(old: string, newpa: string, token: string) {
+ const r = await fetch(root() + "/api/v1/user/password", {
+ method: "POST",
+ body: JSON.stringify({
+ "old": old,
+ "new": newpa
+ }),
+ headers: {
+ "Authorization": "Bearer " + token
+ }
+ })
+ return await apiGet(r)
+}
+
+export async function getConfig() {
+ const r = await fetch(root() + "/api/v1/config")
+ return await apiGet(r)
+}
+
+export async function changeName(name: string, token: string) {
+ const r = await fetch(root() + "/api/v1/user/name", {
+ method: "POST",
+ body: JSON.stringify({
+ "name": name,
+ }),
+ headers: {
+ "Authorization": "Bearer " + token
+ }
+ })
+ return await apiGet(r)
+}
+
+export async function ListUser(page: number, token: string, email: string, name: string) {
+ const u = new URL(root() + "/api/v1/admin/users")
+ u.searchParams.set("page", String(page))
+ u.searchParams.set("email", email)
+ u.searchParams.set("name", name)
+ const r = await fetch(u.toString(), {
+ method: "GET",
+ headers: {
+ "Authorization": "Bearer " + token
+ }
+ })
+ return await apiGet>(r)
+}
+
+export async function editUser(u: EditUser, token: string, uid: string) {
+ const r = await fetch(root() + "/api/v1/admin/user/" + uid, {
+ method: "PATCH",
+ headers: {
+ "Authorization": "Bearer " + token
+ },
+ body: JSON.stringify(u)
+ })
+ return await apiGet(r)
+}
+
+export async function sendRegEmail(email: string, captchaToken: string) {
+ const r = await fetch(root() + "/api/v1/user/reg_email", {
+ method: "POST",
+ body: JSON.stringify({
+ "email": email,
+ "captchaToken": captchaToken
+ })
+ })
+ return await apiGet(r)
+}
+
+export async function sendForgotEmail(email: string, captchaToken: string) {
+ const r = await fetch(root() + "/api/v1/user/forgot_email", {
+ method: "POST",
+ body: JSON.stringify({
+ "email": email,
+ "captchaToken": captchaToken
+ })
+ })
+ return await apiGet(r)
+}
+
+
+export async function forgotPassWord(email: string, emailJwt: string, password: string) {
+ const r = await fetch(root() + "/api/v1/user/forgot", {
+ method: "POST",
+ body: JSON.stringify({
+ "email": email,
+ "emailJwt": emailJwt,
+ "passWord": password,
+ })
+ })
+ return await apiGet(r)
+}
\ No newline at end of file
diff --git a/frontend/src/apis/error.ts b/frontend/src/apis/error.ts
new file mode 100644
index 0000000..58c962b
--- /dev/null
+++ b/frontend/src/apis/error.ts
@@ -0,0 +1,8 @@
+export class ApiErr extends Error {
+ readonly code: number
+
+ constructor(code: number, msg: string) {
+ super(msg)
+ this.code = code
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/apis/model.ts b/frontend/src/apis/model.ts
new file mode 100644
index 0000000..5dc0828
--- /dev/null
+++ b/frontend/src/apis/model.ts
@@ -0,0 +1,66 @@
+export interface tokenData {
+ token: string
+ name: string
+ uuid: string
+}
+
+export interface Api {
+ code: number
+ msg: string
+ data: T
+}
+
+export interface List {
+ total: number
+ list: T[]
+}
+
+
+interface captcha {
+ type: string
+ siteKey: string
+}
+
+
+export interface ApiUser {
+ uid: string
+ uuid: string
+ is_admin: boolean
+}
+
+export interface YggProfile {
+ name: string
+ properties: {
+ name: string
+ value: string
+ }[]
+}
+
+export interface ApiConfig {
+ captcha: captcha
+ AllowChangeName: boolean
+ serverName: string
+ NeedEmail: boolean
+ AllowDomain: string[]
+ EmailReg: string
+ EmailRegMsg: string
+}
+
+export interface UserInfo {
+ uid: number
+ uuid: string
+ is_admin: boolean
+ is_disable: boolean
+ email: string
+ reg_ip: string
+ name: string
+}
+
+export interface EditUser {
+ email?: string
+ name?: string
+ password?: string
+ is_admin?: boolean
+ is_disable?: boolean
+ del_textures?: boolean
+}
\ No newline at end of file
diff --git a/frontend/src/apis/utils.ts b/frontend/src/apis/utils.ts
new file mode 100644
index 0000000..be66411
--- /dev/null
+++ b/frontend/src/apis/utils.ts
@@ -0,0 +1,10 @@
+import { ApiErr } from "./error"
+
+export async function apiGet(v: Response) {
+ type api = { data: T, msg: string, code: number }
+ const data = await v.json() as api
+ if (!v.ok) {
+ throw new ApiErr(data.code, data.msg)
+ }
+ return data.data
+}
diff --git a/frontend/src/components/CaptchaWidget.tsx b/frontend/src/components/CaptchaWidget.tsx
new file mode 100644
index 0000000..c24cfcc
--- /dev/null
+++ b/frontend/src/components/CaptchaWidget.tsx
@@ -0,0 +1,65 @@
+import { Turnstile } from '@marsidev/react-turnstile'
+import Button from '@mui/material/Button'
+import { useRef, useState, memo, forwardRef, useImperativeHandle, useEffect } from 'react'
+import type { TurnstileInstance } from '@marsidev/react-turnstile'
+import Alert from '@mui/material/Alert';
+import Skeleton from '@mui/material/Skeleton';
+import { useRequest } from 'ahooks';
+import { getConfig } from '@/apis/apis';
+
+interface prop {
+ onSuccess: ((token: string) => void)
+}
+
+export type refType = {
+ reload: () => void
+}
+
+
+const CaptchaWidget = forwardRef(({ onSuccess }, ref) => {
+ const Turnstileref = useRef(null)
+ const [key, setKey] = useState(1)
+ const { data, error, loading } = useRequest(getConfig, {
+ cacheKey: "/api/v1/config",
+ staleTime: 600000,
+ loadingDelay: 200
+ })
+
+ useImperativeHandle(ref, () => {
+ return {
+ reload: () => {
+ setKey(key + 1)
+ }
+ }
+ })
+ useEffect(() => {
+ if (data?.captcha?.type != "turnstile") {
+ onSuccess("ok")
+ return
+ }
+ }, [data?.captcha?.type, onSuccess])
+
+
+ if (error) {
+ console.warn(error)
+ return {String(error)}
+ }
+ if (!data && loading) {
+ return
+ }
+
+ if (data?.captcha.type == "") {
+ return <>>
+ }
+
+ return (
+ <>
+
+
+ >
+ )
+})
+
+const CaptchaWidgetMemo = memo(CaptchaWidget)
+
+export default CaptchaWidgetMemo
\ No newline at end of file
diff --git a/frontend/src/components/CheckInput.tsx b/frontend/src/components/CheckInput.tsx
new file mode 100644
index 0000000..e323714
--- /dev/null
+++ b/frontend/src/components/CheckInput.tsx
@@ -0,0 +1,65 @@
+import TextField from '@mui/material/TextField';
+import { useState, useImperativeHandle, forwardRef } from 'react';
+import type { TextFieldProps } from '@mui/material/TextField';
+import { useControllableValue } from 'ahooks';
+
+export type refType = {
+ verify: () => boolean
+}
+
+type prop = {
+ checkList: {
+ errMsg: string
+ reg: RegExp
+ }[]
+} & Omit, 'helperText'>
+
+export const CheckInput = forwardRef(({ required, checkList, ...textFied }, ref) => {
+ const [err, setErr] = useState("");
+ const [value, setValue] = useControllableValue(textFied);
+
+
+ const check = (value: string) => {
+ if (required && (!value || value == "")) {
+ setErr("此项必填")
+ return false
+ }
+ for (const v of checkList) {
+ if (!v.reg.test(value)) {
+ setErr(v.errMsg)
+ return false
+ }
+ }
+ setErr("")
+ return true
+ }
+
+ const verify = () => {
+ return check(value)
+ }
+
+ useImperativeHandle(ref, () => {
+ return {
+ verify
+ }
+ })
+
+ const onChange = (event: React.ChangeEvent) => {
+ const value = event.target.value
+ setValue(value)
+ check(value)
+ }
+
+
+
+ return
+})
+
+export default CheckInput
\ No newline at end of file
diff --git a/frontend/src/components/Loading.tsx b/frontend/src/components/Loading.tsx
new file mode 100644
index 0000000..9b09deb
--- /dev/null
+++ b/frontend/src/components/Loading.tsx
@@ -0,0 +1,15 @@
+import Backdrop from "@mui/material/Backdrop";
+import CircularProgress from "@mui/material/CircularProgress";
+
+export default function Loading() {
+ return (
+ <>
+ theme.zIndex.modal + 1 }}
+ open={true}
+ >
+
+
+ >
+ )
+}
diff --git a/frontend/src/components/NeedLogin.tsx b/frontend/src/components/NeedLogin.tsx
new file mode 100644
index 0000000..b7b38b9
--- /dev/null
+++ b/frontend/src/components/NeedLogin.tsx
@@ -0,0 +1,41 @@
+import { userInfo } from "@/apis/apis";
+import { ApiErr } from "@/apis/error";
+import { token } from "@/store/store";
+import { useRequest } from "ahooks";
+import { useAtomValue } from "jotai";
+import { useEffect } from "react";
+import { useNavigate, Navigate } from "react-router-dom";
+
+
+export default function NeedLogin({ children, needAdmin = false }: { children: JSX.Element, needAdmin?: boolean }) {
+ const t = useAtomValue(token)
+ const navigate = useNavigate();
+ const u = useRequest(() => userInfo(t), {
+ refreshDeps: [t],
+ cacheKey: "/api/v1/user" + t,
+ staleTime: 60000,
+ onError: e => {
+ if (e instanceof ApiErr && e.code == 5) {
+ navigate("/login")
+ }
+ console.warn(e)
+ }
+ })
+
+ useEffect(() => {
+ if (!u.data) return
+ if (!u.data.is_admin && needAdmin) {
+ navigate("/login")
+ }
+ if (u.data.uuid == "") {
+ navigate("/login")
+ }
+ }, [navigate, needAdmin, u.data])
+
+ if (!localStorage.getItem("token") || localStorage.getItem("token") == '""') {
+ return
+ }
+
+
+ return <> {children}>
+}
\ No newline at end of file
diff --git a/frontend/src/components/SkinViewUUID.tsx b/frontend/src/components/SkinViewUUID.tsx
new file mode 100644
index 0000000..d68b300
--- /dev/null
+++ b/frontend/src/components/SkinViewUUID.tsx
@@ -0,0 +1,89 @@
+import { yggProfile } from "@/apis/apis";
+import { decodeSkin } from "@/utils/skin";
+import Skeleton from "@mui/material/Skeleton";
+import { useHover, useMemoizedFn, useRequest, useUnmount } from "ahooks";
+import { memo, useEffect, useRef, useState } from "react";
+import ReactSkinview3d, { ReactSkinview3dOptions } from "@/components/Skinview3d";
+import { SkinViewer, WalkingAnimation } from "skinview3d";
+import Box from "@mui/material/Box";
+import Typography from "@mui/material/Typography";
+
+interface prop {
+ uuid: string
+ width: number
+ height: number
+}
+
+const SkinViewUUID = memo(function SkinViewUUID({ uuid, width, height }: prop) {
+ const [textures, setTextures] = useState({ skin: "", cape: "", model: "default" })
+ const [err, setErr] = useState("")
+
+ const SkinInfo = useRequest(() => yggProfile(uuid), {
+ cacheKey: "/api/yggdrasil/sessionserver/session/minecraft/profile/" + uuid,
+ onError: e => {
+ console.warn(e)
+ setErr(String(e))
+ },
+ refreshDeps: [uuid],
+ })
+
+ useEffect(() => {
+ if (!SkinInfo.data) return
+ const [skin, cape, model] = decodeSkin(SkinInfo.data)
+ setTextures({ cape: cape, skin: skin, model: model })
+ }, [SkinInfo.data])
+
+ if (err != "") {
+ return {err}
+ }
+ return (<>
+ {
+ (SkinInfo.loading && !SkinInfo.data) ?
+ : (textures.skin != "" || textures.cape != "") ? (
+ ) :
+ 还没有设置皮肤
+
+ }
+ >)
+})
+
+
+const MySkin = function MySkin(p: ReactSkinview3dOptions) {
+ const refSkinview3d = useRef(null);
+ const skinisHovering = useHover(refSkinview3d);
+ const skinview3dView = useRef(null);
+
+ useEffect(() => {
+ if (skinview3dView.current) {
+ skinview3dView.current.autoRotate = !skinisHovering
+ }
+ if (skinview3dView.current?.animation) {
+ skinview3dView.current.animation.paused = skinisHovering
+ }
+ }, [skinisHovering])
+
+ useUnmount(() => {
+ skinview3dView.current?.dispose()
+ })
+
+ const handelOnReady = useMemoizedFn(v => {
+ v.viewer.animation = new WalkingAnimation()
+ v.viewer.autoRotate = true
+ skinview3dView.current = v.viewer
+ })
+
+ return
+
+
+}
+
+export default SkinViewUUID
\ No newline at end of file
diff --git a/frontend/src/components/Skinview3d.tsx b/frontend/src/components/Skinview3d.tsx
new file mode 100644
index 0000000..b4fdcc8
--- /dev/null
+++ b/frontend/src/components/Skinview3d.tsx
@@ -0,0 +1,101 @@
+import { memo, useEffect, useRef } from "react";
+import { SkinViewer, SkinViewerOptions } from "skinview3d";
+
+// https://github.com/Hacksore/react-skinview3d/blob/master/src/index.tsx
+
+/**
+ * This is the interface that describes the parameter in `onReady`
+ */
+export interface ViewerReadyCallbackOptions {
+ /**
+ * The instance of the skinview3d
+ */
+ viewer: SkinViewer;
+ /**
+ * The ref to the canvas element
+ */
+ canvasRef: HTMLCanvasElement;
+}
+
+export interface ReactSkinview3dOptions {
+ /**
+ * The class names to apply to the canvas
+ */
+ className?: string;
+ /**
+ * The width of the canvas
+ */
+ width: number | string;
+ /**
+ * The height of the canvas
+ */
+ height: number | string;
+ /**
+ * The skin to load in the canvas
+ */
+ skinUrl: string;
+ /**
+ * The cape to load in the canvas
+ */
+ capeUrl?: string;
+ /**
+ * A function that is called when the skin viewer is ready
+ * @param {SkinViewer} instance callback function to execute when the viewer is loaded {@link SkinViewer}
+ * @example
+ * onReady((instance) => {
+ * console.log(instance)
+ * })
+ */
+ onReady?: ({ viewer, canvasRef }: ViewerReadyCallbackOptions) => void;
+ /**
+ * Parameters passed to the skinview3d constructor allowing you to override or add extra features
+ * @notes please take a look at the upstream repo for more info
+ * [bs-community/skinview3d](https://bs-community.github.io/skinview3d/)
+ */
+ options?: SkinViewerOptions;
+}
+
+/**
+ * A skinview3d component
+ */
+const ReactSkinview3d = memo(function ReactSkinview3d({
+ className,
+ width,
+ height,
+ skinUrl,
+ capeUrl,
+ onReady,
+ options,
+}: ReactSkinview3dOptions) {
+ const canvasRef = useRef(null);
+ const skinviewRef = useRef();
+
+ useEffect(() => {
+ if (!canvasRef.current) return
+
+ const viewer = new SkinViewer({
+ canvas: canvasRef.current,
+ width: Number(width),
+ height: Number(height),
+ ...options,
+ });
+
+ // handle cape/skin load initially
+ skinUrl && viewer.loadSkin(skinUrl, { model: options?.model ?? "auto-detect" });
+ capeUrl && viewer.loadCape(capeUrl);
+
+ skinviewRef.current = viewer;
+
+ // call onReady with the viewer instance
+ if (onReady) {
+ onReady({ viewer: skinviewRef.current, canvasRef: canvasRef.current });
+ }
+
+ return () => viewer.dispose()
+ }, [capeUrl, height, onReady, options, skinUrl, width]);
+
+
+ return ;
+})
+
+export default ReactSkinview3d;
\ No newline at end of file
diff --git a/frontend/src/hooks/useTitle.ts b/frontend/src/hooks/useTitle.ts
new file mode 100644
index 0000000..2ec60da
--- /dev/null
+++ b/frontend/src/hooks/useTitle.ts
@@ -0,0 +1,16 @@
+import { getConfig } from '@/apis/apis'
+import { useTitle as auseTitle, useRequest } from 'ahooks'
+import { useEffect } from 'react'
+
+export default function useTitle(title: string) {
+ const { data, error } = useRequest(getConfig, {
+ cacheKey: "/api/v1/config",
+ staleTime: 60000,
+ })
+ useEffect(() => {
+ error && console.warn(error)
+ }, [error])
+ auseTitle(title + " - " + data?.serverName, {
+ restoreOnUnmount: true
+ })
+}
\ No newline at end of file
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
new file mode 100644
index 0000000..30c9a76
--- /dev/null
+++ b/frontend/src/main.tsx
@@ -0,0 +1,11 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App.tsx'
+import CssBaseline from '@mui/material/CssBaseline';
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+
+
+)
diff --git a/frontend/src/store/store.ts b/frontend/src/store/store.ts
new file mode 100644
index 0000000..00bc090
--- /dev/null
+++ b/frontend/src/store/store.ts
@@ -0,0 +1,10 @@
+import { atom } from 'jotai'
+import { atomWithStorage } from 'jotai/utils'
+
+export const token = atomWithStorage("token", "")
+export const user = atomWithStorage("username", {
+ name: "",
+ uuid: ""
+})
+
+export const LayoutAlertErr = atom("")
\ No newline at end of file
diff --git a/frontend/src/utils/email.ts b/frontend/src/utils/email.ts
new file mode 100644
index 0000000..2d88b7d
--- /dev/null
+++ b/frontend/src/utils/email.ts
@@ -0,0 +1,3 @@
+export function checkEmail(email: string) {
+ return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email);
+}
\ No newline at end of file
diff --git a/frontend/src/utils/root.ts b/frontend/src/utils/root.ts
new file mode 100644
index 0000000..d5d67a1
--- /dev/null
+++ b/frontend/src/utils/root.ts
@@ -0,0 +1,6 @@
+export default function root() {
+ if (import.meta.env.VITE_APIADDR != "") {
+ return import.meta.env.VITE_APIADDR
+ }
+ return location.origin
+}
\ No newline at end of file
diff --git a/frontend/src/utils/skin.ts b/frontend/src/utils/skin.ts
new file mode 100644
index 0000000..53b9295
--- /dev/null
+++ b/frontend/src/utils/skin.ts
@@ -0,0 +1,17 @@
+import { YggProfile } from "@/apis/model";
+
+export function decodeSkin(y: YggProfile) {
+ if (y.properties.length == 0) {
+ return ["", "", ""]
+ }
+ const p = y.properties.find(v => v.name == "textures")
+ if (!p?.value || p?.value == "") {
+ return ["", "", ""]
+ }
+ const textures = JSON.parse(atob(p.value))
+
+ const skin = textures?.textures?.SKIN?.url as string ?? ""
+ const cape = textures?.textures?.CAPE?.url as string ?? ""
+ const model = textures?.textures?.SKIN?.metadata?.model as string ?? "default"
+ return [skin, cape, model]
+}
\ No newline at end of file
diff --git a/frontend/src/views/Forgot.tsx b/frontend/src/views/Forgot.tsx
new file mode 100644
index 0000000..65ad9ec
--- /dev/null
+++ b/frontend/src/views/Forgot.tsx
@@ -0,0 +1,120 @@
+import Avatar from '@mui/material/Avatar';
+import Button from '@mui/material/Button';
+import CssBaseline from '@mui/material/CssBaseline';
+import Grid from '@mui/material/Grid';
+import Box from '@mui/material/Box';
+import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
+import Typography from '@mui/material/Typography';
+import Container from '@mui/material/Container';
+import TextField from '@mui/material/TextField';
+import { useTitle } from 'ahooks';
+import { useEffect, useState } from 'react';
+import Snackbar from '@mui/material/Snackbar';
+import Alert from '@mui/material/Alert';
+import Loading from '@/components/Loading';
+import { produce } from 'immer';
+import { forgotPassWord } from '@/apis/apis';
+import { useNavigate } from 'react-router-dom';
+
+export default function Forgot() {
+ const [err, setErr] = useState("")
+ useTitle("重设密码")
+ const [passerr, setPasserr] = useState("")
+ const [pass, setPass] = useState({
+ pass1: "",
+ pass2: "",
+ })
+ const [load, setLoad] = useState(false)
+ const [email, setEmail] = useState("")
+ const [code, setCode] = useState("")
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ if (pass.pass1 != pass.pass2 && pass.pass2 != "") {
+ setPasserr("密码不相等")
+ return
+ }
+ setPasserr("")
+ }, [pass.pass1, pass.pass2])
+
+ const u = new URL(location.href)
+
+ useEffect(() => {
+ setEmail(u.searchParams.get("email") ?? "")
+ setCode(u.searchParams.get("code") ?? "")
+ }, [u.searchParams])
+
+
+ const onSubmit = (e: React.FormEvent) => {
+ e.preventDefault()
+ setLoad(true)
+ forgotPassWord(email, code, pass.pass1).then(() => {
+ navigate("/")
+ }).catch(e => {
+ setErr(String(e))
+ }).finally(() => { setLoad(false) })
+ }
+
+
+ return (
+
+
+
+
+
+
+
+ 找回密码
+
+
+
+
+ setPass(produce(v => { v.pass1 = p.target.value }))}
+ autoComplete="new-password"
+ />
+
+
+ setPass(produce(v => { v.pass2 = p.target.value }))}
+ autoComplete="new-password"
+ />
+
+
+
+
+
+
+ setErr("")} severity="error">{err}
+
+
+ {load && }
+
+ )
+}
\ No newline at end of file
diff --git a/frontend/src/views/Index.tsx b/frontend/src/views/Index.tsx
new file mode 100644
index 0000000..cc1cccc
--- /dev/null
+++ b/frontend/src/views/Index.tsx
@@ -0,0 +1,9 @@
+import Profile from "@/views/profile/Profile"
+import Login from "@/views/Login"
+
+export default function Index() {
+ if (localStorage.getItem("token") && localStorage.getItem("token") != '""') {
+ return
+ }
+ return
+}
\ No newline at end of file
diff --git a/frontend/src/views/Layout.tsx b/frontend/src/views/Layout.tsx
new file mode 100644
index 0000000..87555b8
--- /dev/null
+++ b/frontend/src/views/Layout.tsx
@@ -0,0 +1,291 @@
+import * as React from 'react';
+import { styled, useTheme } from '@mui/material/styles';
+import Box from '@mui/material/Box';
+import Drawer from '@mui/material/Drawer';
+import Toolbar from '@mui/material/Toolbar';
+import List from '@mui/material/List';
+import Divider from '@mui/material/Divider';
+import IconButton from '@mui/material/IconButton';
+import MenuIcon from '@mui/icons-material/Menu';
+import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
+import ChevronRightIcon from '@mui/icons-material/ChevronRight';
+import ListItem from '@mui/material/ListItem';
+import ListItemButton from '@mui/material/ListItemButton';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import ListItemText from '@mui/material/ListItemText';
+import AppBar from '@mui/material/AppBar';
+import { Outlet } from 'react-router-dom';
+import { AccountCircle } from '@mui/icons-material';
+import Menu from '@mui/material/Menu';
+import MenuItem from '@mui/material/MenuItem';
+import { LayoutAlertErr, token, user } from '@/store/store';
+import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
+import Button from '@mui/material/Button';
+import { useNavigate } from "react-router-dom";
+import { useRequest, useMemoizedFn } from 'ahooks';
+import { getConfig, userInfo } from '@/apis/apis'
+import Snackbar from '@mui/material/Snackbar';
+import Alert from '@mui/material/Alert';
+import { memo } from 'react';
+import useMediaQuery from '@mui/material/useMediaQuery';
+import Typography from '@mui/material/Typography';
+import Container from '@mui/material/Container';
+import PersonIcon from '@mui/icons-material/Person';
+import SecurityIcon from '@mui/icons-material/Security';
+import SettingsIcon from '@mui/icons-material/Settings';
+import { Link } from "react-router-dom";
+import GroupIcon from '@mui/icons-material/Group';
+import { ApiErr } from '@/apis/error';
+
+const drawerWidth = 240;
+const DrawerOpen = atom(false)
+
+const DrawerHeader = styled('div')(({ theme }) => ({
+ display: 'flex',
+ alignItems: 'center',
+ padding: theme.spacing(0, 1),
+ // necessary for content to be below app bar
+ ...theme.mixins.toolbar,
+ justifyContent: 'flex-end',
+}));
+
+interface ListItem {
+ icon: JSX.Element
+ title: string
+ link: string
+}
+
+const Layout = memo(function Layout() {
+ const theme = useTheme();
+ const [err, setErr] = useAtom(LayoutAlertErr)
+
+ return (<>
+
+
+
+
+
+
+ setErr("")} severity="error">{err}
+
+
+
+
+
+
+
+
+ >)
+})
+
+const MyToolbar = memo(function MyToolbar() {
+ const [nowUser, setNowUser] = useAtom(user)
+ const [anchorEl, setAnchorEl] = React.useState(null);
+ const navigate = useNavigate();
+ const setToken = useSetAtom(token)
+ const setErr = useSetAtom(LayoutAlertErr)
+ const setOpen = useSetAtom(DrawerOpen)
+
+ const server = useRequest(getConfig, {
+ cacheKey: "/api/v1/config",
+ staleTime: 60000,
+ onError: e => {
+ console.warn(e)
+ setErr(String(e))
+ }
+ })
+
+
+ const handleLogOut = useMemoizedFn(() => {
+ setAnchorEl(null);
+ setNowUser({ name: "", uuid: "" })
+ setToken("")
+ navigate("/login")
+ })
+
+
+
+ return (
+ <>
+
+ {nowUser.name != "" && (<>
+ setOpen(true)}
+ >
+
+
+ >)
+ }
+
+
+ {server.data?.serverName ?? "皮肤站"}
+
+
+ {nowUser.name != "" && (
+
+
setAnchorEl(event.currentTarget)}
+ color="inherit"
+ >
+
+
+
+
+ )}
+ {nowUser.name == "" && (
+
+ )}
+
+ >)
+})
+
+const MyList = memo(function MyList(p: { list: ListItem[] }) {
+
+
+ return (
+ <>
+
+ {p.list.map(item =>
+
+ )}
+
+ >
+ )
+})
+
+const MyListItem = function MyListItem(p: ListItem) {
+ const navigate = useNavigate();
+
+ const handleClick = () => {
+ navigate(p.link)
+ }
+
+ return (
+
+
+
+ {p.icon}
+
+
+
+
+ )
+}
+
+const MyDrawer = function MyDrawer() {
+ const nowToken = useAtomValue(token)
+ const setErr = useSetAtom(LayoutAlertErr)
+ const theme = useTheme();
+ const isLg = useMediaQuery(theme.breakpoints.up('lg'))
+ const [open, setOpen] = useAtom(DrawerOpen)
+ const navigate = useNavigate();
+
+ const userinfo = useRequest(() => userInfo(nowToken), {
+ refreshDeps: [nowToken],
+ cacheKey: "/api/v1/user" + nowToken,
+ staleTime: 60000,
+ onError: e => {
+ if (e instanceof ApiErr && e.code == 5) {
+ navigate("/login")
+ }
+ console.warn(e)
+ setErr(String(e))
+ },
+ })
+
+ const userDrawerList = React.useMemo(() => [
+ {
+ icon: ,
+ title: '个人信息',
+ link: '/profile'
+ },
+ {
+ icon: ,
+ title: '皮肤设置',
+ link: '/textures'
+ },
+ {
+ icon: ,
+ title: '账号设置',
+ link: '/security'
+ }
+ ] as ListItem[], [])
+
+ const adminDrawerList = React.useMemo(() => [
+ {
+ icon: ,
+ title: '用户管理',
+ link: '/admin/user'
+ }
+ ] as ListItem[], [])
+
+
+
+ return (<>
+ {userinfo.data && (
+ setOpen(false)}
+ >
+
+ setOpen(false)}>
+ {theme.direction === 'ltr' ? : }
+
+
+
+
+ {userinfo.data?.is_admin && (
+ <>
+
+
+ >)}
+
+ )}
+ >)
+}
+
+export default Layout
\ No newline at end of file
diff --git a/frontend/src/views/Login.tsx b/frontend/src/views/Login.tsx
new file mode 100644
index 0000000..8d1127d
--- /dev/null
+++ b/frontend/src/views/Login.tsx
@@ -0,0 +1,169 @@
+import * as React from 'react';
+import { useState } from 'react';
+import Avatar from '@mui/material/Avatar';
+import Button from '@mui/material/Button';
+import TextField from '@mui/material/TextField';
+import Link from '@mui/material/Link';
+import Grid from '@mui/material/Grid';
+import Box from '@mui/material/Box';
+import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
+import Typography from '@mui/material/Typography';
+import Container from '@mui/material/Container';
+import Snackbar from '@mui/material/Snackbar';
+import Alert from '@mui/material/Alert';
+import { useSetAtom } from 'jotai';
+import { token, user } from '@/store/store'
+import { getConfig, login } from '@/apis/apis'
+import { Link as RouterLink, useNavigate } from "react-router-dom";
+import Loading from '@/components/Loading'
+import CheckInput, { refType } from '@/components/CheckInput'
+import useTitle from '@/hooks/useTitle';
+import CaptchaWidget from '@/components/CaptchaWidget';
+import type { refType as CaptchaWidgetRef } from '@/components/CaptchaWidget'
+import { ApiErr } from '@/apis/error';
+import { useRequest } from 'ahooks';
+
+
+
+export default function SignIn() {
+ const [err, setErr] = useState("");
+ const [loading, setLoading] = useState(false);
+ const setToken = useSetAtom(token)
+ const setUserInfo = useSetAtom(user)
+ const checkList = React.useRef