Compare commits
24 Commits
ai-alt-tex
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
2971fb298e
|
|||
|
d75501860d
|
|||
|
ff886d3002
|
|||
|
48c7d522c1
|
|||
|
531bb8750e
|
|||
|
8572e22c5d
|
|||
|
ea5eb6fa59
|
|||
|
0c72a756c5
|
|||
|
c915df904d
|
|||
|
93a327c634
|
|||
|
3b8b3efa4a
|
|||
|
dd7cd6a944
|
|||
|
ed81662ae5
|
|||
|
7605ccb0aa
|
|||
|
6680ccc023
|
|||
|
1b6763cc3a
|
|||
|
c2d2e6c5a7
|
|||
|
c42401383b
|
|||
|
7e9c618267
|
|||
|
752c93e460
|
|||
|
e83272d8e8
|
|||
|
90deab01b1
|
|||
|
227db7e879
|
|||
|
2015ea6f2e
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -41,3 +41,4 @@ yarn-error.log*
|
||||
next-env.d.ts
|
||||
|
||||
/src/generated/prisma
|
||||
/scripts/
|
||||
|
||||
@ -18,6 +18,12 @@ RUN bunx prisma generate
|
||||
|
||||
# Uncomment the following line in case you want to disable telemetry during the build.
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ARG GIT_SHA=unknown
|
||||
ARG APP_VERSION=0.0.0
|
||||
ARG DEPLOY_ENV=production
|
||||
ENV NEXT_PUBLIC_GIT_SHA=$GIT_SHA \
|
||||
NEXT_PUBLIC_APP_VERSION=$APP_VERSION \
|
||||
NEXT_PUBLIC_DEPLOY_ENV=$DEPLOY_ENV
|
||||
|
||||
# Copy the rest of the code
|
||||
RUN bun run build -d
|
||||
@ -31,6 +37,12 @@ ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV NODE_ENV=production \
|
||||
PORT=3000 \
|
||||
HOSTNAME="0.0.0.0"
|
||||
ARG GIT_SHA=unknown
|
||||
ARG APP_VERSION=0.0.0
|
||||
ARG DEPLOY_ENV=production
|
||||
ENV NEXT_PUBLIC_GIT_SHA=$GIT_SHA \
|
||||
NEXT_PUBLIC_APP_VERSION=$APP_VERSION \
|
||||
NEXT_PUBLIC_DEPLOY_ENV=$DEPLOY_ENV
|
||||
|
||||
RUN groupadd --system --gid 1001 nodejs && \
|
||||
useradd --system --uid 1001 --no-log-init -g nodejs nextjs
|
||||
|
||||
@ -14,11 +14,16 @@ FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
# RUN bunx prisma migrate deploy
|
||||
RUN bunx prisma generate
|
||||
|
||||
# Uncomment the following line in case you want to disable telemetry during the build.
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ARG GIT_SHA=unknown
|
||||
ARG APP_VERSION=0.0.0
|
||||
ARG DEPLOY_ENV=production
|
||||
ENV NEXT_PUBLIC_GIT_SHA=$GIT_SHA \
|
||||
NEXT_PUBLIC_APP_VERSION=$APP_VERSION \
|
||||
NEXT_PUBLIC_DEPLOY_ENV=$DEPLOY_ENV
|
||||
|
||||
# Copy the rest of the code
|
||||
RUN bun run build -d
|
||||
@ -32,6 +37,12 @@ ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV NODE_ENV=production \
|
||||
PORT=3000 \
|
||||
HOSTNAME="0.0.0.0"
|
||||
ARG GIT_SHA=unknown
|
||||
ARG APP_VERSION=0.0.0
|
||||
ARG DEPLOY_ENV=production
|
||||
ENV NEXT_PUBLIC_GIT_SHA=$GIT_SHA \
|
||||
NEXT_PUBLIC_APP_VERSION=$APP_VERSION \
|
||||
NEXT_PUBLIC_DEPLOY_ENV=$DEPLOY_ENV
|
||||
|
||||
RUN groupadd --system --gid 1001 nodejs && \
|
||||
useradd --system --uid 1001 --no-log-init -g nodejs nextjs
|
||||
|
||||
327
bun.lock
327
bun.lock
@ -5,8 +5,8 @@
|
||||
"": {
|
||||
"name": "admin.gaertan.art",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.974.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.974.0",
|
||||
"@aws-sdk/client-s3": "^3.980.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.980.0",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/modifiers": "^9.0.0",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
@ -39,7 +39,7 @@
|
||||
"@radix-ui/react-tooltip": "^1.2.8",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"archiver": "^7.0.1",
|
||||
"better-auth": "^1.4.17",
|
||||
"better-auth": "^1.4.18",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.1.1",
|
||||
@ -48,15 +48,15 @@
|
||||
"dotenv": "^17.2.3",
|
||||
"lowlight": "^3.3.0",
|
||||
"lucide-react": "^0.561.0",
|
||||
"next": "^16.1.4",
|
||||
"next": "16.1.6",
|
||||
"next-themes": "^0.4.6",
|
||||
"node-vibrant": "^4.0.3",
|
||||
"nodemailer": "^7.0.12",
|
||||
"pg": "^8.17.2",
|
||||
"node-vibrant": "^4.0.4",
|
||||
"nodemailer": "^7.0.13",
|
||||
"pg": "^8.18.0",
|
||||
"platejs": "^52.0.17",
|
||||
"react": "19.2.1",
|
||||
"react": "19.2.4",
|
||||
"react-day-picker": "^9.13.0",
|
||||
"react-dom": "19.2.1",
|
||||
"react-dom": "19.2.4",
|
||||
"react-hook-form": "^7.71.1",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"remark-math": "^6.0.0",
|
||||
@ -65,6 +65,7 @@
|
||||
"tailwind-scrollbar-hide": "^4.0.0",
|
||||
"uuid": "^13.0.0",
|
||||
"zod": "^4.3.6",
|
||||
"zustand": "^5.0.8",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.2.0",
|
||||
@ -73,10 +74,10 @@
|
||||
"@types/culori": "^4.0.1",
|
||||
"@types/date-fns": "^2.6.3",
|
||||
"@types/node": "^20.19.30",
|
||||
"@types/nodemailer": "^7.0.5",
|
||||
"@types/nodemailer": "^7.0.9",
|
||||
"@types/pg": "^8.16.0",
|
||||
"@types/react": "^19.2.9",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/react": "19.2.10",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"@types/uuid": "^11.0.0",
|
||||
"prisma": "^7.3.0",
|
||||
"tailwindcss": "^4.1.18",
|
||||
@ -85,6 +86,10 @@
|
||||
},
|
||||
},
|
||||
},
|
||||
"overrides": {
|
||||
"@types/react": "19.2.10",
|
||||
"@types/react-dom": "19.2.3",
|
||||
},
|
||||
"packages": {
|
||||
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||
|
||||
@ -102,83 +107,81 @@
|
||||
|
||||
"@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="],
|
||||
|
||||
"@aws-sdk/client-s3": ["@aws-sdk/client-s3@3.974.0", "", { "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.0", "@aws-sdk/credential-provider-node": "^3.972.1", "@aws-sdk/middleware-bucket-endpoint": "^3.972.1", "@aws-sdk/middleware-expect-continue": "^3.972.1", "@aws-sdk/middleware-flexible-checksums": "^3.972.1", "@aws-sdk/middleware-host-header": "^3.972.1", "@aws-sdk/middleware-location-constraint": "^3.972.1", "@aws-sdk/middleware-logger": "^3.972.1", "@aws-sdk/middleware-recursion-detection": "^3.972.1", "@aws-sdk/middleware-sdk-s3": "^3.972.1", "@aws-sdk/middleware-ssec": "^3.972.1", "@aws-sdk/middleware-user-agent": "^3.972.1", "@aws-sdk/region-config-resolver": "^3.972.1", "@aws-sdk/signature-v4-multi-region": "3.972.0", "@aws-sdk/types": "^3.973.0", "@aws-sdk/util-endpoints": "3.972.0", "@aws-sdk/util-user-agent-browser": "^3.972.1", "@aws-sdk/util-user-agent-node": "^3.972.1", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.21.0", "@smithy/eventstream-serde-browser": "^4.2.8", "@smithy/eventstream-serde-config-resolver": "^4.3.8", "@smithy/eventstream-serde-node": "^4.2.8", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-blob-browser": "^4.2.9", "@smithy/hash-node": "^4.2.8", "@smithy/hash-stream-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/md5-js": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.10", "@smithy/middleware-retry": "^4.4.26", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.8", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.25", "@smithy/util-defaults-mode-node": "^4.2.28", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-stream": "^4.5.10", "@smithy/util-utf8": "^4.2.0", "@smithy/util-waiter": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-X+vpXNJ8cU8Iw1FtDgDHxo9z6RxlXfcTtpdGnKws4rk+tCYKSAor/DG6BRMzbh4E5xAA7DiU1Ny3BTrRRSt/Yg=="],
|
||||
"@aws-sdk/client-s3": ["@aws-sdk/client-s3@3.980.0", "", { "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.5", "@aws-sdk/credential-provider-node": "^3.972.4", "@aws-sdk/middleware-bucket-endpoint": "^3.972.3", "@aws-sdk/middleware-expect-continue": "^3.972.3", "@aws-sdk/middleware-flexible-checksums": "^3.972.3", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-location-constraint": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", "@aws-sdk/middleware-sdk-s3": "^3.972.5", "@aws-sdk/middleware-ssec": "^3.972.3", "@aws-sdk/middleware-user-agent": "^3.972.5", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/signature-v4-multi-region": "3.980.0", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.980.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", "@aws-sdk/util-user-agent-node": "^3.972.3", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.22.0", "@smithy/eventstream-serde-browser": "^4.2.8", "@smithy/eventstream-serde-config-resolver": "^4.3.8", "@smithy/eventstream-serde-node": "^4.2.8", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-blob-browser": "^4.2.9", "@smithy/hash-node": "^4.2.8", "@smithy/hash-stream-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/md5-js": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.12", "@smithy/middleware-retry": "^4.4.29", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.8", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.28", "@smithy/util-defaults-mode-node": "^4.2.31", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-stream": "^4.5.10", "@smithy/util-utf8": "^4.2.0", "@smithy/util-waiter": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-ch8QqKehyn1WOYbd8LyDbWjv84Z9OEj9qUxz8q3IOCU3ftAVkVR0wAuN96a1xCHnpOJcQZo3rOB08RlyKdkGxQ=="],
|
||||
|
||||
"@aws-sdk/client-sesv2": ["@aws-sdk/client-sesv2@3.958.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.957.0", "@aws-sdk/credential-provider-node": "3.958.0", "@aws-sdk/middleware-host-header": "3.957.0", "@aws-sdk/middleware-logger": "3.957.0", "@aws-sdk/middleware-recursion-detection": "3.957.0", "@aws-sdk/middleware-user-agent": "3.957.0", "@aws-sdk/region-config-resolver": "3.957.0", "@aws-sdk/signature-v4-multi-region": "3.957.0", "@aws-sdk/types": "3.957.0", "@aws-sdk/util-endpoints": "3.957.0", "@aws-sdk/util-user-agent-browser": "3.957.0", "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.1", "@smithy/middleware-retry": "^4.4.17", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.16", "@smithy/util-defaults-mode-node": "^4.2.19", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-3x3n8IIxIMAkdpt9wy9zS7MO2lqTcJwQTdHMn6BlD7YUohb+r5Q4KCOEQ2uHWd4WIJv2tlbXnfypHaXReO/WXA=="],
|
||||
"@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.980.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.5", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", "@aws-sdk/middleware-user-agent": "^3.972.5", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.980.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", "@aws-sdk/util-user-agent-node": "^3.972.3", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.22.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.12", "@smithy/middleware-retry": "^4.4.29", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.8", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.28", "@smithy/util-defaults-mode-node": "^4.2.31", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-AhNXQaJ46C1I+lQ+6Kj+L24il5K9lqqIanJd8lMszPmP7bLnmX0wTKK0dxywcvrLdij3zhWttjAKEBNgLtS8/A=="],
|
||||
|
||||
"@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.974.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.0", "@aws-sdk/middleware-host-header": "^3.972.1", "@aws-sdk/middleware-logger": "^3.972.1", "@aws-sdk/middleware-recursion-detection": "^3.972.1", "@aws-sdk/middleware-user-agent": "^3.972.1", "@aws-sdk/region-config-resolver": "^3.972.1", "@aws-sdk/types": "^3.973.0", "@aws-sdk/util-endpoints": "3.972.0", "@aws-sdk/util-user-agent-browser": "^3.972.1", "@aws-sdk/util-user-agent-node": "^3.972.1", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.21.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.10", "@smithy/middleware-retry": "^4.4.26", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.8", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.25", "@smithy/util-defaults-mode-node": "^4.2.28", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-ci+GiM0c4ULo4D79UMcY06LcOLcfvUfiyt8PzNY0vbt5O8BfCPYf4QomwVgkNcLLCYmroO4ge2Yy1EsLUlcD6g=="],
|
||||
|
||||
"@aws-sdk/core": ["@aws-sdk/core@3.973.0", "", { "dependencies": { "@aws-sdk/types": "^3.973.0", "@aws-sdk/xml-builder": "^3.972.1", "@smithy/core": "^3.21.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-qy3Fmt8z4PRInM3ZqJmHihQ2tfCdj/MzbGaZpuHjYjgl1/Gcar4Pyp/zzHXh9hGEb61WNbWgsJcDUhnGIiX1TA=="],
|
||||
"@aws-sdk/core": ["@aws-sdk/core@3.973.5", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@aws-sdk/xml-builder": "^3.972.2", "@smithy/core": "^3.22.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-IMM7xGfLGW6lMvubsA4j6BHU5FPgGAxoQ/NA63KqNLMwTS+PeMBcx8DPHL12Vg6yqOZnqok9Mu4H2BdQyq7gSA=="],
|
||||
|
||||
"@aws-sdk/crc64-nvme": ["@aws-sdk/crc64-nvme@3.972.0", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-ThlLhTqX68jvoIVv+pryOdb5coP1cX1/MaTbB9xkGDCbWbsqQcLqzPxuSoW1DCnAAIacmXCWpzUNOB9pv+xXQw=="],
|
||||
|
||||
"@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.1", "", { "dependencies": { "@aws-sdk/core": "^3.973.0", "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-/etNHqnx96phy/SjI0HRC588o4vKH5F0xfkZ13yAATV7aNrb+5gYGNE6ePWafP+FuZ3HkULSSlJFj0AxgrAqYw=="],
|
||||
"@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.3", "", { "dependencies": { "@aws-sdk/core": "^3.973.5", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-OBYNY4xQPq7Rx+oOhtyuyO0AQvdJSpXRg7JuPNBJH4a1XXIzJQl4UHQTPKZKwfJXmYLpv4+OkcFen4LYmDPd3g=="],
|
||||
|
||||
"@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.1", "", { "dependencies": { "@aws-sdk/core": "^3.973.0", "@aws-sdk/types": "^3.973.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/node-http-handler": "^4.4.8", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/util-stream": "^4.5.10", "tslib": "^2.6.2" } }, "sha512-AeopObGW5lpWbDRZ+t4EAtS7wdfSrHPLeFts7jaBzgIaCCD7TL7jAyAB9Y5bCLOPF+17+GL54djCCsjePljUAw=="],
|
||||
"@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.5", "", { "dependencies": { "@aws-sdk/core": "^3.973.5", "@aws-sdk/types": "^3.973.1", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/node-http-handler": "^4.4.8", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "@smithy/util-stream": "^4.5.10", "tslib": "^2.6.2" } }, "sha512-GpvBgEmSZPvlDekd26Zi+XsI27Qz7y0utUx0g2fSTSiDzhnd1FSa1owuodxR0BcUKNL7U2cOVhhDxgZ4iSoPVg=="],
|
||||
|
||||
"@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.1", "", { "dependencies": { "@aws-sdk/core": "^3.973.0", "@aws-sdk/credential-provider-env": "^3.972.1", "@aws-sdk/credential-provider-http": "^3.972.1", "@aws-sdk/credential-provider-login": "^3.972.1", "@aws-sdk/credential-provider-process": "^3.972.1", "@aws-sdk/credential-provider-sso": "^3.972.1", "@aws-sdk/credential-provider-web-identity": "^3.972.1", "@aws-sdk/nested-clients": "3.974.0", "@aws-sdk/types": "^3.973.0", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-OdbJA3v+XlNDsrYzNPRUwr8l7gw1r/nR8l4r96MDzSBDU8WEo8T6C06SvwaXR8SpzsjO3sq5KMP86wXWg7Rj4g=="],
|
||||
"@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.3", "", { "dependencies": { "@aws-sdk/core": "^3.973.5", "@aws-sdk/credential-provider-env": "^3.972.3", "@aws-sdk/credential-provider-http": "^3.972.5", "@aws-sdk/credential-provider-login": "^3.972.3", "@aws-sdk/credential-provider-process": "^3.972.3", "@aws-sdk/credential-provider-sso": "^3.972.3", "@aws-sdk/credential-provider-web-identity": "^3.972.3", "@aws-sdk/nested-clients": "3.980.0", "@aws-sdk/types": "^3.973.1", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-rMQAIxstP7cLgYfsRGrGOlpyMl0l8JL2mcke3dsIPLWke05zKOFyR7yoJzWCsI/QiIxjRbxpvPiAeKEA6CoYkg=="],
|
||||
|
||||
"@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.1", "", { "dependencies": { "@aws-sdk/core": "^3.973.0", "@aws-sdk/nested-clients": "3.974.0", "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-CccqDGL6ZrF3/EFWZefvKW7QwwRdxlHUO8NVBKNVcNq6womrPDvqB6xc9icACtE0XB0a7PLoSTkAg8bQVkTO2w=="],
|
||||
"@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.3", "", { "dependencies": { "@aws-sdk/core": "^3.973.5", "@aws-sdk/nested-clients": "3.980.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-Gc3O91iVvA47kp2CLIXOwuo5ffo1cIpmmyIewcYjAcvurdFHQ8YdcBe1KHidnbbBO4/ZtywGBACsAX5vr3UdoA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.1", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.1", "@aws-sdk/credential-provider-http": "^3.972.1", "@aws-sdk/credential-provider-ini": "^3.972.1", "@aws-sdk/credential-provider-process": "^3.972.1", "@aws-sdk/credential-provider-sso": "^3.972.1", "@aws-sdk/credential-provider-web-identity": "^3.972.1", "@aws-sdk/types": "^3.973.0", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwXPk9GfuU/xG9tmCyXFVkCr6X3W8ZCoL5Ptb0pbltEx1/LCcg7T+PBqDlPiiinNCD6ilIoMJDWsnJ8ikzZA7Q=="],
|
||||
"@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.4", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.3", "@aws-sdk/credential-provider-http": "^3.972.5", "@aws-sdk/credential-provider-ini": "^3.972.3", "@aws-sdk/credential-provider-process": "^3.972.3", "@aws-sdk/credential-provider-sso": "^3.972.3", "@aws-sdk/credential-provider-web-identity": "^3.972.3", "@aws-sdk/types": "^3.973.1", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-UwerdzosMSY7V5oIZm3NsMDZPv2aSVzSkZxYxIOWHBeKTZlUqW7XpHtJMZ4PZpJ+HMRhgP+MDGQx4THndgqJfQ=="],
|
||||
|
||||
"@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.1", "", { "dependencies": { "@aws-sdk/core": "^3.973.0", "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-bi47Zigu3692SJwdBvo8y1dEwE6B61stCwCFnuRWJVTfiM84B+VTSCV661CSWJmIZzmcy7J5J3kWyxL02iHj0w=="],
|
||||
"@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.3", "", { "dependencies": { "@aws-sdk/core": "^3.973.5", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-xkSY7zjRqeVc6TXK2xr3z1bTLm0wD8cj3lAkproRGaO4Ku7dPlKy843YKnHrUOUzOnMezdZ4xtmFc0eKIDTo2w=="],
|
||||
|
||||
"@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.1", "", { "dependencies": { "@aws-sdk/client-sso": "3.974.0", "@aws-sdk/core": "^3.973.0", "@aws-sdk/token-providers": "3.974.0", "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-dLZVNhM7wSgVUFsgVYgI5hb5Z/9PUkT46pk/SHrSmUqfx6YDvoV4YcPtaiRqviPpEGGiRtdQMEadyOKIRqulUQ=="],
|
||||
"@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.3", "", { "dependencies": { "@aws-sdk/client-sso": "3.980.0", "@aws-sdk/core": "^3.973.5", "@aws-sdk/token-providers": "3.980.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-8Ww3F5Ngk8dZ6JPL/V5LhCU1BwMfQd3tLdoEuzaewX8FdnT633tPr+KTHySz9FK7fFPcz5qG3R5edVEhWQD4AA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.1", "", { "dependencies": { "@aws-sdk/core": "^3.973.0", "@aws-sdk/nested-clients": "3.974.0", "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-YMDeYgi0u687Ay0dAq/pFPKuijrlKTgsaB/UATbxCs/FzZfMiG4If5ksywHmmW7MiYUF8VVv+uou3TczvLrN4w=="],
|
||||
"@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.3", "", { "dependencies": { "@aws-sdk/core": "^3.973.5", "@aws-sdk/nested-clients": "3.980.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-62VufdcH5rRfiRKZRcf1wVbbt/1jAntMj1+J0qAd+r5pQRg2t0/P9/Rz16B1o5/0Se9lVL506LRjrhIJAhYBfA=="],
|
||||
|
||||
"@aws-sdk/middleware-bucket-endpoint": ["@aws-sdk/middleware-bucket-endpoint@3.972.1", "", { "dependencies": { "@aws-sdk/types": "^3.973.0", "@aws-sdk/util-arn-parser": "^3.972.1", "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-config-provider": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-YVvoitBdE8WOpHqIXvv49efT73F4bJ99XH2bi3Dn3mx7WngI4RwHwn/zF5i0q1Wdi5frGSCNF3vuh+pY817//w=="],
|
||||
"@aws-sdk/middleware-bucket-endpoint": ["@aws-sdk/middleware-bucket-endpoint@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-arn-parser": "^3.972.2", "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-config-provider": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-fmbgWYirF67YF1GfD7cg5N6HHQ96EyRNx/rDIrTF277/zTWVuPI2qS/ZHgofwR1NZPe/NWvoppflQY01LrbVLg=="],
|
||||
|
||||
"@aws-sdk/middleware-expect-continue": ["@aws-sdk/middleware-expect-continue@3.972.1", "", { "dependencies": { "@aws-sdk/types": "^3.973.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-6lfl2/J/kutzw/RLu1kjbahsz4vrGPysrdxWaw8fkjLYG+6M6AswocIAZFS/LgAVi/IWRwPTx9YC0/NH2wDrSw=="],
|
||||
"@aws-sdk/middleware-expect-continue": ["@aws-sdk/middleware-expect-continue@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-4msC33RZsXQpUKR5QR4HnvBSNCPLGHmB55oDiROqqgyOc+TOfVu2xgi5goA7ms6MdZLeEh2905UfWMnMMF4mRg=="],
|
||||
|
||||
"@aws-sdk/middleware-flexible-checksums": ["@aws-sdk/middleware-flexible-checksums@3.972.1", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", "@aws-crypto/util": "5.2.0", "@aws-sdk/core": "^3.973.0", "@aws-sdk/crc64-nvme": "3.972.0", "@aws-sdk/types": "^3.973.0", "@smithy/is-array-buffer": "^4.2.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.10", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kjVVREpqeUkYQsXr78AcsJbEUlxGH7+H6yS7zkjrnu6HyEVxbdSndkKX6VpKneFOihjCAhIXlk4wf3butDHkNQ=="],
|
||||
"@aws-sdk/middleware-flexible-checksums": ["@aws-sdk/middleware-flexible-checksums@3.972.3", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", "@aws-crypto/util": "5.2.0", "@aws-sdk/core": "^3.973.5", "@aws-sdk/crc64-nvme": "3.972.0", "@aws-sdk/types": "^3.973.1", "@smithy/is-array-buffer": "^4.2.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.10", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-MkNGJ6qB9kpsLwL18kC/ZXppsJbftHVGCisqpEVbTQsum8CLYDX1Bmp/IvhRGNxsqCO2w9/4PwhDKBjG3Uvr4Q=="],
|
||||
|
||||
"@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.972.1", "", { "dependencies": { "@aws-sdk/types": "^3.973.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-/R82lXLPmZ9JaUGSUdKtBp2k/5xQxvBT3zZWyKiBOhyulFotlfvdlrO8TnqstBimsl4lYEYySDL+W6ldFh6ALg=="],
|
||||
"@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-aknPTb2M+G3s+0qLCx4Li/qGZH8IIYjugHMv15JTYMe6mgZO8VBpYgeGYsNMGCqCZOcWzuf900jFBG5bopfzmA=="],
|
||||
|
||||
"@aws-sdk/middleware-location-constraint": ["@aws-sdk/middleware-location-constraint@3.972.1", "", { "dependencies": { "@aws-sdk/types": "^3.973.0", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-YisPaCbvBk9gY5aUI8jDMDKXsLZ9Fet0WYj1MviK8tZYMgxBIYHM6l3O/OHaAIujojZvamd9F3haYYYWp5/V3w=="],
|
||||
"@aws-sdk/middleware-location-constraint": ["@aws-sdk/middleware-location-constraint@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-nIg64CVrsXp67vbK0U1/Is8rik3huS3QkRHn2DRDx4NldrEFMgdkZGI/+cZMKD9k4YOS110Dfu21KZLHrFA/1g=="],
|
||||
|
||||
"@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.972.1", "", { "dependencies": { "@aws-sdk/types": "^3.973.0", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-JGgFl6cHg9G2FHu4lyFIzmFN8KESBiRr84gLC3Aeni0Gt1nKm+KxWLBuha/RPcXxJygGXCcMM4AykkIwxor8RA=="],
|
||||
"@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-Ftg09xNNRqaz9QNzlfdQWfpqMCJbsQdnZVJP55jfhbKi1+FTWxGuvfPoBhDHIovqWKjqbuiew3HuhxbJ0+OjgA=="],
|
||||
|
||||
"@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.972.1", "", { "dependencies": { "@aws-sdk/types": "^3.973.0", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-taGzNRe8vPHjnliqXIHp9kBgIemLE/xCaRTMH1NH0cncHeaPcjxtnCroAAM9aOlPuKvBe2CpZESyvM1+D8oI7Q=="],
|
||||
"@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-PY57QhzNuXHnwbJgbWYTrqIDHYSeOlhfYERTAuc16LKZpTZRJUjzBFokp9hF7u1fuGeE3D70ERXzdbMBOqQz7Q=="],
|
||||
|
||||
"@aws-sdk/middleware-sdk-s3": ["@aws-sdk/middleware-sdk-s3@3.972.1", "", { "dependencies": { "@aws-sdk/core": "^3.973.0", "@aws-sdk/types": "^3.973.0", "@aws-sdk/util-arn-parser": "^3.972.1", "@smithy/core": "^3.21.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.10", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-q/hK0ZNf/aafFRv2wIlDM3p+izi5cXwktVNvRvW646A0MvVZmT4/vwadv/jPA9AORFbnpyf/0luxiMz181f9yg=="],
|
||||
"@aws-sdk/middleware-sdk-s3": ["@aws-sdk/middleware-sdk-s3@3.972.5", "", { "dependencies": { "@aws-sdk/core": "^3.973.5", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-arn-parser": "^3.972.2", "@smithy/core": "^3.22.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.10", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-3IgeIDiQ15tmMBFIdJ1cTy3A9rXHGo+b9p22V38vA3MozeMyVC8VmCYdDLA0iMWo4VHA9LDJTgCM0+xU3wjBOg=="],
|
||||
|
||||
"@aws-sdk/middleware-ssec": ["@aws-sdk/middleware-ssec@3.972.1", "", { "dependencies": { "@aws-sdk/types": "^3.973.0", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-fLtRTPd/MxJT2drJKft2GVGKm35PiNEeQ1Dvz1vc/WhhgAteYrp4f1SfSgjgLaYWGMExESJL4bt8Dxqp6tVsog=="],
|
||||
"@aws-sdk/middleware-ssec": ["@aws-sdk/middleware-ssec@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-dU6kDuULN3o3jEHcjm0c4zWJlY1zWVkjG9NPe9qxYLLpcbdj5kRYBS2DdWYD+1B9f910DezRuws7xDEqKkHQIg=="],
|
||||
|
||||
"@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.972.1", "", { "dependencies": { "@aws-sdk/core": "^3.973.0", "@aws-sdk/types": "^3.973.0", "@aws-sdk/util-endpoints": "3.972.0", "@smithy/core": "^3.21.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-6SVg4pY/9Oq9MLzO48xuM3lsOb8Rxg55qprEtFRpkUmuvKij31f5SQHEGxuiZ4RqIKrfjr2WMuIgXvqJ0eJsPA=="],
|
||||
"@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.972.5", "", { "dependencies": { "@aws-sdk/core": "^3.973.5", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.980.0", "@smithy/core": "^3.22.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-TVZQ6PWPwQbahUI8V+Er+gS41ctIawcI/uMNmQtQ7RMcg3JYn6gyKAFKUb3HFYx2OjYlx1u11sETSwwEUxVHTg=="],
|
||||
|
||||
"@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.974.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.0", "@aws-sdk/middleware-host-header": "^3.972.1", "@aws-sdk/middleware-logger": "^3.972.1", "@aws-sdk/middleware-recursion-detection": "^3.972.1", "@aws-sdk/middleware-user-agent": "^3.972.1", "@aws-sdk/region-config-resolver": "^3.972.1", "@aws-sdk/types": "^3.973.0", "@aws-sdk/util-endpoints": "3.972.0", "@aws-sdk/util-user-agent-browser": "^3.972.1", "@aws-sdk/util-user-agent-node": "^3.972.1", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.21.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.10", "@smithy/middleware-retry": "^4.4.26", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.8", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.25", "@smithy/util-defaults-mode-node": "^4.2.28", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-k3dwdo/vOiHMJc9gMnkPl1BA5aQfTrZbz+8fiDkWrPagqAioZgmo5oiaOaeX0grObfJQKDtcpPFR4iWf8cgl8Q=="],
|
||||
"@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.980.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.5", "@aws-sdk/middleware-host-header": "^3.972.3", "@aws-sdk/middleware-logger": "^3.972.3", "@aws-sdk/middleware-recursion-detection": "^3.972.3", "@aws-sdk/middleware-user-agent": "^3.972.5", "@aws-sdk/region-config-resolver": "^3.972.3", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-endpoints": "3.980.0", "@aws-sdk/util-user-agent-browser": "^3.972.3", "@aws-sdk/util-user-agent-node": "^3.972.3", "@smithy/config-resolver": "^4.4.6", "@smithy/core": "^3.22.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", "@smithy/middleware-endpoint": "^4.4.12", "@smithy/middleware-retry": "^4.4.29", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.8", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.28", "@smithy/util-defaults-mode-node": "^4.2.31", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-/dONY5xc5/CCKzOqHZCTidtAR4lJXWkGefXvTRKdSKMGaYbbKsxDckisd6GfnvPSLxWtvQzwgRGRutMRoYUApQ=="],
|
||||
|
||||
"@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.972.1", "", { "dependencies": { "@aws-sdk/types": "^3.973.0", "@smithy/config-resolver": "^4.4.6", "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-voIY8RORpxLAEgEkYaTFnkaIuRwVBEc+RjVZYcSSllPV+ZEKAacai6kNhJeE3D70Le+JCfvRb52tng/AVHY+jQ=="],
|
||||
"@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/config-resolver": "^4.4.6", "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-v4J8qYAWfOMcZ4MJUyatntOicTzEMaU7j3OpkRCGGFSL2NgXQ5VbxauIyORA+pxdKZ0qQG2tCQjQjZDlXEC3Ow=="],
|
||||
|
||||
"@aws-sdk/s3-request-presigner": ["@aws-sdk/s3-request-presigner@3.974.0", "", { "dependencies": { "@aws-sdk/signature-v4-multi-region": "3.972.0", "@aws-sdk/types": "^3.973.0", "@aws-sdk/util-format-url": "^3.972.1", "@smithy/middleware-endpoint": "^4.4.10", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-tApmJb4XXBdNQzxTYIBq9aYj8vjJqiMPyeUF25wzvGjLQfXgvcv5sTR4yyzXBxRc8+O7quWDBgMJGtcNerapRQ=="],
|
||||
"@aws-sdk/s3-request-presigner": ["@aws-sdk/s3-request-presigner@3.980.0", "", { "dependencies": { "@aws-sdk/signature-v4-multi-region": "3.980.0", "@aws-sdk/types": "^3.973.1", "@aws-sdk/util-format-url": "^3.972.3", "@smithy/middleware-endpoint": "^4.4.12", "@smithy/protocol-http": "^5.3.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-qX1Ptvja9Le0Wt1VadgsJ7Kw8Xf57pTIVmIcvYD5HrdAot71qgXdfBtcbuvNKZPeD+HfcUITwxxHpDiXfSoTsA=="],
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.972.0", "", { "dependencies": { "@aws-sdk/middleware-sdk-s3": "3.972.0", "@aws-sdk/types": "3.972.0", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-2udiRijmjpN81Pvajje4TsjbXDZNP6K9bYUanBYH8hXa/tZG5qfGCySD+TyX0sgDxCQmEDMg3LaQdfjNHBDEgQ=="],
|
||||
"@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.980.0", "", { "dependencies": { "@aws-sdk/middleware-sdk-s3": "^3.972.5", "@aws-sdk/types": "^3.973.1", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-tO2jBj+ZIVM0nEgi1SyxWtaYGpuAJdsrugmWcI3/U2MPWCYsrvKasUo0026NvJJao38wyUq9B8XTG8Xu53j/VA=="],
|
||||
|
||||
"@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.974.0", "", { "dependencies": { "@aws-sdk/core": "^3.973.0", "@aws-sdk/nested-clients": "3.974.0", "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-cBykL0LiccKIgNhGWvQRTPvsBLPZxnmJU3pYxG538jpFX8lQtrCy1L7mmIHNEdxIdIGEPgAEHF8/JQxgBToqUQ=="],
|
||||
"@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.980.0", "", { "dependencies": { "@aws-sdk/core": "^3.973.5", "@aws-sdk/nested-clients": "3.980.0", "@aws-sdk/types": "^3.973.1", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-1nFileg1wAgDmieRoj9dOawgr2hhlh7xdvcH57b1NnqfPaVlcqVJyPc6k3TLDUFPY69eEwNxdGue/0wIz58vjA=="],
|
||||
|
||||
"@aws-sdk/types": ["@aws-sdk/types@3.973.0", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-jYIdB7a7jhRTvyb378nsjyvJh1Si+zVduJ6urMNGpz8RjkmHZ+9vM2H07XaIB2Cfq0GhJRZYOfUCH8uqQhqBkQ=="],
|
||||
"@aws-sdk/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="],
|
||||
|
||||
"@aws-sdk/util-arn-parser": ["@aws-sdk/util-arn-parser@3.972.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-XnNit6H9PPHhqUXW/usjX6JeJ6Pm8ZNqivTjmNjgWHeOfVpblUc/MTic02UmCNR0jJLPjQ3mBKiMen0tnkNQjQ=="],
|
||||
"@aws-sdk/util-arn-parser": ["@aws-sdk/util-arn-parser@3.972.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-VkykWbqMjlSgBFDyrY3nOSqupMc6ivXuGmvci6Q3NnLq5kC+mKQe2QBZ4nrWRE/jqOxeFP2uYzLtwncYYcvQDg=="],
|
||||
|
||||
"@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.972.0", "", { "dependencies": { "@aws-sdk/types": "3.972.0", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-endpoints": "^3.2.8", "tslib": "^2.6.2" } }, "sha512-6JHsl1V/a1ZW8D8AFfd4R52fwZPnZ5H4U6DS8m/bWT8qad72NvbOFAC7U2cDtFs2TShqUO3TEiX/EJibtY3ijg=="],
|
||||
"@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.980.0", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-endpoints": "^3.2.8", "tslib": "^2.6.2" } }, "sha512-AjKBNEc+rjOZQE1HwcD9aCELqg1GmUj1rtICKuY8cgwB73xJ4U/kNyqKKpN2k9emGqlfDY2D8itIp/vDc6OKpw=="],
|
||||
|
||||
"@aws-sdk/util-format-url": ["@aws-sdk/util-format-url@3.972.1", "", { "dependencies": { "@aws-sdk/types": "^3.973.0", "@smithy/querystring-builder": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-8wJ4/XOLU/RIYBHsXsIOTR04bNmalC8F2YPMyf3oL8YC750M3Rv5WGywW0Fo07HCv770KXJOzVq03Gyl68moFg=="],
|
||||
"@aws-sdk/util-format-url": ["@aws-sdk/util-format-url@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/querystring-builder": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-n7F2ycckcKFXa01vAsT/SJdjFHfKH9s96QHcs5gn8AaaigASICeME8WdUL9uBp8XV/OVwEt8+6gzn6KFUgQa8g=="],
|
||||
|
||||
"@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.953.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-mPxK+I1LcrgC/RSa3G5AMAn8eN2Ay0VOgw8lSRmV1jCtO+iYvNeCqOdxoJUjOW6I5BA4niIRWqVORuRP07776Q=="],
|
||||
|
||||
"@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.972.1", "", { "dependencies": { "@aws-sdk/types": "^3.973.0", "@smithy/types": "^4.12.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-IgF55NFmJX8d9Wql9M0nEpk2eYbuD8G4781FN4/fFgwTXBn86DvlZJuRWDCMcMqZymnBVX7HW9r+3r9ylqfW0w=="],
|
||||
"@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.972.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.1", "@smithy/types": "^4.12.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-JurOwkRUcXD/5MTDBcqdyQ9eVedtAsZgw5rBwktsPTN7QtPiS2Ld1jkJepNgYoCufz1Wcut9iup7GJDoIHp8Fw=="],
|
||||
|
||||
"@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.972.1", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "^3.972.1", "@aws-sdk/types": "^3.973.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-oIs4JFcADzoZ0c915R83XvK2HltWupxNsXUIuZse2rgk7b97zTpkxaqXiH0h9ylh31qtgo/t8hp4tIqcsMrEbQ=="],
|
||||
"@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.972.3", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "^3.972.5", "@aws-sdk/types": "^3.973.1", "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-gqG+02/lXQtO0j3US6EVnxtwwoXQC5l2qkhLCrqUrqdtcQxV7FDMbm9wLjKqoronSHyELGTjbFKK/xV5q1bZNA=="],
|
||||
|
||||
"@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" } }, "sha512-6zZGlPOqn7Xb+25MAXGb1JhgvaC5HjZj6GzszuVrnEgbhvzBRFGKYemuHBV4bho+dtqeYKPgaZUv7/e80hIGNg=="],
|
||||
"@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.2", "", { "dependencies": { "@smithy/types": "^4.12.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" } }, "sha512-jGOOV/bV1DhkkUhHiZ3/1GZ67cZyOXaDb7d1rYD6ZiXf5V9tBNOcgqXwRRPvrCbYaFRa1pPMFb3ZjqjWpR3YfA=="],
|
||||
|
||||
"@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.2", "", {}, "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg=="],
|
||||
|
||||
"@better-auth/core": ["@better-auth/core@1.4.17", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.3.5" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-call": "1.1.8", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-WSaEQDdUO6B1CzAmissN6j0lx9fM9lcslEYzlApB5UzFaBeAOHNUONTdglSyUs6/idiZBoRvt0t/qMXCgIU8ug=="],
|
||||
"@better-auth/core": ["@better-auth/core@1.4.18", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.3.5" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-call": "1.1.8", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-q+awYgC7nkLEBdx2sW0iJjkzgSHlIxGnOpsN1r/O1+a4m7osJNHtfK2mKJSL1I+GfNyIlxJF8WvD/NLuYMpmcg=="],
|
||||
|
||||
"@better-auth/telemetry": ["@better-auth/telemetry@1.4.17", "", { "dependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21" }, "peerDependencies": { "@better-auth/core": "1.4.17" } }, "sha512-R1BC4e/bNjQbXu7lG6ubpgmsPj7IMqky5DvMlzAtnAJWJhh99pMh/n6w5gOHa0cqDZgEAuj75IPTxv+q3YiInA=="],
|
||||
"@better-auth/telemetry": ["@better-auth/telemetry@1.4.18", "", { "dependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21" }, "peerDependencies": { "@better-auth/core": "1.4.18" } }, "sha512-e5rDF8S4j3Um/0LIVATL2in9dL4lfO2fr2v1Wio4qTMRbfxqnUDTa+6SZtwdeJrbc4O+a3c+IyIpjG9Q/6GpfQ=="],
|
||||
|
||||
"@better-auth/utils": ["@better-auth/utils@0.3.0", "", {}, "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw=="],
|
||||
|
||||
@ -328,23 +331,23 @@
|
||||
|
||||
"@mrleebo/prisma-ast": ["@mrleebo/prisma-ast@0.13.1", "", { "dependencies": { "chevrotain": "^10.5.0", "lilconfig": "^2.1.0" } }, "sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw=="],
|
||||
|
||||
"@next/env": ["@next/env@16.1.4", "", {}, "sha512-gkrXnZyxPUy0Gg6SrPQPccbNVLSP3vmW8LU5dwEttEEC1RwDivk8w4O+sZIjFvPrSICXyhQDCG+y3VmjlJf+9A=="],
|
||||
"@next/env": ["@next/env@16.1.6", "", {}, "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ=="],
|
||||
|
||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.1.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-T8atLKuvk13XQUdVLCv1ZzMPgLPW0+DWWbHSQXs0/3TjPrKNxTmUIhOEaoEyl3Z82k8h/gEtqyuoZGv6+Ugawg=="],
|
||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.1.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw=="],
|
||||
|
||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.1.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-AKC/qVjUGUQDSPI6gESTx0xOnOPQ5gttogNS3o6bA83yiaSZJek0Am5yXy82F1KcZCx3DdOwdGPZpQCluonuxg=="],
|
||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.1.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ=="],
|
||||
|
||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.1.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-POQ65+pnYOkZNdngWfMEt7r53bzWiKkVNbjpmCt1Zb3V6lxJNXSsjwRuTQ8P/kguxDC8LRkqaL3vvsFrce4dMQ=="],
|
||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw=="],
|
||||
|
||||
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.1.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-3Wm0zGYVCs6qDFAiSSDL+Z+r46EdtCv/2l+UlIdMbAq9hPJBvGu/rZOeuvCaIUjbArkmXac8HnTyQPJFzFWA0Q=="],
|
||||
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ=="],
|
||||
|
||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.1.4", "", { "os": "linux", "cpu": "x64" }, "sha512-lWAYAezFinaJiD5Gv8HDidtsZdT3CDaCeqoPoJjeB57OqzvMajpIhlZFce5sCAH6VuX4mdkxCRqecCJFwfm2nQ=="],
|
||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ=="],
|
||||
|
||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.1.4", "", { "os": "linux", "cpu": "x64" }, "sha512-fHaIpT7x4gA6VQbdEpYUXRGyge/YbRrkG6DXM60XiBqDM2g2NcrsQaIuj375egnGFkJow4RHacgBOEsHfGbiUw=="],
|
||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg=="],
|
||||
|
||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.1.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-MCrXxrTSE7jPN1NyXJr39E+aNFBrQZtO154LoCz7n99FuKqJDekgxipoodLNWdQP7/DZ5tKMc/efybx1l159hw=="],
|
||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.1.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw=="],
|
||||
|
||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-JSVlm9MDhmTXw/sO2PE/MRj+G6XOSMZB+BcZ0a7d6KwVFZVpkHcb2okyoYFBaco6LeiL53BBklRlOrDDbOeE5w=="],
|
||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.1.6", "", { "os": "win32", "cpu": "x64" }, "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A=="],
|
||||
|
||||
"@noble/ciphers": ["@noble/ciphers@2.1.1", "", {}, "sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw=="],
|
||||
|
||||
@ -496,7 +499,7 @@
|
||||
|
||||
"@smithy/config-resolver": ["@smithy/config-resolver@4.4.6", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ=="],
|
||||
|
||||
"@smithy/core": ["@smithy/core@3.21.1", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.9", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.10", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-NUH8R4O6FkN8HKMojzbGg/5pNjsfTjlMmeFclyPfPaXXUrbr5TzhWgbf7t92wfrpCHRgpjyz7ffASIS3wX28aA=="],
|
||||
"@smithy/core": ["@smithy/core@3.22.0", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.9", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.10", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-6vjCHD6vaY8KubeNw2Fg3EK0KLGQYdldG4fYgQmA0xSW0dJ8G2xFhSOdrlUakWVoP5JuWHtFODg3PNd/DN3FDA=="],
|
||||
|
||||
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.8", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw=="],
|
||||
|
||||
@ -526,9 +529,9 @@
|
||||
|
||||
"@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.8", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A=="],
|
||||
|
||||
"@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.11", "", { "dependencies": { "@smithy/core": "^3.21.1", "@smithy/middleware-serde": "^4.2.9", "@smithy/node-config-provider": "^4.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-/WqsrycweGGfb9sSzME4CrsuayjJF6BueBmkKlcbeU5q18OhxRrvvKlmfw3tpDsK5ilx2XUJvoukwxHB0nHs/Q=="],
|
||||
"@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.12", "", { "dependencies": { "@smithy/core": "^3.22.0", "@smithy/middleware-serde": "^4.2.9", "@smithy/node-config-provider": "^4.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-9JMKHVJtW9RysTNjcBZQHDwB0p3iTP6B1IfQV4m+uCevkVd/VuLgwfqk5cnI4RHcp4cPwoIvxQqN4B1sxeHo8Q=="],
|
||||
|
||||
"@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.27", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/service-error-classification": "^4.2.8", "@smithy/smithy-client": "^4.10.12", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-xFUYCGRVsfgiN5EjsJJSzih9+yjStgMTCLANPlf0LVQkPDYCe0hz97qbdTZosFOiYlGBlHYityGRxrQ/hxhfVQ=="],
|
||||
"@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.29", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/service-error-classification": "^4.2.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-bmTn75a4tmKRkC5w61yYQLb3DmxNzB8qSVu9SbTYqW6GAL0WXO2bDZuMAn/GJSbOdHEdjZvWxe+9Kk015bw6Cg=="],
|
||||
|
||||
"@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.9", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ=="],
|
||||
|
||||
@ -552,7 +555,7 @@
|
||||
|
||||
"@smithy/signature-v4": ["@smithy/signature-v4@5.3.8", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg=="],
|
||||
|
||||
"@smithy/smithy-client": ["@smithy/smithy-client@4.10.12", "", { "dependencies": { "@smithy/core": "^3.21.1", "@smithy/middleware-endpoint": "^4.4.11", "@smithy/middleware-stack": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-stream": "^4.5.10", "tslib": "^2.6.2" } }, "sha512-VKO/HKoQ5OrSHW6AJUmEnUKeXI1/5LfCwO9cwyao7CmLvGnZeM1i36Lyful3LK1XU7HwTVieTqO1y2C/6t3qtA=="],
|
||||
"@smithy/smithy-client": ["@smithy/smithy-client@4.11.1", "", { "dependencies": { "@smithy/core": "^3.22.0", "@smithy/middleware-endpoint": "^4.4.12", "@smithy/middleware-stack": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-stream": "^4.5.10", "tslib": "^2.6.2" } }, "sha512-SERgNg5Z1U+jfR6/2xPYjSEHY1t3pyTHC/Ma3YQl6qWtmiL42bvNId3W/oMUWIwu7ekL2FMPdqAmwbQegM7HeQ=="],
|
||||
|
||||
"@smithy/types": ["@smithy/types@4.12.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw=="],
|
||||
|
||||
@ -568,9 +571,9 @@
|
||||
|
||||
"@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="],
|
||||
|
||||
"@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.26", "", { "dependencies": { "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.10.12", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-vva0dzYUTgn7DdE0uaha10uEdAgmdLnNFowKFjpMm6p2R0XDk5FHPX3CBJLzWQkQXuEprsb0hGz9YwbicNWhjw=="],
|
||||
"@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.28", "", { "dependencies": { "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-/9zcatsCao9h6g18p/9vH9NIi5PSqhCkxQ/tb7pMgRFnqYp9XUOyOlGPDMHzr8n5ih6yYgwJEY2MLEobUgi47w=="],
|
||||
|
||||
"@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.29", "", { "dependencies": { "@smithy/config-resolver": "^4.4.6", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.10.12", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-c6D7IUBsZt/aNnTBHMTf+OVh+h/JcxUUgfTcIJaWRe6zhOum1X+pNKSZtZ+7fbOn5I99XVFtmrnXKv8yHHErTQ=="],
|
||||
"@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.31", "", { "dependencies": { "@smithy/config-resolver": "^4.4.6", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-JTvoApUXA5kbpceI2vuqQzRjeTbLpx1eoa5R/YEZbTgtxvIB7AQZxFJ0SEyfCpgPCyVV9IT7we+ytSeIB3CyWA=="],
|
||||
|
||||
"@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.8", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw=="],
|
||||
|
||||
@ -654,11 +657,11 @@
|
||||
|
||||
"@types/node": ["@types/node@20.19.30", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g=="],
|
||||
|
||||
"@types/nodemailer": ["@types/nodemailer@7.0.5", "", { "dependencies": { "@aws-sdk/client-sesv2": "^3.839.0", "@types/node": "*" } }, "sha512-7WtR4MFJUNN2UFy0NIowBRJswj5KXjXDhlZY43Hmots5eGu5q/dTeFd/I6GgJA/qj3RqO6dDy4SvfcV3fOVeIA=="],
|
||||
"@types/nodemailer": ["@types/nodemailer@7.0.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-vI8oF1M+8JvQhsId0Pc38BdUP2evenIIys7c7p+9OZXSPOH5c1dyINP1jT8xQ2xPuBUXmIC87s+91IZMDjH8Ow=="],
|
||||
|
||||
"@types/pg": ["@types/pg@8.16.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ=="],
|
||||
|
||||
"@types/react": ["@types/react@19.2.9", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA=="],
|
||||
"@types/react": ["@types/react@19.2.10", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw=="],
|
||||
|
||||
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
||||
|
||||
@ -674,27 +677,27 @@
|
||||
|
||||
"@udecode/utils": ["@udecode/utils@52.0.1", "", {}, "sha512-T/qa4++J2MMY9CbhZ05ONpcpkvsRV0uBvOfMhhYWKkAND4DSVAVzmZTV7WQ5fjGq81agAped0WQxcqsEg617uQ=="],
|
||||
|
||||
"@vibrant/color": ["@vibrant/color@4.0.0", "", {}, "sha512-S9ItdqS1135wTXoIIqAJu8df9dqlOo6Boc5Y4MGsBTu9UmUOvOwfj5b4Ga6S5yrLAKmKYIactkz7zYJdMddkig=="],
|
||||
"@vibrant/color": ["@vibrant/color@4.0.4", "", {}, "sha512-Fq2tAszz4QOPWfHZ+KuEAchXUD8i594BM2fOJt8dI/fvYbiVoBycBF/BlNH6F4IWBubxXoPqD4JmmAHvFYbNew=="],
|
||||
|
||||
"@vibrant/core": ["@vibrant/core@4.0.0", "", { "dependencies": { "@vibrant/color": "^4.0.0", "@vibrant/generator": "^4.0.0", "@vibrant/image": "^4.0.0", "@vibrant/quantizer": "^4.0.0", "@vibrant/worker": "^4.0.0" } }, "sha512-fqlVRUTDjEws9VNKvI3cDXM4wUT7fMFS+cVqEjJk3im+R5EvjJzPF6OAbNhfPzW04NvHNE555eY9FfhYuX3PRw=="],
|
||||
"@vibrant/core": ["@vibrant/core@4.0.4", "", { "dependencies": { "@vibrant/color": "^4.0.4", "@vibrant/generator": "^4.0.4", "@vibrant/image": "^4.0.4", "@vibrant/quantizer": "^4.0.4", "@vibrant/worker": "^4.0.4" } }, "sha512-yZ0XSpW2biKyaJPpBC31AVYgn7NseKSO2q3KNMmDrkL2qC6TEWsBMnSQ28n0m///chZELXpQLx1CCOsWg5pj8w=="],
|
||||
|
||||
"@vibrant/generator": ["@vibrant/generator@4.0.0", "", { "dependencies": { "@vibrant/color": "^4.0.0", "@vibrant/types": "^4.0.0" } }, "sha512-CqKAjmgHVDXJVo3Q5+9pUJOvksR7cN3bzx/6MbURYh7lA4rhsIewkUK155M6q0vfcUN3ETi/eTneCi0tLuM2Sg=="],
|
||||
"@vibrant/generator": ["@vibrant/generator@4.0.4", "", { "dependencies": { "@vibrant/color": "^4.0.4", "@vibrant/types": "^4.0.4" } }, "sha512-rwq8PnlpKdch4YqaA1FAwdm71gKE2cMrUsbu72TqRFGa8rpP1roaZlQCVXIIwElXVc3r9axZyAcqyTLaMjhrTg=="],
|
||||
|
||||
"@vibrant/generator-default": ["@vibrant/generator-default@4.0.3", "", { "dependencies": { "@vibrant/color": "^4.0.0", "@vibrant/generator": "^4.0.0" } }, "sha512-HZlfp19sDokODEkZF4p70QceARHgjP3a1Dmxg+dlblYMJM98jPq+azA0fzqKNR7R17JJNHxexpJEepEsNlG0gw=="],
|
||||
"@vibrant/generator-default": ["@vibrant/generator-default@4.0.4", "", { "dependencies": { "@vibrant/color": "^4.0.4", "@vibrant/generator": "^4.0.4" } }, "sha512-QeVDeH2dz9lityvJCb84Ml4hlBTElwCpU7SVpiDFBh6gPoCLnzcb1H9G4NgG3hOlAPyrBM+Ivq1Pg+1lZj5Ywg=="],
|
||||
|
||||
"@vibrant/image": ["@vibrant/image@4.0.0", "", { "dependencies": { "@vibrant/color": "^4.0.0" } }, "sha512-Asv/7R/L701norosgvbjOVkodFiwcFihkXixA/gbAd6C+5GCts1Wm1NPk14FNKnM7eKkfAN+0wwPkdOH+PY/YA=="],
|
||||
"@vibrant/image": ["@vibrant/image@4.0.4", "", { "dependencies": { "@vibrant/color": "^4.0.4" } }, "sha512-NBIJj7umfDRVpFjJHQo1AFSCWCzQyjfil+Yxu7W62PEL72GPCif0CDiglPkvVF8QhDLmnx/x1k3LIBb9jWF2sw=="],
|
||||
|
||||
"@vibrant/image-browser": ["@vibrant/image-browser@4.0.0", "", { "dependencies": { "@vibrant/image": "^4.0.0" } }, "sha512-mXckzvJWiP575Y/wNtP87W/TPgyJoGlPBjW4E9YmNS6n4Jb6RqyHQA0ZVulqDslOxjSsihDzY7gpAORRclaoLg=="],
|
||||
"@vibrant/image-browser": ["@vibrant/image-browser@4.0.4", "", { "dependencies": { "@vibrant/image": "^4.0.4" } }, "sha512-7qVyAm+z9t98iwMDzUgGCwgRg0KBB5RXQFgiO2Um5Izd1wO7BKC0SHVEz2k7sRx3XNfBf+JExp8quPrvSz17gg=="],
|
||||
|
||||
"@vibrant/image-node": ["@vibrant/image-node@4.0.0", "", { "dependencies": { "@jimp/custom": "^0.22.12", "@jimp/plugin-resize": "^0.22.12", "@jimp/types": "^0.22.12", "@vibrant/image": "^4.0.0" } }, "sha512-m7yfnQtmo2y8z+tOjRFBx6q/qGnhl/ax2uCaj4TBkm4TtXfR4Dsn90wT6OWXmCFFzxIKHXKKEBShkxR+4RHseA=="],
|
||||
"@vibrant/image-node": ["@vibrant/image-node@4.0.4", "", { "dependencies": { "@jimp/custom": "^0.22.12", "@jimp/plugin-resize": "^0.22.12", "@jimp/types": "^0.22.12", "@vibrant/image": "^4.0.4" } }, "sha512-aG8Ukt9oTa6FWaAV5oBKsBetkKASWH31hZiFJ2R1291f3TZlphUyQTJz5TubucIRsCEl4dgG1xyxFPgse2IABA=="],
|
||||
|
||||
"@vibrant/quantizer": ["@vibrant/quantizer@4.0.0", "", { "dependencies": { "@vibrant/color": "^4.0.0", "@vibrant/image": "^4.0.0", "@vibrant/types": "^4.0.0" } }, "sha512-YDGxmCv/RvHFtZghDlVRwH5GMxdGGozWS1JpUOUt73/F5zAKGiiier8F31K1npIXARn6/Gspvg/Rbg7qqyEr2A=="],
|
||||
"@vibrant/quantizer": ["@vibrant/quantizer@4.0.4", "", { "dependencies": { "@vibrant/color": "^4.0.4", "@vibrant/image": "^4.0.4", "@vibrant/types": "^4.0.4" } }, "sha512-722CooC2W4mlBiv+zyAsIrIvARnMCN/P2Muo8bnWd0SQlVWFtQnFxJWGOUPOPS4DGe3pGoqmNfvS0let4dICZQ=="],
|
||||
|
||||
"@vibrant/quantizer-mmcq": ["@vibrant/quantizer-mmcq@4.0.0", "", { "dependencies": { "@vibrant/color": "^4.0.0", "@vibrant/image": "^4.0.0", "@vibrant/quantizer": "^4.0.0" } }, "sha512-TZqNiRoGGyCP8fH1XE6rvhFwLNv9D8MP1Xhz3K8tsuUweC6buWax3qLfrfEnkhtQnPJHaqvTfTOlIIXVMfRpow=="],
|
||||
"@vibrant/quantizer-mmcq": ["@vibrant/quantizer-mmcq@4.0.4", "", { "dependencies": { "@vibrant/color": "^4.0.4", "@vibrant/image": "^4.0.4", "@vibrant/quantizer": "^4.0.4" } }, "sha512-/1CNnM96J8K+OBCWNUzywo6VdnmdFJyiKO+ty/nkfe8H0NseOEHIL7PrVtWGgtsb0rh2uTAq2rjXv65TfgPy8g=="],
|
||||
|
||||
"@vibrant/types": ["@vibrant/types@4.0.0", "", {}, "sha512-tA5TAbuROXcPkt+PWjmGfoaiEXyySVaNnCZovf6vXhCbMdrTTCQXvNCde2geiVl6YwtuU/Qrj9iZxS5jZ6yVIw=="],
|
||||
"@vibrant/types": ["@vibrant/types@4.0.4", "", {}, "sha512-Qq3mVTJamn7yD4OBgBEUKaxfDlm3sxBK55N7dH3XzI9Ey7KR00R06uwtqOcEJMsziWTEXdYN3VUlYaj2Tkt7hw=="],
|
||||
|
||||
"@vibrant/worker": ["@vibrant/worker@4.0.0", "", { "dependencies": { "@vibrant/types": "^4.0.0" } }, "sha512-nSaZZwWQKOgN/nPYUAIRF0/uoa7KpK91A+gjLmZZDgfN1enqxaiihmn+75ayNadW0c6cxAEpEFEHTONR5u9tMw=="],
|
||||
"@vibrant/worker": ["@vibrant/worker@4.0.4", "", { "dependencies": { "@vibrant/types": "^4.0.4" } }, "sha512-Q/R6PYhSMWCXEk/IcXbWIzIu7Z4b58ABkGvcdF8Y+q/7g+KnpxKW5x/jfQ/6ciyYSby13wZZoEdNr3QQVgsdBQ=="],
|
||||
|
||||
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
|
||||
|
||||
@ -730,7 +733,7 @@
|
||||
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.9.11", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ=="],
|
||||
|
||||
"better-auth": ["better-auth@1.4.17", "", { "dependencies": { "@better-auth/core": "1.4.17", "@better-auth/telemetry": "1.4.17", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "better-call": "1.1.8", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1", "zod": "^4.3.5" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "@tanstack/solid-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": ">=0.41.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "@tanstack/solid-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-VmHGQyKsEahkEs37qguROKg/6ypYpNF13D7v/lkbO7w7Aivz0Bv2h+VyUkH4NzrGY0QBKXi1577mGhDCVwp0ew=="],
|
||||
"better-auth": ["better-auth@1.4.18", "", { "dependencies": { "@better-auth/core": "1.4.18", "@better-auth/telemetry": "1.4.18", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "better-call": "1.1.8", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1", "zod": "^4.3.5" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "@tanstack/solid-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": ">=0.41.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "@tanstack/solid-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-bnyifLWBPcYVltH3RhS7CM62MoelEqC6Q+GnZwfiDWNfepXoQZBjEvn4urcERC7NTKgKq5zNBM8rvPvRBa6xcg=="],
|
||||
|
||||
"better-call": ["better-call@1.1.8", "", { "dependencies": { "@better-auth/utils": "^0.3.0", "@better-fetch/fetch": "^1.1.4", "rou3": "^0.7.10", "set-cookie-parser": "^2.7.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-XMQ2rs6FNXasGNfMjzbyroSwKwYbZ/T3IxruSS6U2MJRsSYh3wYtG3o6H00ZlKZ/C/UPOAD97tqgQJNsxyeTXw=="],
|
||||
|
||||
@ -1114,7 +1117,7 @@
|
||||
|
||||
"nanostores": ["nanostores@1.1.0", "", {}, "sha512-yJBmDJr18xy47dbNVlHcgdPrulSn1nhSE6Ns9vTG+Nx9VPT6iV1MD6aQFp/t52zpf82FhLLTXAXr30NuCnxvwA=="],
|
||||
|
||||
"next": ["next@16.1.4", "", { "dependencies": { "@next/env": "16.1.4", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.1.4", "@next/swc-darwin-x64": "16.1.4", "@next/swc-linux-arm64-gnu": "16.1.4", "@next/swc-linux-arm64-musl": "16.1.4", "@next/swc-linux-x64-gnu": "16.1.4", "@next/swc-linux-x64-musl": "16.1.4", "@next/swc-win32-arm64-msvc": "16.1.4", "@next/swc-win32-x64-msvc": "16.1.4", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-gKSecROqisnV7Buen5BfjmXAm7Xlpx9o2ueVQRo5DxQcjC8d330dOM1xiGWc2k3Dcnz0In3VybyRPOsudwgiqQ=="],
|
||||
"next": ["next@16.1.6", "", { "dependencies": { "@next/env": "16.1.6", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.1.6", "@next/swc-darwin-x64": "16.1.6", "@next/swc-linux-arm64-gnu": "16.1.6", "@next/swc-linux-arm64-musl": "16.1.6", "@next/swc-linux-x64-gnu": "16.1.6", "@next/swc-linux-x64-musl": "16.1.6", "@next/swc-win32-arm64-msvc": "16.1.6", "@next/swc-win32-x64-msvc": "16.1.6", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw=="],
|
||||
|
||||
"next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="],
|
||||
|
||||
@ -1122,9 +1125,9 @@
|
||||
|
||||
"node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="],
|
||||
|
||||
"node-vibrant": ["node-vibrant@4.0.3", "", { "dependencies": { "@types/node": "^18.15.3", "@vibrant/core": "^4.0.0", "@vibrant/generator-default": "^4.0.3", "@vibrant/image-browser": "^4.0.0", "@vibrant/image-node": "^4.0.0", "@vibrant/quantizer-mmcq": "^4.0.0" } }, "sha512-kzoIuJK90BH/k65Avt077JCX4Nhqz1LNc8cIOm2rnYEvFdJIYd8b3SQwU1MTpzcHtr8z8jxkl1qdaCfbP3olFg=="],
|
||||
"node-vibrant": ["node-vibrant@4.0.4", "", { "dependencies": { "@types/node": "^18.15.3", "@vibrant/core": "^4.0.4", "@vibrant/generator-default": "^4.0.4", "@vibrant/image-browser": "^4.0.4", "@vibrant/image-node": "^4.0.4", "@vibrant/quantizer-mmcq": "^4.0.4" } }, "sha512-hA/pUXBE9TJ41G9FlTkzeqD5JdxgvvPGYZb/HNpdkaxxXUEnP36imSolZ644JuPun+lTd+FpWWtBpTYdp2noQA=="],
|
||||
|
||||
"nodemailer": ["nodemailer@7.0.12", "", {}, "sha512-H+rnK5bX2Pi/6ms3sN4/jRQvYSMltV6vqup/0SFOrxYYY/qoNvhXPlYq3e+Pm9RFJRwrMGbMIwi81M4dxpomhA=="],
|
||||
"nodemailer": ["nodemailer@7.0.13", "", {}, "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw=="],
|
||||
|
||||
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
|
||||
|
||||
@ -1152,11 +1155,11 @@
|
||||
|
||||
"perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="],
|
||||
|
||||
"pg": ["pg@8.17.2", "", { "dependencies": { "pg-connection-string": "^2.10.1", "pg-pool": "^3.11.0", "pg-protocol": "^1.11.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-vjbKdiBJRqzcYw1fNU5KuHyYvdJ1qpcQg1CeBrHFqV1pWgHeVR6j/+kX0E1AAXfyuLUGY1ICrN2ELKA/z2HWzw=="],
|
||||
"pg": ["pg@8.18.0", "", { "dependencies": { "pg-connection-string": "^2.11.0", "pg-pool": "^3.11.0", "pg-protocol": "^1.11.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-xqrUDL1b9MbkydY/s+VZ6v+xiMUmOUk7SS9d/1kpyQxoJ6U9AO1oIJyUWVZojbfe5Cc/oluutcgFG4L9RDP1iQ=="],
|
||||
|
||||
"pg-cloudflare": ["pg-cloudflare@1.3.0", "", {}, "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ=="],
|
||||
|
||||
"pg-connection-string": ["pg-connection-string@2.10.1", "", {}, "sha512-iNzslsoeSH2/gmDDKiyMqF64DATUCWj3YJ0wP14kqcsf2TUklwimd+66yYojKwZCA7h2yRNLGug71hCBA2a4sw=="],
|
||||
"pg-connection-string": ["pg-connection-string@2.11.0", "", {}, "sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ=="],
|
||||
|
||||
"pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
|
||||
|
||||
@ -1204,13 +1207,13 @@
|
||||
|
||||
"rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="],
|
||||
|
||||
"react": ["react@19.2.1", "", {}, "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw=="],
|
||||
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
|
||||
|
||||
"react-compiler-runtime": ["react-compiler-runtime@1.0.0", "", { "peerDependencies": { "react": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^0.0.0-experimental" } }, "sha512-rRfjYv66HlG8896yPUDONgKzG5BxZD1nV9U6rkm+7VCuvQc903C4MjcoZR4zPw53IKSOX9wMQVpA1IAbRtzQ7w=="],
|
||||
|
||||
"react-day-picker": ["react-day-picker@9.13.0", "", { "dependencies": { "@date-fns/tz": "^1.4.1", "date-fns": "^4.1.0", "date-fns-jalali": "^4.1.0-0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-euzj5Hlq+lOHqI53NiuNhCP8HWgsPf/bBAVijR50hNaY1XwjKjShAnIe8jm8RD2W9IJUvihDIZ+KrmqfFzNhFQ=="],
|
||||
|
||||
"react-dom": ["react-dom@19.2.1", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.1" } }, "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg=="],
|
||||
"react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
|
||||
|
||||
"react-hook-form": ["react-hook-form@7.71.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w=="],
|
||||
|
||||
@ -1426,82 +1429,12 @@
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/core": ["@aws-sdk/core@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@aws-sdk/xml-builder": "3.957.0", "@smithy/core": "^3.20.0", "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/signature-v4": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-DrZgDnF1lQZv75a52nFWs6MExihJF2GZB6ETZRqr6jMwhrk2kbJPUtvgbifwcL7AYmVqHQDJBrR/MqkwwFCpiw=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.958.0", "", { "dependencies": { "@aws-sdk/credential-provider-env": "3.957.0", "@aws-sdk/credential-provider-http": "3.957.0", "@aws-sdk/credential-provider-ini": "3.958.0", "@aws-sdk/credential-provider-process": "3.957.0", "@aws-sdk/credential-provider-sso": "3.958.0", "@aws-sdk/credential-provider-web-identity": "3.958.0", "@aws-sdk/types": "3.957.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-vdoZbNG2dt66I7EpN3fKCzi6fp9xjIiwEA/vVVgqO4wXCGw8rKPIdDUus4e13VvTr330uQs2W0UNg/7AgtquEQ=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-BBgKawVyfQZglEkNTuBBdC3azlyqNXsvvN4jPkWAiNYcY0x1BasaJFl+7u/HisfULstryweJq/dAvIZIxzlZaA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-w1qfKrSKHf9b5a8O76yQ1t69u6NWuBjr5kBX+jRWFx/5mu6RLpqERXRpVJxfosbep7k3B+DSB5tZMZ82GKcJtQ=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-D2H/WoxhAZNYX+IjkKTdOhOkWQaK0jjJrDBj56hKjU5c9ltQiaX/1PqJ4dfjHntEshJfu0w+E6XJ+/6A6ILBBA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.957.0", "", { "dependencies": { "@aws-sdk/core": "3.957.0", "@aws-sdk/types": "3.957.0", "@aws-sdk/util-endpoints": "3.957.0", "@smithy/core": "^3.20.0", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-50vcHu96XakQnIvlKJ1UoltrFODjsq2KvtTgHiPFteUS884lQnK5VC/8xd1Msz/1ONpLMzdCVproCQqhDTtMPQ=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-V8iY3blh8l2iaOqXWW88HbkY5jDoWjH56jonprG/cpyqqCnprvpMUZWPWYJoI8rHRf2bqzZeql1slxG6EnKI7A=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.957.0", "", { "dependencies": { "@aws-sdk/middleware-sdk-s3": "3.957.0", "@aws-sdk/types": "3.957.0", "@smithy/protocol-http": "^5.3.7", "@smithy/signature-v4": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-t6UfP1xMUigMMzHcb7vaZcjv7dA2DQkk9C/OAP1dKyrE0vb4lFGDaTApi17GN6Km9zFxJthEMUbBc7DL0hq1Bg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/types": ["@aws-sdk/types@3.957.0", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-wzWC2Nrt859ABk6UCAVY/WYEbAd7FjkdrQL6m24+tfmWYDNRByTJ9uOgU/kw9zqLCAwb//CPvrJdhqjTznWXAg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-endpoints": "^3.2.7", "tslib": "^2.6.2" } }, "sha512-xwF9K24mZSxcxKS3UKQFeX/dPYkEps9wF1b+MGON7EvnbcucrJGyQyK1v1xFPn1aqXkBTFi+SZaMRx5E5YCVFw=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@smithy/types": "^4.11.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-exueuwxef0lUJRnGaVkNSC674eAiWU07ORhxBnevFFZEKisln+09Qrtw823iyv5I1N8T+wKfh95xvtWQrNKNQw=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.957.0", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "3.957.0", "@aws-sdk/types": "3.957.0", "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-ycbYCwqXk4gJGp0Oxkzf2KBeeGBdTxz559D41NJP8FlzSej1Gh7Rk40Zo6AyTfsNWkrl/kVi1t937OIzC5t+9Q=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/config-resolver": ["@smithy/config-resolver@4.4.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-HAGoUAFYsUkoSckuKbCPayECeMim8pOu+yLy1zOxt1sifzEbrsRpYa+mKcMdiHKMeiqOibyPG0sFJnmaV/OGEg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/core": ["@smithy/core@3.20.0", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.8", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-stream": "^4.5.8", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-WsSHCPq/neD5G/MkK4csLI5Y5Pkd9c1NMfpYEKeghSGaD4Ja1qLIohRQf2D5c1Uy5aXp76DeKHkzWZ9KAlHroQ=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.8", "", { "dependencies": { "@smithy/protocol-http": "^5.3.7", "@smithy/querystring-builder": "^4.2.7", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-h/Fi+o7mti4n8wx1SR6UHWLaakwHRx29sizvp8OOm7iqwKGFneT06GCSFhml6Bha5BT6ot5pj3CYZnCHhGC2Rg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/hash-node": ["@smithy/hash-node@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-PU/JWLTBCV1c8FtB8tEFnY4eV1tSfBc7bDBADHfn1K+uRbPgSJ9jnJp0hyjiFN2PMdPzxsf1Fdu0eo9fJ760Xw=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-ncvgCr9a15nPlkhIUx3CU4d7E7WEuVJOV7fS7nnK2hLtPK9tYRBkMHQbhXU1VvvKeBm/O0x26OEoBq+ngFpOEQ=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.7", "", { "dependencies": { "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-GszfBfCcvt7kIbJ41LuNa5f0wvQCHhnGx/aDaZJCCT05Ld6x6U2s0xsc/0mBFONBZjQJp2U/0uSJ178OXOwbhg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.1", "", { "dependencies": { "@smithy/core": "^3.20.0", "@smithy/middleware-serde": "^4.2.8", "@smithy/node-config-provider": "^4.3.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-middleware": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-gpLspUAoe6f1M6H0u4cVuFzxZBrsGZmjx2O9SigurTx4PbntYa4AJ+o0G0oGm1L2oSX6oBhcGHwrfJHup2JnJg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.17", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/protocol-http": "^5.3.7", "@smithy/service-error-classification": "^4.2.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-MqbXK6Y9uq17h+4r0ogu/sBT6V/rdV+5NvYL7ZV444BKfQygYe8wAhDrVXagVebN6w2RE0Fm245l69mOsPGZzg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.8", "", { "dependencies": { "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-8rDGYen5m5+NV9eHv9ry0sqm2gI6W7mc1VSFMtn6Igo25S507/HaOX9LTHAS2/J32VXD0xSzrY0H5FJtOMS4/w=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-bsOT0rJ+HHlZd9crHoS37mt8qRRN/h9jRve1SXUhVbkRzu0QaNYZp1i1jha4n098tsvROjcwfLlfvcFuJSXEsw=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.7", "", { "dependencies": { "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-7r58wq8sdOcrwWe+klL9y3bc4GW1gnlfnFOuL7CXa7UzfhzhxKuzNdtqgzmTV+53lEp9NXh5hY/S4UgjLOzPfw=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.7", "", { "dependencies": { "@smithy/abort-controller": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/querystring-builder": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-NELpdmBOO6EpZtWgQiHjoShs1kmweaiNuETUpuup+cmm/xJYjT4eUjfhrXRP4jCOaAsS3c3yPsP3B+K+/fyPCQ=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/protocol-http": ["@smithy/protocol-http@5.3.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-1r07pb994I20dD/c2seaZhoCuNYm0rWrvBxhCQ70brNh11M5Ml2ew6qJVo0lclB3jMIXirD4s2XRXRe7QEi0xA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/smithy-client": ["@smithy/smithy-client@4.10.2", "", { "dependencies": { "@smithy/core": "^3.20.0", "@smithy/middleware-endpoint": "^4.4.1", "@smithy/middleware-stack": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-stream": "^4.5.8", "tslib": "^2.6.2" } }, "sha512-D5z79xQWpgrGpAHb054Fn2CCTQZpog7JELbVQ6XAvXs5MNKWf28U9gzSBlJkOyMl9LA1TZEjRtwvGXfP0Sl90g=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/types": ["@smithy/types@4.11.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/url-parser": ["@smithy/url-parser@4.2.7", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-/RLtVsRV4uY3qPWhBDsjwahAtt3x2IsMGnP5W1b2VZIe+qgCqkLxI1UOHDZp1Q1QSOrdOR32MF3Ph2JfWT1VHg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.16", "", { "dependencies": { "@smithy/property-provider": "^4.2.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-/eiSP3mzY3TsvUOYMeL4EqUX6fgUOj2eUOU4rMMgVbq67TiRLyxT7Xsjxq0bW3OwuzK009qOwF0L2OgJqperAQ=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.19", "", { "dependencies": { "@smithy/config-resolver": "^4.4.5", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-3a4+4mhf6VycEJyHIQLypRbiwG6aJvbQAeRAVXydMmfweEPnLLabRbdyo/Pjw8Rew9vjsh5WCdhmDaHkQnhhhA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.7", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-s4ILhyAvVqhMDYREeTS68R43B1V5aenV5q/V1QpRQJkCXib5BPRo4s7uNdzGtIKxaPHCfU/8YkvPAEvTpxgspg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/util-middleware": ["@smithy/util-middleware@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-i1IkpbOae6NvIKsEeLLM9/2q4X+M90KV3oCFgWQI4q0Qz+yUZvsr+gZPdAEAtFhWQhAHpTsJO8DRJPuwVyln+w=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/util-retry": ["@smithy/util-retry@4.2.7", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-SvDdsQyF5CIASa4EYVT02LukPHVzAgUA4kMAuZ97QJc2BpAqZfA4PINB8/KOoCXEw9tsuv/jQjMeaHFvxdLNGg=="],
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3": ["@aws-sdk/middleware-sdk-s3@3.972.0", "", { "dependencies": { "@aws-sdk/core": "3.972.0", "@aws-sdk/types": "3.972.0", "@aws-sdk/util-arn-parser": "3.972.0", "@smithy/core": "^3.20.6", "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", "@smithy/smithy-client": "^4.10.8", "@smithy/types": "^4.12.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.10", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-0bcKFXWx+NZ7tIlOo7KjQ+O2rydiHdIQahrq+fN6k9Osky29v17guy68urUKfhTobR6iY6KvxkroFWaFtTgS5w=="],
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region/@aws-sdk/types": ["@aws-sdk/types@3.972.0", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-U7xBIbLSetONxb2bNzHyDgND3oKGoIfmknrEVnoEU4GUSs+0augUOIn9DIWGUO2ETcRFdsRUnmx9KhPT9Ojbug=="],
|
||||
|
||||
"@aws-sdk/util-endpoints/@aws-sdk/types": ["@aws-sdk/types@3.972.0", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-U7xBIbLSetONxb2bNzHyDgND3oKGoIfmknrEVnoEU4GUSs+0augUOIn9DIWGUO2ETcRFdsRUnmx9KhPT9Ojbug=="],
|
||||
|
||||
"@jimp/core/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
|
||||
|
||||
"@platejs/core/nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="],
|
||||
|
||||
"@prisma/adapter-pg/pg": ["pg@8.17.2", "", { "dependencies": { "pg-connection-string": "^2.10.1", "pg-pool": "^3.11.0", "pg-protocol": "^1.11.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.3.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-vjbKdiBJRqzcYw1fNU5KuHyYvdJ1qpcQg1CeBrHFqV1pWgHeVR6j/+kX0E1AAXfyuLUGY1ICrN2ELKA/z2HWzw=="],
|
||||
|
||||
"@prisma/engines/@prisma/get-platform": ["@prisma/get-platform@7.3.0", "", { "dependencies": { "@prisma/debug": "7.3.0" } }, "sha512-N7c6m4/I0Q6JYmWKP2RCD/sM9eWiyCPY98g5c0uEktObNSZnugW2U/PO+pwL0UaqzxqTXt7gTsYsb0FnMnJNbg=="],
|
||||
|
||||
"@prisma/fetch-engine/@prisma/get-platform": ["@prisma/get-platform@7.3.0", "", { "dependencies": { "@prisma/debug": "7.3.0" } }, "sha512-N7c6m4/I0Q6JYmWKP2RCD/sM9eWiyCPY98g5c0uEktObNSZnugW2U/PO+pwL0UaqzxqTXt7gTsYsb0FnMnJNbg=="],
|
||||
@ -1588,65 +1521,9 @@
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.957.0", "", { "dependencies": { "@smithy/types": "^4.11.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" } }, "sha512-Ai5iiQqS8kJ5PjzMhWcLKN0G2yasAkvpnPlq2EnqlIMdB48HsizElt62qcktdxp4neRMyGkFq4NzgmDbXnhRiA=="],
|
||||
"@prisma/adapter-pg/pg/pg-connection-string": ["pg-connection-string@2.10.1", "", {}, "sha512-iNzslsoeSH2/gmDDKiyMqF64DATUCWj3YJ0wP14kqcsf2TUklwimd+66yYojKwZCA7h2yRNLGug71hCBA2a4sw=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/core/@smithy/property-provider": ["@smithy/property-provider@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/core/@smithy/signature-v4": ["@smithy/signature-v4@5.3.7", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-9oNUlqBlFZFOSdxgImA6X5GFuzE7V2H7VG/7E70cdLhidFbdtvxxt81EHgykGK5vq5D3FafH//X+Oy31j3CKOg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.957.0", "", { "dependencies": { "@aws-sdk/core": "3.957.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-475mkhGaWCr+Z52fOOVb/q2VHuNvqEDixlYIkeaO6xJ6t9qR0wpLt4hOQaR6zR1wfZV0SlE7d8RErdYq/PByog=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.957.0", "", { "dependencies": { "@aws-sdk/core": "3.957.0", "@aws-sdk/types": "3.957.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/node-http-handler": "^4.4.7", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/util-stream": "^4.5.8", "tslib": "^2.6.2" } }, "sha512-8dS55QHRxXgJlHkEYaCGZIhieCs9NU1HU1BcqQ4RfUdSsfRdxxktqUKgCnBnOOn0oD3PPA8cQOCAVgIyRb3Rfw=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.958.0", "", { "dependencies": { "@aws-sdk/core": "3.957.0", "@aws-sdk/credential-provider-env": "3.957.0", "@aws-sdk/credential-provider-http": "3.957.0", "@aws-sdk/credential-provider-login": "3.958.0", "@aws-sdk/credential-provider-process": "3.957.0", "@aws-sdk/credential-provider-sso": "3.958.0", "@aws-sdk/credential-provider-web-identity": "3.958.0", "@aws-sdk/nested-clients": "3.958.0", "@aws-sdk/types": "3.957.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-u7twvZa1/6GWmPBZs6DbjlegCoNzNjBsMS/6fvh5quByYrcJr/uLd8YEr7S3UIq4kR/gSnHqcae7y2nL2bqZdg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.957.0", "", { "dependencies": { "@aws-sdk/core": "3.957.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-/KIz9kadwbeLy6SKvT79W81Y+hb/8LMDyeloA2zhouE28hmne+hLn0wNCQXAAupFFlYOAtZR2NTBs7HBAReJlg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.958.0", "", { "dependencies": { "@aws-sdk/client-sso": "3.958.0", "@aws-sdk/core": "3.957.0", "@aws-sdk/token-providers": "3.958.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-CBYHJ5ufp8HC4q+o7IJejCUctJXWaksgpmoFpXerbjAso7/Fg7LLUu9inXVOxlHKLlvYekDXjIUBXDJS2WYdgg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.958.0", "", { "dependencies": { "@aws-sdk/core": "3.957.0", "@aws-sdk/nested-clients": "3.958.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-dgnvwjMq5Y66WozzUzxNkCFap+umHUtqMMKlr8z/vl9NYMLem/WUbWNpFFOVFWquXikc+ewtpBMR4KEDXfZ+KA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.7", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-CmduWdCiILCRNbQWFR0OcZlUPVtyE49Sr8yYL0rZQ4D/wKxiNzBNS/YHemvnbkIWj623fplgkexUd/c9CAKdoA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@smithy/property-provider": ["@smithy/property-provider@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.2", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-M7iUUff/KwfNunmrgtqBfvZSzh3bmFgv/j/t1Y1dQ+8dNo34br1cqVEqy6v0mYEgi0DkGO7Xig0AnuOaEGVlcg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3": ["@aws-sdk/middleware-sdk-s3@3.957.0", "", { "dependencies": { "@aws-sdk/core": "3.957.0", "@aws-sdk/types": "3.957.0", "@aws-sdk/util-arn-parser": "3.957.0", "@smithy/core": "^3.20.0", "@smithy/node-config-provider": "^4.3.7", "@smithy/protocol-http": "^5.3.7", "@smithy/signature-v4": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-stream": "^4.5.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-5B2qY2nR2LYpxoQP0xUum5A1UNvH2JQpLHDH1nWFNF/XetV7ipFHksMxPNhtJJ6ARaWhQIDXfOUj0jcnkJxXUg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@smithy/signature-v4": ["@smithy/signature-v4@5.3.7", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-9oNUlqBlFZFOSdxgImA6X5GFuzE7V2H7VG/7E70cdLhidFbdtvxxt81EHgykGK5vq5D3FafH//X+Oy31j3CKOg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/core/@smithy/util-stream": ["@smithy/util-stream@4.5.8", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.8", "@smithy/node-http-handler": "^4.4.7", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/fetch-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-eKONSywHZxK4tBxe2lXEysh8wbBdvDWiA+RIuaxZSgCMmA0zMgoDpGLJhnyj+c0leOQprVnXOmcB4m+W9Rw7sg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/middleware-endpoint/@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.2", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-M7iUUff/KwfNunmrgtqBfvZSzh3bmFgv/j/t1Y1dQ+8dNo34br1cqVEqy6v0mYEgi0DkGO7Xig0AnuOaEGVlcg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/middleware-retry/@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0" } }, "sha512-YB7oCbukqEb2Dlh3340/8g8vNGbs/QsNNRms+gv3N2AtZz9/1vSBx6/6tpwQpZMEJFs7Uq8h4mmOn48ZZ72MkA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/node-config-provider/@smithy/property-provider": ["@smithy/property-provider@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/node-config-provider/@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.2", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-M7iUUff/KwfNunmrgtqBfvZSzh3bmFgv/j/t1Y1dQ+8dNo34br1cqVEqy6v0mYEgi0DkGO7Xig0AnuOaEGVlcg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/node-http-handler/@smithy/abort-controller": ["@smithy/abort-controller@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-rzMY6CaKx2qxrbYbqjXWS0plqEy7LOdKHS0bg4ixJ6aoGDPNUcLWk/FRNuCILh7GKLG9TFUXYYeQQldMBBwuyw=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/node-http-handler/@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-eKONSywHZxK4tBxe2lXEysh8wbBdvDWiA+RIuaxZSgCMmA0zMgoDpGLJhnyj+c0leOQprVnXOmcB4m+W9Rw7sg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/smithy-client/@smithy/util-stream": ["@smithy/util-stream@4.5.8", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.8", "@smithy/node-http-handler": "^4.4.7", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/url-parser/@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-3X5ZvzUHmlSTHAXFlswrS6EGt8fMSIxX/c3Rm1Pni3+wYWB6cjGocmRIoqcQF9nU5OgGmL0u7l9m44tSUpfj9w=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/util-defaults-mode-browser/@smithy/property-provider": ["@smithy/property-provider@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/util-defaults-mode-node/@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.7", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-CmduWdCiILCRNbQWFR0OcZlUPVtyE49Sr8yYL0rZQ4D/wKxiNzBNS/YHemvnbkIWj623fplgkexUd/c9CAKdoA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/util-defaults-mode-node/@smithy/property-provider": ["@smithy/property-provider@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@smithy/util-retry/@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0" } }, "sha512-YB7oCbukqEb2Dlh3340/8g8vNGbs/QsNNRms+gv3N2AtZz9/1vSBx6/6tpwQpZMEJFs7Uq8h4mmOn48ZZ72MkA=="],
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@aws-sdk/core": ["@aws-sdk/core@3.972.0", "", { "dependencies": { "@aws-sdk/types": "3.972.0", "@aws-sdk/xml-builder": "3.972.0", "@smithy/core": "^3.20.6", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", "@smithy/smithy-client": "^4.10.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-nEeUW2M9F+xdIaD98F5MBcQ4ITtykj3yKbgFZ6J0JtL3bq+Z90szQ6Yy8H/BLPYXTs3V4n9ifnBo8cprRDiE6A=="],
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@aws-sdk/util-arn-parser": ["@aws-sdk/util-arn-parser@3.972.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-RM5Mmo/KJ593iMSrALlHEOcc9YOIyOsDmS5x2NLOMdEmzv1o00fcpAkCQ02IGu1eFneBFT7uX0Mpag0HI+Cz2g=="],
|
||||
"@prisma/adapter-pg/pg/pg-protocol": ["pg-protocol@1.11.0", "", {}, "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g=="],
|
||||
|
||||
"lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||
|
||||
@ -1665,25 +1542,5 @@
|
||||
"@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-http/@smithy/util-stream": ["@smithy/util-stream@4.5.8", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.8", "@smithy/node-http-handler": "^4.4.7", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.958.0", "", { "dependencies": { "@aws-sdk/core": "3.957.0", "@aws-sdk/nested-clients": "3.958.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-sDwtDnBSszUIbzbOORGh5gmXGl9aK25+BHb4gb1aVlqB+nNL2+IUEJA62+CE55lXSH8qXF90paivjK8tOHTwPA=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.958.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.957.0", "@aws-sdk/middleware-host-header": "3.957.0", "@aws-sdk/middleware-logger": "3.957.0", "@aws-sdk/middleware-recursion-detection": "3.957.0", "@aws-sdk/middleware-user-agent": "3.957.0", "@aws-sdk/region-config-resolver": "3.957.0", "@aws-sdk/types": "3.957.0", "@aws-sdk/util-endpoints": "3.957.0", "@aws-sdk/util-user-agent-browser": "3.957.0", "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.1", "@smithy/middleware-retry": "^4.4.17", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.16", "@smithy/util-defaults-mode-node": "^4.2.19", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-/KuCcS8b5TpQXkYOrPLYytrgxBhv81+5pChkOlhegbeHttjM69pyUpQVJqyfDM/A7wPLnDrzCAnk4zaAOkY0Nw=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.958.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.957.0", "@aws-sdk/middleware-host-header": "3.957.0", "@aws-sdk/middleware-logger": "3.957.0", "@aws-sdk/middleware-recursion-detection": "3.957.0", "@aws-sdk/middleware-user-agent": "3.957.0", "@aws-sdk/region-config-resolver": "3.957.0", "@aws-sdk/types": "3.957.0", "@aws-sdk/util-endpoints": "3.957.0", "@aws-sdk/util-user-agent-browser": "3.957.0", "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.1", "@smithy/middleware-retry": "^4.4.17", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.16", "@smithy/util-defaults-mode-node": "^4.2.19", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-6qNCIeaMzKzfqasy2nNRuYnMuaMebCcCPP4J2CVGkA8QYMbIVKPlkn9bpB20Vxe6H/r3jtCCLQaOJjVTx/6dXg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.958.0", "", { "dependencies": { "@aws-sdk/core": "3.957.0", "@aws-sdk/nested-clients": "3.958.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-UCj7lQXODduD1myNJQkV+LYcGYJ9iiMggR8ow8Hva1g3A/Na5imNXzz6O67k7DAee0TYpy+gkNw+SizC6min8Q=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.958.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.957.0", "@aws-sdk/middleware-host-header": "3.957.0", "@aws-sdk/middleware-logger": "3.957.0", "@aws-sdk/middleware-recursion-detection": "3.957.0", "@aws-sdk/middleware-user-agent": "3.957.0", "@aws-sdk/region-config-resolver": "3.957.0", "@aws-sdk/types": "3.957.0", "@aws-sdk/util-endpoints": "3.957.0", "@aws-sdk/util-user-agent-browser": "3.957.0", "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.1", "@smithy/middleware-retry": "^4.4.17", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.16", "@smithy/util-defaults-mode-node": "^4.2.19", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-/KuCcS8b5TpQXkYOrPLYytrgxBhv81+5pChkOlhegbeHttjM69pyUpQVJqyfDM/A7wPLnDrzCAnk4zaAOkY0Nw=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@aws-sdk/util-arn-parser": ["@aws-sdk/util-arn-parser@3.957.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Aj6m+AyrhWyg8YQ4LDPg2/gIfGHCEcoQdBt5DeSFogN5k9mmJPOJ+IAmNSWmWRjpOxEy6eY813RNDI6qS97M0g=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@smithy/util-stream": ["@smithy/util-stream@4.5.8", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.8", "@smithy/node-http-handler": "^4.4.7", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w=="],
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region/@aws-sdk/middleware-sdk-s3/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.0", "", { "dependencies": { "@smithy/types": "^4.12.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" } }, "sha512-POaGMcXnozzqBUyJM3HLUZ9GR6OKJWPGJEmhtTnxZXt8B6JcJ/6K3xRJ5H/j8oovVLz8Wg6vFxAHv8lvuASxMg=="],
|
||||
|
||||
"@aws-sdk/client-sesv2/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.958.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.957.0", "@aws-sdk/middleware-host-header": "3.957.0", "@aws-sdk/middleware-logger": "3.957.0", "@aws-sdk/middleware-recursion-detection": "3.957.0", "@aws-sdk/middleware-user-agent": "3.957.0", "@aws-sdk/region-config-resolver": "3.957.0", "@aws-sdk/types": "3.957.0", "@aws-sdk/util-endpoints": "3.957.0", "@aws-sdk/util-user-agent-browser": "3.957.0", "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.1", "@smithy/middleware-retry": "^4.4.17", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.16", "@smithy/util-defaults-mode-node": "^4.2.19", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-/KuCcS8b5TpQXkYOrPLYytrgxBhv81+5pChkOlhegbeHttjM69pyUpQVJqyfDM/A7wPLnDrzCAnk4zaAOkY0Nw=="],
|
||||
}
|
||||
}
|
||||
|
||||
8882
package-lock.json
generated
8882
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
33
package.json
33
package.json
@ -1,17 +1,19 @@
|
||||
{
|
||||
"name": "admin.gaertan.art",
|
||||
"version": "0.1.0",
|
||||
"version": "1.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "PORT=3001 NODE_OPTIONS='--max-old-space-size=4096' next dev",
|
||||
"dev:version": "NEXT_PUBLIC_GIT_SHA=$(git rev-parse --short HEAD) NEXT_PUBLIC_DEPLOY_ENV=dev PORT=3001 NODE_OPTIONS='--max-old-space-size=4096' next dev",
|
||||
"build": "next build",
|
||||
"build:version": "NEXT_PUBLIC_GIT_SHA=$(git rev-parse --short HEAD) NEXT_PUBLIC_DEPLOY_ENV=prod bun run build",
|
||||
"start": "next start",
|
||||
"lint": "biome check",
|
||||
"format": "biome format --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.974.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.974.0",
|
||||
"@aws-sdk/client-s3": "^3.980.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.980.0",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/modifiers": "^9.0.0",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
@ -44,7 +46,7 @@
|
||||
"@radix-ui/react-tooltip": "^1.2.8",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"archiver": "^7.0.1",
|
||||
"better-auth": "^1.4.17",
|
||||
"better-auth": "^1.4.18",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.1.1",
|
||||
@ -53,15 +55,15 @@
|
||||
"dotenv": "^17.2.3",
|
||||
"lowlight": "^3.3.0",
|
||||
"lucide-react": "^0.561.0",
|
||||
"next": "^16.1.4",
|
||||
"next": "16.1.6",
|
||||
"next-themes": "^0.4.6",
|
||||
"node-vibrant": "^4.0.3",
|
||||
"nodemailer": "^7.0.12",
|
||||
"pg": "^8.17.2",
|
||||
"node-vibrant": "^4.0.4",
|
||||
"nodemailer": "^7.0.13",
|
||||
"pg": "^8.18.0",
|
||||
"platejs": "^52.0.17",
|
||||
"react": "19.2.1",
|
||||
"react": "19.2.4",
|
||||
"react-day-picker": "^9.13.0",
|
||||
"react-dom": "19.2.1",
|
||||
"react-dom": "19.2.4",
|
||||
"react-hook-form": "^7.71.1",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"remark-math": "^6.0.0",
|
||||
@ -69,6 +71,7 @@
|
||||
"tailwind-merge": "^3.4.0",
|
||||
"tailwind-scrollbar-hide": "^4.0.0",
|
||||
"uuid": "^13.0.0",
|
||||
"zustand": "^5.0.8",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -78,14 +81,18 @@
|
||||
"@types/culori": "^4.0.1",
|
||||
"@types/date-fns": "^2.6.3",
|
||||
"@types/node": "^20.19.30",
|
||||
"@types/nodemailer": "^7.0.5",
|
||||
"@types/nodemailer": "^7.0.9",
|
||||
"@types/pg": "^8.16.0",
|
||||
"@types/react": "^19.2.9",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/react": "19.2.10",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"@types/uuid": "^11.0.0",
|
||||
"prisma": "^7.3.0",
|
||||
"tailwindcss": "^4.1.18",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"overrides": {
|
||||
"@types/react": "19.2.10",
|
||||
"@types/react-dom": "19.2.3"
|
||||
}
|
||||
}
|
||||
|
||||
65
prisma/migrations/20260201142100_com_7/migration.sql
Normal file
65
prisma/migrations/20260201142100_com_7/migration.sql
Normal file
@ -0,0 +1,65 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "CommissionCustomCard" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"sortIndex" INTEGER NOT NULL DEFAULT 0,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"referenceImageUrl" TEXT,
|
||||
"isVisible" BOOLEAN NOT NULL DEFAULT true,
|
||||
"isSpecialOffer" BOOLEAN NOT NULL DEFAULT false,
|
||||
|
||||
CONSTRAINT "CommissionCustomCard_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "CommissionCustomCardOption" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"sortIndex" INTEGER NOT NULL DEFAULT 0,
|
||||
"cardId" TEXT NOT NULL,
|
||||
"optionId" TEXT NOT NULL,
|
||||
"priceRange" TEXT,
|
||||
"pricePercent" DOUBLE PRECISION,
|
||||
"price" DOUBLE PRECISION,
|
||||
|
||||
CONSTRAINT "CommissionCustomCardOption_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "CommissionCustomCardExtra" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"sortIndex" INTEGER NOT NULL DEFAULT 0,
|
||||
"cardId" TEXT NOT NULL,
|
||||
"extraId" TEXT NOT NULL,
|
||||
"priceRange" TEXT,
|
||||
"pricePercent" DOUBLE PRECISION,
|
||||
"price" DOUBLE PRECISION,
|
||||
|
||||
CONSTRAINT "CommissionCustomCardExtra_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "CommissionCustomCard_isVisible_sortIndex_idx" ON "CommissionCustomCard"("isVisible", "sortIndex");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "CommissionCustomCardOption_cardId_optionId_key" ON "CommissionCustomCardOption"("cardId", "optionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "CommissionCustomCardExtra_cardId_extraId_key" ON "CommissionCustomCardExtra"("cardId", "extraId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CommissionCustomCardOption" ADD CONSTRAINT "CommissionCustomCardOption_cardId_fkey" FOREIGN KEY ("cardId") REFERENCES "CommissionCustomCard"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CommissionCustomCardOption" ADD CONSTRAINT "CommissionCustomCardOption_optionId_fkey" FOREIGN KEY ("optionId") REFERENCES "CommissionOption"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CommissionCustomCardExtra" ADD CONSTRAINT "CommissionCustomCardExtra_cardId_fkey" FOREIGN KEY ("cardId") REFERENCES "CommissionCustomCard"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CommissionCustomCardExtra" ADD CONSTRAINT "CommissionCustomCardExtra_extraId_fkey" FOREIGN KEY ("extraId") REFERENCES "CommissionExtra"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
5
prisma/migrations/20260201144904_com_8/migration.sql
Normal file
5
prisma/migrations/20260201144904_com_8/migration.sql
Normal file
@ -0,0 +1,5 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "CommissionRequest" ADD COLUMN "customCardId" TEXT;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CommissionRequest" ADD CONSTRAINT "CommissionRequest_customCardId_fkey" FOREIGN KEY ("customCardId") REFERENCES "CommissionCustomCard"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
140
prisma/migrations/20260202114116_tags_01/migration.sql
Normal file
140
prisma/migrations/20260202114116_tags_01/migration.sql
Normal file
@ -0,0 +1,140 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "Tag" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"sortIndex" INTEGER NOT NULL DEFAULT 0,
|
||||
"name" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"isVisible" BOOLEAN NOT NULL DEFAULT true,
|
||||
"description" TEXT,
|
||||
|
||||
CONSTRAINT "Tag_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "TagAlias" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"alias" TEXT NOT NULL,
|
||||
"tagId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "TagAlias_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "TagCategory" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"tagId" TEXT NOT NULL,
|
||||
"categoryId" TEXT NOT NULL,
|
||||
"isParent" BOOLEAN NOT NULL DEFAULT false,
|
||||
"showOnAnimalPage" BOOLEAN NOT NULL DEFAULT false,
|
||||
"parentTagId" TEXT,
|
||||
|
||||
CONSTRAINT "TagCategory_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Miniature" (
|
||||
"id" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Miniature_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_ArtworkTagsV2" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_ArtworkTagsV2_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_MiniatureTags" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_MiniatureTags_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_CommissionTypeTags" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_CommissionTypeTags_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Tag_name_key" ON "Tag"("name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Tag_slug_key" ON "Tag"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "TagAlias_alias_key" ON "TagAlias"("alias");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "TagAlias_alias_idx" ON "TagAlias"("alias");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "TagAlias_tagId_alias_key" ON "TagAlias"("tagId", "alias");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "TagCategory_categoryId_idx" ON "TagCategory"("categoryId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "TagCategory_tagId_idx" ON "TagCategory"("tagId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "TagCategory_parentTagId_idx" ON "TagCategory"("parentTagId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "TagCategory_categoryId_parentTagId_idx" ON "TagCategory"("categoryId", "parentTagId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "TagCategory_tagId_categoryId_key" ON "TagCategory"("tagId", "categoryId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_ArtworkTagsV2_B_index" ON "_ArtworkTagsV2"("B");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_MiniatureTags_B_index" ON "_MiniatureTags"("B");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_CommissionTypeTags_B_index" ON "_CommissionTypeTags"("B");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "TagAlias" ADD CONSTRAINT "TagAlias_tagId_fkey" FOREIGN KEY ("tagId") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "TagCategory" ADD CONSTRAINT "TagCategory_tagId_fkey" FOREIGN KEY ("tagId") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "TagCategory" ADD CONSTRAINT "TagCategory_categoryId_fkey" FOREIGN KEY ("categoryId") REFERENCES "ArtCategory"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "TagCategory" ADD CONSTRAINT "TagCategory_parentTagId_fkey" FOREIGN KEY ("parentTagId") REFERENCES "Tag"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ArtworkTagsV2" ADD CONSTRAINT "_ArtworkTagsV2_A_fkey" FOREIGN KEY ("A") REFERENCES "Artwork"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ArtworkTagsV2" ADD CONSTRAINT "_ArtworkTagsV2_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_MiniatureTags" ADD CONSTRAINT "_MiniatureTags_A_fkey" FOREIGN KEY ("A") REFERENCES "Miniature"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_MiniatureTags" ADD CONSTRAINT "_MiniatureTags_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_CommissionTypeTags" ADD CONSTRAINT "_CommissionTypeTags_A_fkey" FOREIGN KEY ("A") REFERENCES "CommissionType"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_CommissionTypeTags" ADD CONSTRAINT "_CommissionTypeTags_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
65
prisma/migrations/20260202121413_tags_02/migration.sql
Normal file
65
prisma/migrations/20260202121413_tags_02/migration.sql
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the `ArtTag` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `ArtTagAlias` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `_ArtCategoryToArtTag` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `_ArtTagToArtwork` table. If the table is not empty, all the data it contains will be lost.
|
||||
- You are about to drop the `_ArtworkTagsV2` table. If the table is not empty, all the data it contains will be lost.
|
||||
|
||||
*/
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "ArtTag" DROP CONSTRAINT "ArtTag_parentId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "ArtTagAlias" DROP CONSTRAINT "ArtTagAlias_tagId_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_ArtCategoryToArtTag" DROP CONSTRAINT "_ArtCategoryToArtTag_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_ArtCategoryToArtTag" DROP CONSTRAINT "_ArtCategoryToArtTag_B_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_ArtTagToArtwork" DROP CONSTRAINT "_ArtTagToArtwork_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_ArtTagToArtwork" DROP CONSTRAINT "_ArtTagToArtwork_B_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_ArtworkTagsV2" DROP CONSTRAINT "_ArtworkTagsV2_A_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "_ArtworkTagsV2" DROP CONSTRAINT "_ArtworkTagsV2_B_fkey";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "ArtTag";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "ArtTagAlias";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_ArtCategoryToArtTag";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_ArtTagToArtwork";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "_ArtworkTagsV2";
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "_ArtworkTags" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_ArtworkTags_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_ArtworkTags_B_index" ON "_ArtworkTags"("B");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ArtworkTags" ADD CONSTRAINT "_ArtworkTags_A_fkey" FOREIGN KEY ("A") REFERENCES "Artwork"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_ArtworkTags" ADD CONSTRAINT "_ArtworkTags_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
16
prisma/migrations/20260202151753_tags_03/migration.sql
Normal file
16
prisma/migrations/20260202151753_tags_03/migration.sql
Normal file
@ -0,0 +1,16 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "_CommissionCustomCardTags" (
|
||||
"A" TEXT NOT NULL,
|
||||
"B" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "_CommissionCustomCardTags_AB_pkey" PRIMARY KEY ("A","B")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "_CommissionCustomCardTags_B_index" ON "_CommissionCustomCardTags"("B");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_CommissionCustomCardTags" ADD CONSTRAINT "_CommissionCustomCardTags_A_fkey" FOREIGN KEY ("A") REFERENCES "CommissionCustomCard"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "_CommissionCustomCardTags" ADD CONSTRAINT "_CommissionCustomCardTags_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@ -53,7 +53,7 @@ model Artwork {
|
||||
albums Album[]
|
||||
categories ArtCategory[]
|
||||
colors ArtworkColor[]
|
||||
tags ArtTag[]
|
||||
tags Tag[] @relation("ArtworkTags")
|
||||
variants FileVariant[]
|
||||
|
||||
@@index([colorStatus])
|
||||
@ -101,43 +101,7 @@ model ArtCategory {
|
||||
description String?
|
||||
|
||||
artworks Artwork[]
|
||||
tags ArtTag[]
|
||||
}
|
||||
|
||||
model ArtTag {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
sortIndex Int @default(0)
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
isParent Boolean @default(false)
|
||||
showOnAnimalPage Boolean @default(false)
|
||||
|
||||
description String?
|
||||
|
||||
aliases ArtTagAlias[]
|
||||
artworks Artwork[]
|
||||
categories ArtCategory[]
|
||||
|
||||
parentId String?
|
||||
parent ArtTag? @relation("TagHierarchy", fields: [parentId], references: [id], onDelete: SetNull)
|
||||
children ArtTag[] @relation("TagHierarchy")
|
||||
}
|
||||
|
||||
model ArtTagAlias {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
alias String @unique
|
||||
|
||||
tagId String
|
||||
tag ArtTag @relation(fields: [tagId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([tagId, alias])
|
||||
@@index([alias])
|
||||
tagLinks TagCategory[]
|
||||
}
|
||||
|
||||
model Color {
|
||||
@ -248,6 +212,72 @@ model FileVariant {
|
||||
@@unique([artworkId, type])
|
||||
}
|
||||
|
||||
model Tag {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
sortIndex Int @default(0)
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
isVisible Boolean @default(true)
|
||||
|
||||
description String?
|
||||
|
||||
aliases TagAlias[]
|
||||
categoryLinks TagCategory[]
|
||||
categoryParents TagCategory[] @relation("TagCategoryParent")
|
||||
artworks Artwork[] @relation("ArtworkTags")
|
||||
commissionTypes CommissionType[] @relation("CommissionTypeTags")
|
||||
commissionCustomCards CommissionCustomCard[] @relation("CommissionCustomCardTags")
|
||||
miniatures Miniature[] @relation("MiniatureTags")
|
||||
}
|
||||
|
||||
model TagAlias {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
alias String @unique
|
||||
|
||||
tagId String
|
||||
tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([tagId, alias])
|
||||
@@index([alias])
|
||||
}
|
||||
|
||||
model TagCategory {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
tagId String
|
||||
categoryId String
|
||||
|
||||
isParent Boolean @default(false)
|
||||
showOnAnimalPage Boolean @default(false)
|
||||
parentTagId String?
|
||||
|
||||
tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)
|
||||
category ArtCategory @relation(fields: [categoryId], references: [id], onDelete: Cascade)
|
||||
parentTag Tag? @relation("TagCategoryParent", fields: [parentTagId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@unique([tagId, categoryId])
|
||||
@@index([categoryId])
|
||||
@@index([tagId])
|
||||
@@index([parentTagId])
|
||||
@@index([categoryId, parentTagId])
|
||||
}
|
||||
|
||||
model Miniature {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
tags Tag[] @relation("MiniatureTags")
|
||||
}
|
||||
|
||||
model Commission {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
@ -265,12 +295,35 @@ model CommissionType {
|
||||
|
||||
description String?
|
||||
|
||||
tags Tag[] @relation("CommissionTypeTags")
|
||||
|
||||
options CommissionTypeOption[]
|
||||
extras CommissionTypeExtra[]
|
||||
customInputs CommissionTypeCustomInput[]
|
||||
requests CommissionRequest[]
|
||||
}
|
||||
|
||||
model CommissionCustomCard {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
sortIndex Int @default(0)
|
||||
|
||||
name String
|
||||
|
||||
description String?
|
||||
referenceImageUrl String?
|
||||
isVisible Boolean @default(true)
|
||||
isSpecialOffer Boolean @default(false)
|
||||
|
||||
tags Tag[] @relation("CommissionCustomCardTags")
|
||||
options CommissionCustomCardOption[]
|
||||
extras CommissionCustomCardExtra[]
|
||||
requests CommissionRequest[]
|
||||
|
||||
@@index([isVisible, sortIndex])
|
||||
}
|
||||
|
||||
model CommissionOption {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
@ -282,6 +335,7 @@ model CommissionOption {
|
||||
description String?
|
||||
|
||||
types CommissionTypeOption[]
|
||||
customCards CommissionCustomCardOption[]
|
||||
requests CommissionRequest[]
|
||||
}
|
||||
|
||||
@ -316,6 +370,7 @@ model CommissionExtra {
|
||||
|
||||
requests CommissionRequest[]
|
||||
types CommissionTypeExtra[]
|
||||
customCards CommissionCustomCardExtra[]
|
||||
}
|
||||
|
||||
model CommissionTypeExtra {
|
||||
@ -337,6 +392,25 @@ model CommissionTypeExtra {
|
||||
@@unique([typeId, extraId])
|
||||
}
|
||||
|
||||
model CommissionCustomCardOption {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
sortIndex Int @default(0)
|
||||
|
||||
cardId String
|
||||
optionId String
|
||||
|
||||
priceRange String?
|
||||
pricePercent Float?
|
||||
price Float?
|
||||
|
||||
card CommissionCustomCard @relation(fields: [cardId], references: [id], onDelete: Cascade)
|
||||
option CommissionOption @relation(fields: [optionId], references: [id])
|
||||
|
||||
@@unique([cardId, optionId])
|
||||
}
|
||||
|
||||
model CommissionCustomInput {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
@ -368,6 +442,25 @@ model CommissionTypeCustomInput {
|
||||
@@unique([typeId, customInputId])
|
||||
}
|
||||
|
||||
model CommissionCustomCardExtra {
|
||||
id String @id @default(cuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
sortIndex Int @default(0)
|
||||
|
||||
cardId String
|
||||
extraId String
|
||||
|
||||
priceRange String?
|
||||
pricePercent Float?
|
||||
price Float?
|
||||
|
||||
card CommissionCustomCard @relation(fields: [cardId], references: [id], onDelete: Cascade)
|
||||
extra CommissionExtra @relation(fields: [extraId], references: [id])
|
||||
|
||||
@@unique([cardId, extraId])
|
||||
}
|
||||
|
||||
model CommissionRequest {
|
||||
id String @id @default(cuid())
|
||||
index Int @default(autoincrement())
|
||||
@ -386,8 +479,10 @@ model CommissionRequest {
|
||||
|
||||
optionId String?
|
||||
typeId String?
|
||||
customCardId String?
|
||||
option CommissionOption? @relation(fields: [optionId], references: [id])
|
||||
type CommissionType? @relation(fields: [typeId], references: [id])
|
||||
customCard CommissionCustomCard? @relation(fields: [customCardId], references: [id])
|
||||
|
||||
extras CommissionExtra[]
|
||||
files CommissionRequestFile[]
|
||||
|
||||
@ -4,6 +4,7 @@ import { prisma } from "@/lib/prisma";
|
||||
import { s3 } from "@/lib/s3";
|
||||
import { DeleteObjectCommand } from "@aws-sdk/client-s3";
|
||||
|
||||
// Deletes an artwork and all related assets and records.
|
||||
export async function deleteArtwork(artworkId: string) {
|
||||
const artwork = await prisma.artwork.findUnique({
|
||||
where: { id: artworkId },
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { getImageBufferFromS3Key } from "@/utils/getImageBufferFromS3";
|
||||
|
||||
export async function generateAltTextForArtwork(
|
||||
artworkId: string,
|
||||
prompt?: string,
|
||||
) {
|
||||
const serviceUrl = process.env.ALT_TEXT_SERVICE_URL;
|
||||
if (!serviceUrl) {
|
||||
throw new Error("ALT_TEXT_SERVICE_URL is not set");
|
||||
}
|
||||
|
||||
const artwork = await prisma.artwork.findUnique({
|
||||
where: { id: artworkId },
|
||||
select: {
|
||||
variants: {
|
||||
where: { type: "original" },
|
||||
select: { s3Key: true },
|
||||
take: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const original = artwork?.variants?.[0];
|
||||
if (!original?.s3Key) {
|
||||
throw new Error("Original image variant not found");
|
||||
}
|
||||
|
||||
const buffer = await getImageBufferFromS3Key(original.s3Key);
|
||||
|
||||
const formData = new FormData();
|
||||
const bytes = new Uint8Array(buffer);
|
||||
formData.append(
|
||||
"image",
|
||||
new Blob([bytes], { type: "image/jpeg" }),
|
||||
"artwork.jpg",
|
||||
);
|
||||
if (prompt && prompt.trim().length > 0) {
|
||||
formData.append("prompt", prompt.trim());
|
||||
}
|
||||
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 120000);
|
||||
|
||||
let response: Response | null = null;
|
||||
let lastError: unknown = null;
|
||||
|
||||
for (let attempt = 0; attempt < 2; attempt += 1) {
|
||||
try {
|
||||
response = await fetch(`${serviceUrl}/caption`, {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
signal: controller.signal,
|
||||
});
|
||||
break;
|
||||
} catch (err) {
|
||||
lastError = err;
|
||||
if (attempt === 0) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 750));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (!response) {
|
||||
throw new Error(`Alt text service failed: ${String(lastError)}`);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text();
|
||||
throw new Error(`Alt text service failed: ${text}`);
|
||||
}
|
||||
|
||||
const data = (await response.json()) as { altText?: string; error?: string };
|
||||
if (data.error) {
|
||||
throw new Error(`Alt text service error: ${data.error}`);
|
||||
}
|
||||
if (!data.altText) {
|
||||
throw new Error(`Alt text service returned no result: ${JSON.stringify(data)}`);
|
||||
}
|
||||
|
||||
return data.altText.trim();
|
||||
}
|
||||
@ -1,36 +1,49 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { VibrantSwatch } from "@/types/VibrantSwatch";
|
||||
import type { VibrantSwatch } from "@/types/VibrantSwatch";
|
||||
import { getImageBufferFromS3Key } from "@/utils/getImageBufferFromS3";
|
||||
import { generateColorName, rgbToHex } from "@/utils/uploadHelper";
|
||||
import { converter, parse } from "culori";
|
||||
import { Vibrant } from "node-vibrant/node";
|
||||
|
||||
const toOklab = converter("oklab");
|
||||
const A_MIN = -0.5, A_MAX = 0.5;
|
||||
const B_MIN = -0.5, B_MAX = 0.5;
|
||||
const A_MIN = -0.5,
|
||||
A_MAX = 0.5;
|
||||
const B_MIN = -0.5,
|
||||
B_MAX = 0.5;
|
||||
|
||||
function clamp01(x: number) { return Math.max(0, Math.min(1, x)); }
|
||||
function norm(x: number, lo: number, hi: number) { return clamp01((x - lo) / (hi - lo)); }
|
||||
function clamp01(x: number) {
|
||||
return Math.max(0, Math.min(1, x));
|
||||
}
|
||||
function norm(x: number, lo: number, hi: number) {
|
||||
return clamp01((x - lo) / (hi - lo));
|
||||
}
|
||||
|
||||
function hilbertIndex15(x01: number, y01: number): number {
|
||||
let x = Math.floor(clamp01(x01) * 32767);
|
||||
let y = Math.floor(clamp01(y01) * 32767);
|
||||
let index = 0;
|
||||
for (let s = 1 << 14; s > 0; s >>= 1) {
|
||||
const rx = (x & s) ? 1 : 0;
|
||||
const ry = (y & s) ? 1 : 0;
|
||||
const rx = x & s ? 1 : 0;
|
||||
const ry = y & s ? 1 : 0;
|
||||
index += s * s * ((3 * rx) ^ ry);
|
||||
if (ry === 0) {
|
||||
if (rx === 1) { x = 32767 - x; y = 32767 - y; }
|
||||
const t = x; x = y; y = t;
|
||||
if (rx === 1) {
|
||||
x = 32767 - x;
|
||||
y = 32767 - y;
|
||||
}
|
||||
const t = x;
|
||||
x = y;
|
||||
y = t;
|
||||
}
|
||||
}
|
||||
return index >>> 0;
|
||||
}
|
||||
|
||||
function centroidFromPaletteHexes(hexByType: Record<string, string | undefined>) {
|
||||
function centroidFromPaletteHexes(
|
||||
hexByType: Record<string, string | undefined>,
|
||||
) {
|
||||
const weights: Record<string, number> = {
|
||||
Vibrant: 0.7,
|
||||
Muted: 0.15,
|
||||
@ -41,21 +54,27 @@ function centroidFromPaletteHexes(hexByType: Record<string, string | undefined>)
|
||||
};
|
||||
|
||||
const fallbackHex =
|
||||
hexByType["Vibrant"] ||
|
||||
hexByType["Muted"] ||
|
||||
hexByType["DarkVibrant"] ||
|
||||
hexByType["DarkMuted"] ||
|
||||
hexByType["LightVibrant"] ||
|
||||
hexByType["LightMuted"];
|
||||
hexByType.Vibrant ||
|
||||
hexByType.Muted ||
|
||||
hexByType.DarkVibrant ||
|
||||
hexByType.DarkMuted ||
|
||||
hexByType.LightVibrant ||
|
||||
hexByType.LightMuted;
|
||||
|
||||
let L = 0, A = 0, B = 0, W = 0;
|
||||
let L = 0,
|
||||
A = 0,
|
||||
B = 0,
|
||||
W = 0;
|
||||
|
||||
for (const [type, w] of Object.entries(weights)) {
|
||||
const hex = hexByType[type] ?? fallbackHex;
|
||||
if (!hex || w <= 0) continue;
|
||||
const c = toOklab(parse(hex));
|
||||
if (!c) continue;
|
||||
L += c.l * w; A += c.a * w; B += c.b * w; W += w;
|
||||
L += c.l * w;
|
||||
A += c.a * w;
|
||||
B += c.b * w;
|
||||
W += w;
|
||||
}
|
||||
|
||||
if (W === 0) return { l: 0.5, a: 0, b: 0 };
|
||||
@ -78,7 +97,11 @@ export async function generateArtworkColorsForArtwork(artworkId: string) {
|
||||
where: { id: artworkId },
|
||||
select: {
|
||||
file: { select: { fileKey: true } },
|
||||
variants: { where: { type: "original" }, select: { s3Key: true }, take: 1 },
|
||||
variants: {
|
||||
where: { type: "original" },
|
||||
select: { s3Key: true },
|
||||
take: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!artwork) throw new Error("Artwork not found");
|
||||
@ -100,7 +123,9 @@ export async function generateArtworkColorsForArtwork(artworkId: string) {
|
||||
for (const { type, hex } of vibrantHexes) {
|
||||
if (!hex) continue;
|
||||
|
||||
const [r, g, b] = hex.match(/\w\w/g)!.map((h) => parseInt(h, 16));
|
||||
const match = hex.match(/\w\w/g);
|
||||
if (!match) continue;
|
||||
const [r, g, b] = match.map((h) => parseInt(h, 16));
|
||||
const name = generateColorName(hex);
|
||||
|
||||
const color = await prisma.color.upsert({
|
||||
@ -117,11 +142,14 @@ export async function generateArtworkColorsForArtwork(artworkId: string) {
|
||||
}
|
||||
|
||||
const hexByType: Record<string, string | undefined> = Object.fromEntries(
|
||||
vibrantHexes.map(({ type, hex }) => [type, hex])
|
||||
vibrantHexes.map(({ type, hex }) => [type, hex]),
|
||||
);
|
||||
|
||||
const { l, a, b } = centroidFromPaletteHexes(hexByType);
|
||||
const sortKey = hilbertIndex15(norm(a, A_MIN, A_MAX), norm(b, B_MIN, B_MAX));
|
||||
const sortKey = hilbertIndex15(
|
||||
norm(a, A_MIN, A_MAX),
|
||||
norm(b, B_MIN, B_MAX),
|
||||
);
|
||||
|
||||
await prisma.artwork.update({
|
||||
where: { id: artworkId },
|
||||
@ -144,6 +172,9 @@ export async function generateArtworkColorsForArtwork(artworkId: string) {
|
||||
colorError: e instanceof Error ? e.message : "Color generation failed",
|
||||
},
|
||||
});
|
||||
return { ok: false as const, error: e instanceof Error ? e.message : "Color generation failed" };
|
||||
return {
|
||||
ok: false as const,
|
||||
error: e instanceof Error ? e.message : "Color generation failed",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import sharp from "sharp";
|
||||
|
||||
const GALLERY_TARGET_SIZE = 300;
|
||||
|
||||
// Generates a gallery-sized variant for a single artwork.
|
||||
export async function generateGalleryVariant(
|
||||
artworkId: string,
|
||||
opts?: { force?: boolean },
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Returns color swatches for a given artwork.
|
||||
export async function getArtworkColors(artworkId: string) {
|
||||
return prisma.artworkColor.findMany({
|
||||
where: { artworkId },
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Returns album/category options for artwork filters.
|
||||
export async function getArtworkFilterOptions() {
|
||||
const [albums, categories] = await Promise.all([
|
||||
prisma.album.findMany({ select: { id: true, name: true }, orderBy: { name: "asc" } }),
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Loads a single artwork with relations for the edit page.
|
||||
export async function getSingleArtwork(id: string) {
|
||||
return await prisma.artwork.findUnique({
|
||||
return prisma.artwork.findUnique({
|
||||
where: { id },
|
||||
include: {
|
||||
// album: true,
|
||||
@ -17,7 +18,7 @@ export async function getSingleArtwork(id: string) {
|
||||
// sortContexts: true,
|
||||
tags: true,
|
||||
variants: true,
|
||||
timelapse: true
|
||||
}
|
||||
})
|
||||
timelapse: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -1,15 +1,19 @@
|
||||
"use server";
|
||||
|
||||
import type { Prisma } from "@/generated/prisma/client";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { ArtworkTableInput, artworkTableInputSchema, artworkTableOutputSchema } from "@/schemas/artworks/tableSchema";
|
||||
import { type ArtworkTableInput, artworkTableInputSchema, artworkTableOutputSchema } from "@/schemas/artworks/tableSchema";
|
||||
|
||||
// Builds the admin artworks table page with filters, sorting, and pagination.
|
||||
function triToBool(tri: "any" | "true" | "false"): boolean | undefined {
|
||||
if (tri === "any") return undefined;
|
||||
return tri === "true";
|
||||
}
|
||||
|
||||
function mapSortingToOrderBy(sorting: ArtworkTableInput["sorting"]) {
|
||||
const allowed: Record<string, (desc: boolean) => any> = {
|
||||
function mapSortingToOrderBy(
|
||||
sorting: ArtworkTableInput["sorting"]
|
||||
): Prisma.ArtworkOrderByWithRelationInput[] {
|
||||
const allowed: Record<string, (desc: boolean) => Prisma.ArtworkOrderByWithRelationInput> = {
|
||||
createdAt: (desc) => ({ createdAt: desc ? "desc" : "asc" }),
|
||||
updatedAt: (desc) => ({ updatedAt: desc ? "desc" : "asc" }),
|
||||
sortIndex: (desc) => ({ sortIndex: desc ? "desc" : "asc" }),
|
||||
@ -25,9 +29,10 @@ function mapSortingToOrderBy(sorting: ArtworkTableInput["sorting"]) {
|
||||
tagsCount: (desc) => ({ tags: { _count: desc ? "desc" : "asc" } }),
|
||||
};
|
||||
|
||||
const orderBy = sorting
|
||||
.map((s) => allowed[s.id]?.(s.desc))
|
||||
.filter(Boolean);
|
||||
const orderBy = sorting.flatMap((s) => {
|
||||
const mapper = allowed[s.id];
|
||||
return mapper ? [mapper(s.desc)] : [];
|
||||
});
|
||||
|
||||
orderBy.push({ id: "desc" });
|
||||
return orderBy;
|
||||
@ -44,7 +49,7 @@ export async function getArtworksTablePage(input: unknown) {
|
||||
const nsfw = triToBool(filters.nsfw);
|
||||
const needsWork = triToBool(filters.needsWork);
|
||||
|
||||
const where: any = {
|
||||
const where: Prisma.ArtworkWhereInput = {
|
||||
...(typeof published === "boolean" ? { published } : {}),
|
||||
...(typeof nsfw === "boolean" ? { nsfw } : {}),
|
||||
...(typeof needsWork === "boolean" ? { needsWork } : {}),
|
||||
|
||||
@ -1,13 +1,9 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import type { GalleryVariantStats } from "@/types/Artwork";
|
||||
|
||||
export type GalleryVariantStats = {
|
||||
total: number;
|
||||
withGallery: number;
|
||||
missing: number;
|
||||
};
|
||||
|
||||
// Returns counts for gallery variant presence.
|
||||
export async function getGalleryVariantStats(): Promise<GalleryVariantStats> {
|
||||
const [total, withGallery] = await Promise.all([
|
||||
prisma.artwork.count(),
|
||||
|
||||
@ -2,25 +2,30 @@
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { s3 } from "@/lib/s3";
|
||||
import {
|
||||
confirmArtworkTimelapseUploadSchema,
|
||||
createArtworkTimelapseUploadSchema,
|
||||
deleteArtworkTimelapseSchema,
|
||||
setArtworkTimelapseEnabledSchema,
|
||||
} from "@/schemas/artworks/timelapse";
|
||||
import type {
|
||||
ConfirmArtworkTimelapseUploadInput,
|
||||
CreateArtworkTimelapseUploadInput,
|
||||
DeleteArtworkTimelapseInput,
|
||||
SetArtworkTimelapseEnabledInput,
|
||||
} from "@/schemas/artworks/timelapse";
|
||||
import { PutObjectCommand, DeleteObjectCommand } from "@aws-sdk/client-s3";
|
||||
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { z } from "zod/v4";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
const createUploadSchema = z.object({
|
||||
artworkId: z.string().min(1),
|
||||
fileName: z.string().min(1),
|
||||
mimeType: z.string().min(1),
|
||||
sizeBytes: z.number().int().positive(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a presigned PUT url so the client can upload large timelapse videos directly to S3
|
||||
* (avoids Next.js body-size/proxy limits).
|
||||
*/
|
||||
export async function createArtworkTimelapseUpload(input: z.infer<typeof createUploadSchema>) {
|
||||
const { artworkId, fileName, mimeType, sizeBytes } = createUploadSchema.parse(input);
|
||||
export async function createArtworkTimelapseUpload(input: CreateArtworkTimelapseUploadInput) {
|
||||
const { artworkId, fileName, mimeType, sizeBytes } =
|
||||
createArtworkTimelapseUploadSchema.parse(input);
|
||||
|
||||
const ext = fileName.includes(".") ? fileName.split(".").pop() : undefined;
|
||||
const suffix = ext ? `.${ext}` : "";
|
||||
@ -41,17 +46,10 @@ export async function createArtworkTimelapseUpload(input: z.infer<typeof createU
|
||||
return { uploadUrl, s3Key, fileName, mimeType, sizeBytes };
|
||||
}
|
||||
|
||||
const confirmSchema = z.object({
|
||||
artworkId: z.string().min(1),
|
||||
s3Key: z.string().min(1),
|
||||
fileName: z.string().min(1),
|
||||
mimeType: z.string().min(1),
|
||||
sizeBytes: z.number().int().positive(),
|
||||
});
|
||||
|
||||
/** Persist uploaded timelapse metadata in DB (upsert by artworkId). */
|
||||
export async function confirmArtworkTimelapseUpload(input: z.infer<typeof confirmSchema>) {
|
||||
const { artworkId, s3Key, fileName, mimeType, sizeBytes } = confirmSchema.parse(input);
|
||||
export async function confirmArtworkTimelapseUpload(input: ConfirmArtworkTimelapseUploadInput) {
|
||||
const { artworkId, s3Key, fileName, mimeType, sizeBytes } =
|
||||
confirmArtworkTimelapseUploadSchema.parse(input);
|
||||
|
||||
// If an old timelapse exists, delete the old object so you don't leak storage.
|
||||
const existing = await prisma.artworkTimelapse.findUnique({ where: { artworkId } });
|
||||
@ -91,13 +89,8 @@ export async function confirmArtworkTimelapseUpload(input: z.infer<typeof confir
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const enabledSchema = z.object({
|
||||
artworkId: z.string().min(1),
|
||||
enabled: z.boolean(),
|
||||
});
|
||||
|
||||
export async function setArtworkTimelapseEnabled(input: z.infer<typeof enabledSchema>) {
|
||||
const { artworkId, enabled } = enabledSchema.parse(input);
|
||||
export async function setArtworkTimelapseEnabled(input: SetArtworkTimelapseEnabledInput) {
|
||||
const { artworkId, enabled } = setArtworkTimelapseEnabledSchema.parse(input);
|
||||
|
||||
await prisma.artworkTimelapse.update({
|
||||
where: { artworkId },
|
||||
@ -108,12 +101,8 @@ export async function setArtworkTimelapseEnabled(input: z.infer<typeof enabledSc
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const deleteSchema = z.object({
|
||||
artworkId: z.string().min(1),
|
||||
});
|
||||
|
||||
export async function deleteArtworkTimelapse(input: z.infer<typeof deleteSchema>) {
|
||||
const { artworkId } = deleteSchema.parse(input);
|
||||
export async function deleteArtworkTimelapse(input: DeleteArtworkTimelapseInput) {
|
||||
const { artworkId } = deleteArtworkTimelapseSchema.parse(input);
|
||||
|
||||
const existing = await prisma.artworkTimelapse.findUnique({ where: { artworkId } });
|
||||
if (!existing) return { ok: true };
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { artworkSchema } from "@/schemas/artworks/imageSchema";
|
||||
import { normalizeNames, slugify } from "@/utils/artworkHelpers";
|
||||
import { z } from "zod/v4";
|
||||
import type { z } from "zod/v4";
|
||||
|
||||
// Updates an artwork and its tag/category relationships.
|
||||
export async function updateArtwork(
|
||||
values: z.infer<typeof artworkSchema>,
|
||||
id: string
|
||||
@ -36,12 +37,11 @@ export async function updateArtwork(
|
||||
const categoriesToCreate = normalizeNames(newCategoryNames);
|
||||
|
||||
const updatedArtwork = await prisma.$transaction(async (tx) => {
|
||||
|
||||
if (setAsHeader) {
|
||||
await tx.artwork.updateMany({
|
||||
where: { setAsHeader: true },
|
||||
data: { setAsHeader: false },
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const tagsRelation =
|
||||
@ -73,7 +73,7 @@ export async function updateArtwork(
|
||||
: {};
|
||||
|
||||
return tx.artwork.update({
|
||||
where: { id: id },
|
||||
where: { id },
|
||||
data: {
|
||||
name,
|
||||
slug: slugify(name),
|
||||
|
||||
@ -2,28 +2,25 @@
|
||||
|
||||
import { auth } from "@/lib/auth";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { z } from "zod/v4";
|
||||
import type { RegisterFirstUserInput } from "@/schemas/auth";
|
||||
import { registerFirstUserSchema } from "@/schemas/auth";
|
||||
import type { SignUpResponse } from "@/types/auth";
|
||||
|
||||
const schema = z.object({
|
||||
name: z.string().min(1).max(200),
|
||||
email: z.string().email().max(320),
|
||||
password: z.string().min(8).max(128),
|
||||
});
|
||||
|
||||
export async function registerFirstUser(input: z.infer<typeof schema>) {
|
||||
// Registers the very first user and upgrades them to admin.
|
||||
export async function registerFirstUser(input: RegisterFirstUserInput) {
|
||||
const count = await prisma.user.count();
|
||||
if (count !== 0) throw new Error("Registration is disabled.");
|
||||
|
||||
const { name, email, password } = schema.parse(input);
|
||||
const { name, email, password } = registerFirstUserSchema.parse(input);
|
||||
|
||||
const res = await auth.api.signUpEmail({
|
||||
const res = (await auth.api.signUpEmail({
|
||||
body: { name, email, password },
|
||||
});
|
||||
})) as SignUpResponse;
|
||||
|
||||
const userId =
|
||||
(res as any)?.user?.id ??
|
||||
(res as any)?.data?.user?.id ??
|
||||
(res as any)?.data?.id;
|
||||
res.user?.id ??
|
||||
res.data?.user?.id ??
|
||||
res.data?.id;
|
||||
|
||||
if (!userId) throw new Error("Signup failed: no user id returned.");
|
||||
|
||||
|
||||
@ -1,25 +1,27 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { categorySchema } from "@/schemas/artworks/categorySchema"
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { categorySchema } from "@/schemas/artworks/categorySchema";
|
||||
import type * as z from "zod/v4";
|
||||
|
||||
export async function createCategory(formData: categorySchema) {
|
||||
const parsed = categorySchema.safeParse(formData)
|
||||
// Creates a new artwork category.
|
||||
export async function createCategory(formData: z.infer<typeof categorySchema>) {
|
||||
const parsed = categorySchema.safeParse(formData);
|
||||
|
||||
if (!parsed.success) {
|
||||
console.error("Validation failed", parsed.error)
|
||||
throw new Error("Invalid input")
|
||||
console.error("Validation failed", parsed.error);
|
||||
throw new Error("Invalid input");
|
||||
}
|
||||
|
||||
const data = parsed.data
|
||||
const data = parsed.data;
|
||||
|
||||
const created = await prisma.artCategory.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
slug: data.slug,
|
||||
description: data.description
|
||||
description: data.description,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
return created
|
||||
return created;
|
||||
}
|
||||
@ -3,6 +3,7 @@
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
// Deletes a category if it is not referenced by artworks or tags.
|
||||
export async function deleteCategory(catId: string) {
|
||||
const cat = await prisma.artCategory.findUnique({
|
||||
where: { id: catId },
|
||||
@ -10,8 +11,8 @@ export async function deleteCategory(catId: string) {
|
||||
id: true,
|
||||
_count: {
|
||||
select: {
|
||||
tags: true,
|
||||
artworks: true
|
||||
tagLinks: true,
|
||||
artworks: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -25,7 +26,7 @@ export async function deleteCategory(catId: string) {
|
||||
throw new Error("Cannot delete category: it is used by artworks.");
|
||||
}
|
||||
|
||||
if (cat._count.tags > 0) {
|
||||
if (cat._count.tagLinks > 0) {
|
||||
throw new Error("Cannot delete category: it is used by tags.");
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Category data fetchers for admin pages.
|
||||
export async function getCategoriesWithTags() {
|
||||
return await prisma.artCategory.findMany({ include: { tags: true }, orderBy: { sortIndex: "asc" } })
|
||||
return prisma.artCategory.findMany({
|
||||
include: { tagLinks: { include: { tag: true } } },
|
||||
orderBy: { sortIndex: "asc" },
|
||||
});
|
||||
}
|
||||
|
||||
export async function getCategoriesWithCount() {
|
||||
return await prisma.artCategory.findMany({
|
||||
return prisma.artCategory.findMany({
|
||||
include: {
|
||||
_count: { select: { artworks: true, tags: true } },
|
||||
_count: { select: { artworks: true, tagLinks: true } },
|
||||
},
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
})
|
||||
});
|
||||
}
|
||||
@ -1,27 +1,28 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { categorySchema } from '@/schemas/artworks/categorySchema';
|
||||
import { z } from 'zod/v4';
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { categorySchema } from "@/schemas/artworks/categorySchema";
|
||||
import type * as z from "zod/v4";
|
||||
|
||||
// Updates an artwork category by id.
|
||||
export async function updateCategory(id: string, rawData: z.infer<typeof categorySchema>) {
|
||||
const parsed = categorySchema.safeParse(rawData)
|
||||
const parsed = categorySchema.safeParse(rawData);
|
||||
|
||||
if (!parsed.success) {
|
||||
console.error("Validation failed", parsed.error)
|
||||
throw new Error("Invalid input")
|
||||
console.error("Validation failed", parsed.error);
|
||||
throw new Error("Invalid input");
|
||||
}
|
||||
|
||||
const data = parsed.data
|
||||
const data = parsed.data;
|
||||
|
||||
const updated = await prisma.artCategory.update({
|
||||
where: { id },
|
||||
data: {
|
||||
name: data.name,
|
||||
slug: data.slug,
|
||||
description: data.description
|
||||
description: data.description,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
return updated
|
||||
return updated;
|
||||
}
|
||||
@ -1,16 +1,9 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import type { ArtworkColorStats } from "@/types/colors";
|
||||
|
||||
export type ArtworkColorStats = {
|
||||
total: number;
|
||||
ready: number;
|
||||
pending: number;
|
||||
processing: number;
|
||||
failed: number;
|
||||
missingSortKey: number;
|
||||
};
|
||||
|
||||
// Aggregates color-processing status counts for artworks.
|
||||
export async function getArtworkColorStats(): Promise<ArtworkColorStats> {
|
||||
const [
|
||||
total,
|
||||
|
||||
@ -1,17 +1,11 @@
|
||||
"use server";
|
||||
|
||||
import { Prisma } from "@/generated/prisma/client";
|
||||
import type { Prisma } from "@/generated/prisma/client";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { generateArtworkColorsForArtwork } from "../artworks/generateArtworkColors";
|
||||
import type { ProcessColorsResult } from "@/types/colors";
|
||||
|
||||
export type ProcessColorsResult = {
|
||||
picked: number;
|
||||
processed: number;
|
||||
ok: number;
|
||||
failed: number;
|
||||
results: Array<{ artworkId: string; ok: boolean; error?: string }>;
|
||||
};
|
||||
|
||||
// Processes pending/failed artwork colors with a configurable batch size.
|
||||
export async function processPendingArtworkColors(args?: {
|
||||
limit?: number;
|
||||
includeFailed?: boolean;
|
||||
|
||||
10
src/actions/commissions/customCards/deleteCard.ts
Normal file
10
src/actions/commissions/customCards/deleteCard.ts
Normal file
@ -0,0 +1,10 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Deletes a custom commission card by id.
|
||||
export async function deleteCommissionCustomCard(id: string) {
|
||||
await prisma.commissionCustomCard.delete({
|
||||
where: { id },
|
||||
});
|
||||
}
|
||||
88
src/actions/commissions/customCards/images.ts
Normal file
88
src/actions/commissions/customCards/images.ts
Normal file
@ -0,0 +1,88 @@
|
||||
"use server";
|
||||
|
||||
import { s3 } from "@/lib/s3";
|
||||
import type { CommissionCustomCardImageItem } from "@/types/commissions";
|
||||
import {
|
||||
DeleteObjectCommand,
|
||||
ListObjectsV2Command,
|
||||
PutObjectCommand,
|
||||
} from "@aws-sdk/client-s3";
|
||||
|
||||
const PREFIX = "commissions/custom-cards/";
|
||||
|
||||
function buildImageUrl(key: string) {
|
||||
return `/api/image/${encodeURI(key)}`;
|
||||
}
|
||||
|
||||
function sanitizeFilename(name: string) {
|
||||
return name.replace(/[^a-zA-Z0-9._-]/g, "_");
|
||||
}
|
||||
|
||||
export async function listCommissionCustomCardImages(): Promise<
|
||||
CommissionCustomCardImageItem[]
|
||||
> {
|
||||
const command = new ListObjectsV2Command({
|
||||
Bucket: `${process.env.BUCKET_NAME}`,
|
||||
Prefix: PREFIX,
|
||||
});
|
||||
|
||||
const res = await s3.send(command);
|
||||
return (
|
||||
res.Contents?.filter((obj) => obj.Key && obj.Key !== PREFIX).map((obj) => {
|
||||
const key = obj.Key as string;
|
||||
return {
|
||||
key,
|
||||
url: buildImageUrl(key),
|
||||
size: obj.Size ?? null,
|
||||
lastModified: obj.LastModified?.toISOString() ?? null,
|
||||
};
|
||||
}) ?? []
|
||||
);
|
||||
}
|
||||
|
||||
export async function uploadCommissionCustomCardImage(
|
||||
formData: FormData
|
||||
): Promise<CommissionCustomCardImageItem> {
|
||||
const file = formData.get("file");
|
||||
|
||||
if (!(file instanceof File)) {
|
||||
throw new Error("Missing file");
|
||||
}
|
||||
|
||||
if (!file.type.startsWith("image/")) {
|
||||
throw new Error("Only image uploads are allowed");
|
||||
}
|
||||
|
||||
const safeName = sanitizeFilename(file.name || "custom-card");
|
||||
const key = `${PREFIX}${Date.now()}-${safeName}`;
|
||||
const buffer = Buffer.from(await file.arrayBuffer());
|
||||
|
||||
await s3.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: `${process.env.BUCKET_NAME}`,
|
||||
Key: key,
|
||||
Body: buffer,
|
||||
ContentType: file.type,
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
key,
|
||||
url: buildImageUrl(key),
|
||||
size: file.size,
|
||||
lastModified: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function deleteCommissionCustomCardImage(key: string) {
|
||||
if (!key.startsWith(PREFIX)) {
|
||||
throw new Error("Invalid key");
|
||||
}
|
||||
|
||||
await s3.send(
|
||||
new DeleteObjectCommand({
|
||||
Bucket: `${process.env.BUCKET_NAME}`,
|
||||
Key: key,
|
||||
})
|
||||
);
|
||||
}
|
||||
56
src/actions/commissions/customCards/newCard.ts
Normal file
56
src/actions/commissions/customCards/newCard.ts
Normal file
@ -0,0 +1,56 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import {
|
||||
commissionCustomCardSchema,
|
||||
type CommissionCustomCardValues,
|
||||
} from "@/schemas/commissionCustomCard";
|
||||
|
||||
// Creates a new custom commission card with options/extras.
|
||||
export async function createCommissionCustomCard(
|
||||
formData: CommissionCustomCardValues
|
||||
) {
|
||||
const parsed = commissionCustomCardSchema.safeParse(formData);
|
||||
|
||||
if (!parsed.success) {
|
||||
console.error("Validation failed", parsed.error);
|
||||
throw new Error("Invalid input");
|
||||
}
|
||||
|
||||
const data = parsed.data;
|
||||
|
||||
const created = await prisma.commissionCustomCard.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
referenceImageUrl: data.referenceImageUrl ?? null,
|
||||
isVisible: data.isVisible ?? true,
|
||||
isSpecialOffer: data.isSpecialOffer ?? false,
|
||||
tags: data.tagIds?.length
|
||||
? { connect: data.tagIds.map((id) => ({ id })) }
|
||||
: undefined,
|
||||
options: {
|
||||
create:
|
||||
data.options?.map((opt, index) => ({
|
||||
option: { connect: { id: opt.optionId } },
|
||||
price: opt.price,
|
||||
pricePercent: opt.pricePercent,
|
||||
priceRange: opt.priceRange,
|
||||
sortIndex: index,
|
||||
})) ?? [],
|
||||
},
|
||||
extras: {
|
||||
create:
|
||||
data.extras?.map((ext, index) => ({
|
||||
extra: { connect: { id: ext.extraId } },
|
||||
price: ext.price,
|
||||
pricePercent: ext.pricePercent,
|
||||
priceRange: ext.priceRange,
|
||||
sortIndex: index,
|
||||
})) ?? [],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return created;
|
||||
}
|
||||
58
src/actions/commissions/customCards/updateCard.ts
Normal file
58
src/actions/commissions/customCards/updateCard.ts
Normal file
@ -0,0 +1,58 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import {
|
||||
commissionCustomCardSchema,
|
||||
type CommissionCustomCardValues,
|
||||
} from "@/schemas/commissionCustomCard";
|
||||
|
||||
// Updates a custom commission card and resets related options/extras.
|
||||
export async function updateCommissionCustomCard(
|
||||
id: string,
|
||||
rawData: CommissionCustomCardValues
|
||||
) {
|
||||
const data = commissionCustomCardSchema.parse(rawData);
|
||||
|
||||
const updated = await prisma.commissionCustomCard.update({
|
||||
where: { id },
|
||||
data: {
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
referenceImageUrl: data.referenceImageUrl ?? null,
|
||||
isVisible: data.isVisible ?? true,
|
||||
isSpecialOffer: data.isSpecialOffer ?? false,
|
||||
tags: data.tagIds
|
||||
? {
|
||||
set: [],
|
||||
connect: data.tagIds.map((id) => ({ id })),
|
||||
}
|
||||
: undefined,
|
||||
options: {
|
||||
deleteMany: {},
|
||||
create: data.options?.map((opt, index) => ({
|
||||
option: { connect: { id: opt.optionId } },
|
||||
price: opt.price ?? null,
|
||||
pricePercent: opt.pricePercent ?? null,
|
||||
priceRange: opt.priceRange ?? null,
|
||||
sortIndex: index,
|
||||
})),
|
||||
},
|
||||
extras: {
|
||||
deleteMany: {},
|
||||
create: data.extras?.map((ext, index) => ({
|
||||
extra: { connect: { id: ext.extraId } },
|
||||
price: ext.price ?? null,
|
||||
pricePercent: ext.pricePercent ?? null,
|
||||
priceRange: ext.priceRange ?? null,
|
||||
sortIndex: index,
|
||||
})),
|
||||
},
|
||||
},
|
||||
include: {
|
||||
options: true,
|
||||
extras: true,
|
||||
},
|
||||
});
|
||||
|
||||
return updated;
|
||||
}
|
||||
17
src/actions/commissions/customCards/updateSortOrder.ts
Normal file
17
src/actions/commissions/customCards/updateSortOrder.ts
Normal file
@ -0,0 +1,17 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Updates sort order for custom commission cards.
|
||||
export async function updateCommissionCustomCardSortOrder(
|
||||
items: { id: string; sortIndex: number }[]
|
||||
) {
|
||||
await prisma.$transaction(
|
||||
items.map((item) =>
|
||||
prisma.commissionCustomCard.update({
|
||||
where: { id: item.id },
|
||||
data: { sortIndex: item.sortIndex },
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
"use server";
|
||||
|
||||
import { s3 } from "@/lib/s3";
|
||||
import type { CommissionExampleItem } from "@/types/commissions";
|
||||
import {
|
||||
DeleteObjectCommand,
|
||||
ListObjectsV2Command,
|
||||
@ -9,13 +10,6 @@ import {
|
||||
|
||||
const PREFIX = "commissions/examples/";
|
||||
|
||||
export type CommissionExampleItem = {
|
||||
key: string;
|
||||
url: string;
|
||||
size: number | null;
|
||||
lastModified: string | null;
|
||||
};
|
||||
|
||||
function buildImageUrl(key: string) {
|
||||
return `/api/image/${encodeURI(key)}`;
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
'use server';
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Returns the latest active commission guidelines (markdown + example image).
|
||||
export async function getActiveGuidelines(): Promise<{
|
||||
markdown: string | null;
|
||||
exampleImageUrl: string | null;
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
'use server';
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Deactivates existing guidelines and creates a new active version.
|
||||
export async function saveGuidelines(markdown: string, exampleImageUrl: string | null) {
|
||||
await prisma.commissionGuidelines.updateMany({
|
||||
where: { isActive: true },
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
// Deletes a commission request by id.
|
||||
export async function deleteCommissionRequest(id: string) {
|
||||
const parsed = z.string().min(1).parse(id);
|
||||
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { calculatePriceRange, PriceSource } from "@/utils/commissionPricing";
|
||||
import { calculatePriceRange, type PriceSource } from "@/utils/commissionPricing";
|
||||
|
||||
// Loads a commission request with related data and computed price estimate.
|
||||
export async function getCommissionRequestById(id: string) {
|
||||
const req = await prisma.commissionRequest.findUnique({
|
||||
where: { id },
|
||||
|
||||
@ -1,39 +1,24 @@
|
||||
"use server";
|
||||
|
||||
import type { Prisma } from "@/generated/prisma/client";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import {
|
||||
commissionRequestTableRowSchema,
|
||||
commissionStatusSchema,
|
||||
} from "@/schemas/commissions/requests";
|
||||
import { z } from "zod";
|
||||
|
||||
export type CursorPagination = { pageIndex: number; pageSize: number };
|
||||
export type SortDir = "asc" | "desc";
|
||||
|
||||
const triStateSchema = z.enum(["any", "true", "false"]);
|
||||
|
||||
const sortingSchema = z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
desc: z.boolean(),
|
||||
})
|
||||
);
|
||||
|
||||
const filtersSchema = z.object({
|
||||
q: z.string().optional(),
|
||||
email: z.string().optional(),
|
||||
status: z.union([z.literal("any"), commissionStatusSchema]).default("any"),
|
||||
hasFiles: triStateSchema.default("any"),
|
||||
});
|
||||
import { commissionRequestTableRowSchema } from "@/schemas/commissions/requests";
|
||||
import type {
|
||||
CommissionRequestsTableFilters,
|
||||
CommissionRequestsTableSorting,
|
||||
} from "@/schemas/commissions/requestsTable";
|
||||
import type { CursorPagination } from "@/types/pagination";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
// Builds a paginated, filtered, and sorted commission-requests table payload for the admin UI.
|
||||
export async function getCommissionRequestsTablePage(input: {
|
||||
pagination: CursorPagination;
|
||||
sorting: z.infer<typeof sortingSchema>;
|
||||
filters: z.infer<typeof filtersSchema>;
|
||||
sorting: CommissionRequestsTableSorting;
|
||||
filters: CommissionRequestsTableFilters;
|
||||
}) {
|
||||
const { pagination, sorting, filters } = input;
|
||||
|
||||
const where: any = {};
|
||||
const where: Prisma.CommissionRequestWhereInput = {};
|
||||
|
||||
if (filters.q) {
|
||||
const q = filters.q.trim();
|
||||
@ -60,7 +45,7 @@ export async function getCommissionRequestsTablePage(input: {
|
||||
|
||||
// sorting
|
||||
const sort = sorting?.[0] ?? { id: "createdAt", desc: true };
|
||||
const orderBy: any =
|
||||
const orderBy: Prisma.CommissionRequestOrderByWithRelationInput =
|
||||
sort.id === "createdAt"
|
||||
? { createdAt: sort.desc ? "desc" : "asc" }
|
||||
: sort.id === "status"
|
||||
@ -94,7 +79,7 @@ export async function getCommissionRequestsTablePage(input: {
|
||||
customerName: r.customerName,
|
||||
customerEmail: r.customerEmail,
|
||||
customerSocials: r.customerSocials ?? null,
|
||||
status: r.status as any,
|
||||
status: r.status,
|
||||
fileCount: r._count.files,
|
||||
}));
|
||||
|
||||
|
||||
@ -2,8 +2,9 @@
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { commissionStatusSchema } from "@/schemas/commissions/requests";
|
||||
import { z } from "zod";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
// Sets a commission request status (admin action).
|
||||
export async function setCommissionRequestStatus(input: {
|
||||
id: string;
|
||||
status: z.infer<typeof commissionStatusSchema>;
|
||||
|
||||
@ -1,20 +1,14 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { commissionStatusSchema } from "@/schemas/commissions/requests";
|
||||
import { z } from "zod/v4";
|
||||
import {
|
||||
updateCommissionRequestSchema,
|
||||
} from "@/schemas/commissions/updateRequest";
|
||||
import type { UpdateCommissionRequestInput } from "@/schemas/commissions/updateRequest";
|
||||
|
||||
const updateSchema = z.object({
|
||||
id: z.string().min(1),
|
||||
status: commissionStatusSchema,
|
||||
customerName: z.string().min(1).max(200),
|
||||
customerEmail: z.string().email().max(320),
|
||||
customerSocials: z.string().max(2000).optional().nullable(),
|
||||
message: z.string().min(1).max(20_000),
|
||||
});
|
||||
|
||||
export async function updateCommissionRequest(input: z.infer<typeof updateSchema>) {
|
||||
const data = updateSchema.parse(input);
|
||||
// Updates editable fields on a commission request.
|
||||
export async function updateCommissionRequest(input: UpdateCommissionRequestInput) {
|
||||
const data = updateCommissionRequestSchema.parse(input);
|
||||
|
||||
await prisma.commissionRequest.update({
|
||||
where: { id: data.id },
|
||||
|
||||
@ -1,21 +1,18 @@
|
||||
"use server";
|
||||
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { z } from "zod";
|
||||
|
||||
import { COMMISSION_STATUSES } from "@/lib/commissions/kanban";
|
||||
import { prisma } from "@/lib/prisma"; // adjust to your prisma import
|
||||
// import { requireAdmin } from "@/lib/auth/requireAdmin"; // recommended if you have it
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import {
|
||||
updateCommissionRequestStatusSchema,
|
||||
} from "@/schemas/commissions/updateRequestStatus";
|
||||
import type { UpdateCommissionRequestStatusInput } from "@/schemas/commissions/updateRequestStatus";
|
||||
|
||||
const schema = z.object({
|
||||
id: z.string().min(1),
|
||||
status: z.enum(COMMISSION_STATUSES),
|
||||
});
|
||||
|
||||
export async function updateCommissionRequestStatus(input: z.infer<typeof schema>) {
|
||||
// await requireAdmin(); // enforce auth/role check here
|
||||
|
||||
const { id, status } = schema.parse(input);
|
||||
// Updates a commission request status and revalidates the kanban page.
|
||||
export async function updateCommissionRequestStatus(
|
||||
input: UpdateCommissionRequestStatusInput
|
||||
) {
|
||||
const { id, status } = updateCommissionRequestStatusSchema.parse(input);
|
||||
|
||||
await prisma.commissionRequest.update({
|
||||
where: { id },
|
||||
@ -23,5 +20,5 @@ export async function updateCommissionRequestStatus(input: z.infer<typeof schema
|
||||
});
|
||||
|
||||
// revalidate the board page so a refresh always reflects server truth
|
||||
revalidatePath("/commissions/board");
|
||||
revalidatePath("/commissions/kanban");
|
||||
}
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Deletes a commission type and its link records.
|
||||
export async function deleteCommissionType(typeId: string) {
|
||||
|
||||
await prisma.commissionTypeOption.deleteMany({
|
||||
where: { typeId },
|
||||
})
|
||||
});
|
||||
|
||||
await prisma.commissionTypeExtra.deleteMany({
|
||||
where: { typeId },
|
||||
})
|
||||
});
|
||||
|
||||
await prisma.commissionType.delete({
|
||||
where: { id: typeId },
|
||||
})
|
||||
|
||||
});
|
||||
}
|
||||
@ -4,8 +4,9 @@ import { prisma } from "@/lib/prisma";
|
||||
import { commissionExtraSchema } from "@/schemas/commissionType";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
const LIST_PATH = "/commissions/extras";
|
||||
const LIST_PATH = "/commissions/types/extras";
|
||||
|
||||
// CRUD helpers for commission extras (admin-only pages).
|
||||
export async function createCommissionExtra(input: unknown) {
|
||||
const data = commissionExtraSchema.parse(input);
|
||||
const created = await prisma.commissionExtra.create({ data });
|
||||
@ -24,7 +25,6 @@ export async function deleteCommissionExtra(id: string) {
|
||||
// Optional safety:
|
||||
// const used = await prisma.commissionTypeExtra.count({ where: { extraId: id } });
|
||||
// if (used > 0) throw new Error("Extra is linked to types.");
|
||||
console.log("TBD");
|
||||
// await prisma.commissionExtra.delete({ where: { id } });
|
||||
// revalidatePath(LIST_PATH);
|
||||
await prisma.commissionExtra.delete({ where: { id } });
|
||||
revalidatePath(LIST_PATH);
|
||||
}
|
||||
|
||||
@ -1,54 +1,65 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { commissionTypeSchema } from "@/schemas/commissionType"
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { commissionTypeSchema } from "@/schemas/commissionType";
|
||||
import type * as z from "zod/v4";
|
||||
|
||||
// Creates a commission option entry.
|
||||
export async function createCommissionOption(data: { name: string }) {
|
||||
return await prisma.commissionOption.create({
|
||||
return prisma.commissionOption.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
description: "",
|
||||
},
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// Creates a commission extra entry.
|
||||
export async function createCommissionExtra(data: { name: string }) {
|
||||
return await prisma.commissionExtra.create({
|
||||
return prisma.commissionExtra.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
description: "",
|
||||
},
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// Creates a commission custom input entry.
|
||||
export async function createCommissionCustomInput(data: {
|
||||
name: string
|
||||
fieldId: string
|
||||
name: string;
|
||||
fieldId: string;
|
||||
}) {
|
||||
return await prisma.commissionCustomInput.create({
|
||||
return prisma.commissionCustomInput.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
fieldId: data.fieldId,
|
||||
},
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
export async function createCommissionType(formData: commissionTypeSchema) {
|
||||
const parsed = commissionTypeSchema.safeParse(formData)
|
||||
// Creates a commission type with nested options/extras/custom inputs.
|
||||
export async function createCommissionType(
|
||||
formData: z.infer<typeof commissionTypeSchema>
|
||||
) {
|
||||
const parsed = commissionTypeSchema.safeParse(formData);
|
||||
|
||||
if (!parsed.success) {
|
||||
console.error("Validation failed", parsed.error)
|
||||
throw new Error("Invalid input")
|
||||
console.error("Validation failed", parsed.error);
|
||||
throw new Error("Invalid input");
|
||||
}
|
||||
|
||||
const data = parsed.data
|
||||
const data = parsed.data;
|
||||
|
||||
const created = await prisma.commissionType.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
tags: data.tagIds?.length
|
||||
? { connect: data.tagIds.map((id) => ({ id })) }
|
||||
: undefined,
|
||||
options: {
|
||||
create: data.options?.map((opt, index) => ({
|
||||
create:
|
||||
data.options?.map((opt, index) => ({
|
||||
option: { connect: { id: opt.optionId } },
|
||||
price: opt.price,
|
||||
pricePercent: opt.pricePercent,
|
||||
@ -57,7 +68,8 @@ export async function createCommissionType(formData: commissionTypeSchema) {
|
||||
})) || [],
|
||||
},
|
||||
extras: {
|
||||
create: data.extras?.map((ext, index) => ({
|
||||
create:
|
||||
data.extras?.map((ext, index) => ({
|
||||
extra: { connect: { id: ext.extraId } },
|
||||
price: ext.price,
|
||||
pricePercent: ext.pricePercent,
|
||||
@ -66,7 +78,8 @@ export async function createCommissionType(formData: commissionTypeSchema) {
|
||||
})) || [],
|
||||
},
|
||||
customInputs: {
|
||||
create: data.customInputs?.map((c, index) => ({
|
||||
create:
|
||||
data.customInputs?.map((c, index) => ({
|
||||
customInput: { connect: { id: c.customInputId } },
|
||||
label: c.label,
|
||||
inputType: c.inputType,
|
||||
@ -75,7 +88,7 @@ export async function createCommissionType(formData: commissionTypeSchema) {
|
||||
})) || [],
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
return created
|
||||
return created;
|
||||
}
|
||||
@ -4,13 +4,9 @@ import { prisma } from "@/lib/prisma";
|
||||
import { commissionOptionSchema } from "@/schemas/commissionType";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
const LIST_PATH = "/commissions/options";
|
||||
|
||||
function toInt(v: string) {
|
||||
const n = Number.parseInt(v, 10);
|
||||
return Number.isFinite(n) ? n : 0;
|
||||
}
|
||||
const LIST_PATH = "/commissions/types/options";
|
||||
|
||||
// CRUD helpers for commission options (admin-only pages).
|
||||
export async function createCommissionOption(input: unknown) {
|
||||
const data = commissionOptionSchema.parse(input);
|
||||
const created = await prisma.commissionOption.create({
|
||||
@ -37,7 +33,6 @@ export async function updateCommissionOption(id: string, input: unknown) {
|
||||
}
|
||||
|
||||
export async function deleteCommissionOption(id: string) {
|
||||
console.log("TBD");
|
||||
// await prisma.commissionOption.delete({ where: { id } });
|
||||
// revalidatePath(LIST_PATH);
|
||||
await prisma.commissionOption.delete({ where: { id } });
|
||||
revalidatePath(LIST_PATH);
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Updates sort order for commission types.
|
||||
export async function updateCommissionTypeSortOrder(
|
||||
ordered: { id: string; sortIndex: number }[]
|
||||
) {
|
||||
@ -10,7 +11,7 @@ export async function updateCommissionTypeSortOrder(
|
||||
where: { id },
|
||||
data: { sortIndex },
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
await Promise.all(updates)
|
||||
await Promise.all(updates);
|
||||
}
|
||||
@ -1,20 +1,27 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { commissionTypeSchema } from "@/schemas/commissionType"
|
||||
import * as z from "zod/v4"
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { commissionTypeSchema } from "@/schemas/commissionType";
|
||||
import type * as z from "zod/v4";
|
||||
|
||||
// Updates a commission type and resets related nested records.
|
||||
export async function updateCommissionType(
|
||||
id: string,
|
||||
rawData: z.infer<typeof commissionTypeSchema>
|
||||
) {
|
||||
const data = commissionTypeSchema.parse(rawData)
|
||||
const data = commissionTypeSchema.parse(rawData);
|
||||
|
||||
const updated = await prisma.commissionType.update({
|
||||
where: { id },
|
||||
data: {
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
tags: data.tagIds
|
||||
? {
|
||||
set: [],
|
||||
connect: data.tagIds.map((id) => ({ id })),
|
||||
}
|
||||
: undefined,
|
||||
options: {
|
||||
deleteMany: {},
|
||||
create: data.options?.map((opt, index) => ({
|
||||
@ -37,7 +44,8 @@ export async function updateCommissionType(
|
||||
},
|
||||
customInputs: {
|
||||
deleteMany: {},
|
||||
create: data.customInputs?.map((c, index) => ({
|
||||
create:
|
||||
data.customInputs?.map((c, index) => ({
|
||||
customInput: { connect: { id: c.customInputId } },
|
||||
label: c.label,
|
||||
inputType: c.inputType,
|
||||
@ -51,7 +59,7 @@ export async function updateCommissionType(
|
||||
extras: true,
|
||||
customInputs: true,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
return updated
|
||||
return updated;
|
||||
}
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import type { CountRow } from "@/types/dashboard";
|
||||
|
||||
type CountRow<K extends string> = {
|
||||
[P in K]: string;
|
||||
} & { _count: { _all: number } };
|
||||
|
||||
function toCountMapSafe(rows: any[], key: string) {
|
||||
// Aggregates dashboard stats for admin overview cards and tables.
|
||||
function toCountMapSafe<K extends string>(rows: Array<CountRow<K>>, key: K) {
|
||||
const out: Record<string, number> = {};
|
||||
for (const r of rows) out[String(r[key])] = Number(r?._count?._all ?? 0);
|
||||
return out;
|
||||
|
||||
@ -1,46 +1,48 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { TagFormInput, tagSchema } from "@/schemas/artworks/tagSchema"
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { tagSchema } from "@/schemas/artworks/tagSchema";
|
||||
import type { TagFormInput } from "@/schemas/artworks/tagSchema";
|
||||
|
||||
// Creates a tag and related category links/aliases.
|
||||
export async function createTag(formData: TagFormInput) {
|
||||
const parsed = tagSchema.safeParse(formData)
|
||||
const parsed = tagSchema.safeParse(formData);
|
||||
|
||||
if (!parsed.success) {
|
||||
console.error("Validation failed", parsed.error)
|
||||
throw new Error("Invalid input")
|
||||
console.error("Validation failed", parsed.error);
|
||||
throw new Error("Invalid input");
|
||||
}
|
||||
|
||||
const data = parsed.data
|
||||
const data = parsed.data;
|
||||
|
||||
const parentId = data.parentId ?? null;
|
||||
const tagSlug = data.name.toLowerCase().replace(/\s+/g, "-");
|
||||
|
||||
const created = await prisma.$transaction(async (tx) => {
|
||||
const tag = await tx.artTag.create({
|
||||
const tag = await tx.tag.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
slug: tagSlug,
|
||||
description: data.description,
|
||||
isParent: data.isParent,
|
||||
showOnAnimalPage: data.showOnAnimalPage,
|
||||
parentId
|
||||
isVisible: data.isVisible ?? true,
|
||||
},
|
||||
});
|
||||
|
||||
if (data.categoryIds) {
|
||||
await tx.artTag.update({
|
||||
where: { id: tag.id },
|
||||
data: {
|
||||
categories: {
|
||||
set: data.categoryIds.map(id => ({ id }))
|
||||
}
|
||||
}
|
||||
await tx.tagCategory.createMany({
|
||||
data: data.categoryIds.map((categoryId) => ({
|
||||
tagId: tag.id,
|
||||
categoryId,
|
||||
isParent: data.isParent,
|
||||
showOnAnimalPage: data.showOnAnimalPage,
|
||||
parentTagId: parentId,
|
||||
})),
|
||||
skipDuplicates: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (data.aliases && data.aliases.length > 0) {
|
||||
await tx.artTagAlias.createMany({
|
||||
await tx.tagAlias.createMany({
|
||||
data: data.aliases.map((alias) => ({
|
||||
tagId: tag.id,
|
||||
alias,
|
||||
@ -52,5 +54,5 @@ export async function createTag(formData: TagFormInput) {
|
||||
return tag;
|
||||
});
|
||||
|
||||
return created
|
||||
return created;
|
||||
}
|
||||
@ -3,15 +3,15 @@
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
// Deletes a tag if it has no artwork references or child tags.
|
||||
export async function deleteTag(tagId: string) {
|
||||
const tag = await prisma.artTag.findUnique({
|
||||
const tag = await prisma.tag.findUnique({
|
||||
where: { id: tagId },
|
||||
select: {
|
||||
id: true,
|
||||
_count: {
|
||||
select: {
|
||||
artworks: true,
|
||||
children: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -25,13 +25,18 @@ export async function deleteTag(tagId: string) {
|
||||
throw new Error("Cannot delete tag: it is used by artworks.");
|
||||
}
|
||||
|
||||
if (tag._count.children > 0) {
|
||||
const parentUsage = await prisma.tagCategory.count({
|
||||
where: { parentTagId: tagId },
|
||||
});
|
||||
|
||||
if (parentUsage > 0) {
|
||||
throw new Error("Cannot delete tag: it has child tags.");
|
||||
}
|
||||
|
||||
await prisma.$transaction(async (tx) => {
|
||||
await tx.artTagAlias.deleteMany({ where: { tagId } });
|
||||
await tx.artTag.delete({ where: { id: tagId } });
|
||||
await tx.tagAlias.deleteMany({ where: { tagId } });
|
||||
await tx.tagCategory.deleteMany({ where: { tagId } });
|
||||
await tx.tag.delete({ where: { id: tagId } });
|
||||
});
|
||||
|
||||
revalidatePath("/tags");
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma"
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Returns tags ordered by sortIndex.
|
||||
export async function getTags() {
|
||||
return await prisma.artTag.findMany({ orderBy: { sortIndex: "asc" } })
|
||||
return prisma.tag.findMany({ orderBy: { sortIndex: "asc" } });
|
||||
}
|
||||
@ -1,21 +1,28 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Returns true if possibleAncestorId is a descendant of tagId (cycle check).
|
||||
export async function isDescendant(tagId: string, possibleAncestorId: string): Promise<boolean> {
|
||||
// Walk upwards from possibleAncestorId; if we hit tagId, it's a cycle.
|
||||
let current: string | null = possibleAncestorId;
|
||||
// Walk upwards across any category hierarchy; if we hit tagId, it's a cycle.
|
||||
const visited = new Set<string>();
|
||||
const queue: string[] = [possibleAncestorId];
|
||||
|
||||
while (current) {
|
||||
while (queue.length > 0) {
|
||||
const current = queue.shift();
|
||||
if (!current) continue;
|
||||
if (current === tagId) return true;
|
||||
if (visited.has(current)) continue;
|
||||
visited.add(current);
|
||||
|
||||
const t: { parentId: string | null } | null =
|
||||
await prisma.artTag.findUnique({
|
||||
where: { id: current },
|
||||
select: { parentId: true },
|
||||
const parents = await prisma.tagCategory.findMany({
|
||||
where: { tagId: current, parentTagId: { not: null } },
|
||||
select: { parentTagId: true },
|
||||
});
|
||||
|
||||
current = t?.parentId ?? null;
|
||||
for (const p of parents) {
|
||||
if (p.parentTagId) queue.push(p.parentTagId);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@ -1,18 +1,20 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { prisma } from '@/lib/prisma';
|
||||
import { TagFormInput, tagSchema } from '@/schemas/artworks/tagSchema';
|
||||
import { isDescendant } from './isDescendant';
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { tagSchema } from "@/schemas/artworks/tagSchema";
|
||||
import type { TagFormInput } from "@/schemas/artworks/tagSchema";
|
||||
import { isDescendant } from "./isDescendant";
|
||||
|
||||
// Updates a tag and its category/alias relationships.
|
||||
export async function updateTag(id: string, rawData: TagFormInput) {
|
||||
const parsed = tagSchema.safeParse(rawData)
|
||||
const parsed = tagSchema.safeParse(rawData);
|
||||
|
||||
if (!parsed.success) {
|
||||
console.error("Validation failed", parsed.error)
|
||||
throw new Error("Invalid input")
|
||||
console.error("Validation failed", parsed.error);
|
||||
throw new Error("Invalid input");
|
||||
}
|
||||
|
||||
const data = parsed.data
|
||||
const data = parsed.data;
|
||||
|
||||
const parentId = data.parentId ?? null;
|
||||
const tagSlug = data.name.toLowerCase().replace(/\s+/g, "-");
|
||||
@ -27,22 +29,62 @@ export async function updateTag(id: string, rawData: TagFormInput) {
|
||||
}
|
||||
|
||||
const updated = await prisma.$transaction(async (tx) => {
|
||||
const tag = await tx.artTag.update({
|
||||
const tag = await tx.tag.update({
|
||||
where: { id },
|
||||
data: {
|
||||
name: data.name,
|
||||
slug: tagSlug,
|
||||
description: data.description,
|
||||
isParent: data.isParent,
|
||||
showOnAnimalPage: data.showOnAnimalPage,
|
||||
parentId,
|
||||
categories: data.categoryIds
|
||||
? { set: data.categoryIds.map((cid) => ({ id: cid })) }
|
||||
: undefined,
|
||||
isVisible: data.isVisible ?? true,
|
||||
},
|
||||
});
|
||||
|
||||
const existing = await tx.artTagAlias.findMany({
|
||||
if (data.categoryIds) {
|
||||
const existingLinks = await tx.tagCategory.findMany({
|
||||
where: { tagId: id },
|
||||
select: { id: true, categoryId: true },
|
||||
});
|
||||
|
||||
const desired = new Set(data.categoryIds);
|
||||
const existingSet = new Set(existingLinks.map((l) => l.categoryId));
|
||||
|
||||
const toCreate = data.categoryIds.filter((cid) => !existingSet.has(cid));
|
||||
const toDeleteIds = existingLinks
|
||||
.filter((l) => !desired.has(l.categoryId))
|
||||
.map((l) => l.id);
|
||||
|
||||
if (toDeleteIds.length > 0) {
|
||||
await tx.tagCategory.deleteMany({
|
||||
where: { id: { in: toDeleteIds } },
|
||||
});
|
||||
}
|
||||
|
||||
if (toCreate.length > 0) {
|
||||
await tx.tagCategory.createMany({
|
||||
data: toCreate.map((categoryId) => ({
|
||||
tagId: id,
|
||||
categoryId,
|
||||
isParent: data.isParent,
|
||||
showOnAnimalPage: data.showOnAnimalPage,
|
||||
parentTagId: parentId,
|
||||
})),
|
||||
skipDuplicates: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (existingLinks.length > 0) {
|
||||
await tx.tagCategory.updateMany({
|
||||
where: { tagId: id, categoryId: { in: data.categoryIds } },
|
||||
data: {
|
||||
isParent: data.isParent,
|
||||
showOnAnimalPage: data.showOnAnimalPage,
|
||||
parentTagId: parentId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const existing = await tx.tagAlias.findMany({
|
||||
where: { tagId: id },
|
||||
select: { id: true, alias: true },
|
||||
});
|
||||
@ -56,13 +98,13 @@ export async function updateTag(id: string, rawData: TagFormInput) {
|
||||
.map((a) => a.id);
|
||||
|
||||
if (toDeleteIds.length > 0) {
|
||||
await tx.artTagAlias.deleteMany({
|
||||
await tx.tagAlias.deleteMany({
|
||||
where: { id: { in: toDeleteIds } },
|
||||
});
|
||||
}
|
||||
|
||||
if (toCreate.length > 0) {
|
||||
await tx.artTagAlias.createMany({
|
||||
await tx.tagAlias.createMany({
|
||||
data: toCreate.map((alias) => ({ tagId: id, alias })),
|
||||
skipDuplicates: true,
|
||||
});
|
||||
@ -71,5 +113,5 @@ export async function updateTag(id: string, rawData: TagFormInput) {
|
||||
return tag;
|
||||
});
|
||||
|
||||
return updated
|
||||
return updated;
|
||||
}
|
||||
@ -1,10 +1,11 @@
|
||||
'use server';
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Returns the most recent Terms of Service markdown.
|
||||
export async function getLatestTos(): Promise<string | null> {
|
||||
const tos = await prisma.termsOfService.findFirst({
|
||||
orderBy: { createdAt: 'desc' },
|
||||
orderBy: { createdAt: "desc" },
|
||||
});
|
||||
return tos?.markdown ?? null;
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
'use server';
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Saves a new Terms of Service version.
|
||||
export async function saveTosAction(markdown: string) {
|
||||
await prisma.termsOfService.create({
|
||||
data: {
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
"use server";
|
||||
|
||||
import { createImageFromFile } from "./createImageFromFile";
|
||||
import type { BulkResult } from "@/types/uploads";
|
||||
|
||||
type BulkResult =
|
||||
| { ok: true; artworkId: string; name: string }
|
||||
| { ok: false; name: string; error: string };
|
||||
|
||||
// Bulk image upload server action used by the admin UI.
|
||||
export async function createImagesBulk(formData: FormData): Promise<BulkResult[]> {
|
||||
const entries = formData.getAll("file");
|
||||
const files = entries.filter((x): x is File => x instanceof File);
|
||||
|
||||
@ -1,203 +1,12 @@
|
||||
"use server"
|
||||
"use server";
|
||||
|
||||
import { fileUploadSchema } from "@/schemas/artworks/imageSchema";
|
||||
import type { fileUploadSchema } from "@/schemas/artworks/imageSchema";
|
||||
import "dotenv/config";
|
||||
import { z } from "zod/v4";
|
||||
import type { z } from "zod/v4";
|
||||
import { createImageFromFile } from "./createImageFromFile";
|
||||
|
||||
// Creates a single artwork image using the shared upload pipeline.
|
||||
export async function createImage(values: z.infer<typeof fileUploadSchema>) {
|
||||
const imageFile = values.file[0];
|
||||
return createImageFromFile(imageFile, { colorMode: "inline" });
|
||||
}
|
||||
|
||||
/*
|
||||
export async function createImage(values: z.infer<typeof fileUploadSchema>) {
|
||||
const imageFile = values.file[0];
|
||||
|
||||
if (!(imageFile instanceof File)) {
|
||||
console.log("No image or invalid type");
|
||||
return null;
|
||||
}
|
||||
|
||||
const fileName = imageFile.name;
|
||||
const fileType = imageFile.type;
|
||||
const fileSize = imageFile.size;
|
||||
const lastModified = new Date(imageFile.lastModified);
|
||||
|
||||
const fileKey = uuidv4();
|
||||
|
||||
const arrayBuffer = await imageFile.arrayBuffer();
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
|
||||
const realFileType = fileType.split("/")[1];
|
||||
const originalKey = `original/${fileKey}.${realFileType}`;
|
||||
const modifiedKey = `modified/${fileKey}.webp`;
|
||||
const resizedKey = `resized/${fileKey}.webp`;
|
||||
const thumbnailKey = `thumbnail/${fileKey}.webp`;
|
||||
|
||||
const sharpData = sharp(buffer);
|
||||
const metadata = await sharpData.metadata();
|
||||
|
||||
//--- Original file
|
||||
await s3.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: `${process.env.BUCKET_NAME}`,
|
||||
Key: originalKey,
|
||||
Body: buffer,
|
||||
ContentType: "image/" + metadata.format,
|
||||
})
|
||||
);
|
||||
//--- Modified file
|
||||
const modifiedBuffer = await sharp(buffer)
|
||||
.toFormat('webp')
|
||||
.toBuffer()
|
||||
const modifiedMetadata = await sharp(modifiedBuffer).metadata();
|
||||
await s3.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: `${process.env.BUCKET_NAME}`,
|
||||
Key: modifiedKey,
|
||||
Body: modifiedBuffer,
|
||||
ContentType: "image/" + modifiedMetadata.format,
|
||||
})
|
||||
);
|
||||
//--- Resized file
|
||||
const { width, height } = modifiedMetadata;
|
||||
const targetSize = 400;
|
||||
let resizeOptions;
|
||||
if (width && height) {
|
||||
if (height < width) {
|
||||
resizeOptions = { height: targetSize };
|
||||
} else {
|
||||
resizeOptions = { width: targetSize };
|
||||
}
|
||||
} else {
|
||||
resizeOptions = { height: targetSize };
|
||||
}
|
||||
const resizedBuffer = await sharp(modifiedBuffer)
|
||||
.resize({ ...resizeOptions, withoutEnlargement: true })
|
||||
.toFormat('webp')
|
||||
.toBuffer();
|
||||
const resizedMetadata = await sharp(resizedBuffer).metadata();
|
||||
await s3.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: `${process.env.BUCKET_NAME}`,
|
||||
Key: resizedKey,
|
||||
Body: resizedBuffer,
|
||||
ContentType: "image/" + resizedMetadata.format,
|
||||
})
|
||||
);
|
||||
//--- Thumbnail file
|
||||
const thumbnailTargetSize = 160;
|
||||
let thumbnailOptions;
|
||||
if (width && height) {
|
||||
if (height < width) {
|
||||
thumbnailOptions = { height: thumbnailTargetSize };
|
||||
} else {
|
||||
thumbnailOptions = { width: thumbnailTargetSize };
|
||||
}
|
||||
} else {
|
||||
thumbnailOptions = { height: thumbnailTargetSize };
|
||||
}
|
||||
const thumbnailBuffer = await sharp(modifiedBuffer)
|
||||
.resize({ ...thumbnailOptions, withoutEnlargement: true })
|
||||
.toFormat('webp')
|
||||
.toBuffer();
|
||||
const thumbnailMetadata = await sharp(thumbnailBuffer).metadata();
|
||||
await s3.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: `${process.env.BUCKET_NAME}`,
|
||||
Key: thumbnailKey,
|
||||
Body: thumbnailBuffer,
|
||||
ContentType: "image/" + thumbnailMetadata.format,
|
||||
})
|
||||
);
|
||||
|
||||
const fileRecord = await prisma.fileData.create({
|
||||
data: {
|
||||
name: fileName,
|
||||
fileKey,
|
||||
originalFile: fileName,
|
||||
uploadDate: lastModified,
|
||||
fileType: realFileType,
|
||||
fileSize: fileSize,
|
||||
},
|
||||
});
|
||||
|
||||
const artworkSlug = fileName.toLowerCase().replace(/\s+/g, "-");
|
||||
const artworkRecord = await prisma.artwork.create({
|
||||
data: {
|
||||
name: fileName,
|
||||
slug: artworkSlug,
|
||||
creationDate: lastModified,
|
||||
fileId: fileRecord.id,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.artworkMetadata.create({
|
||||
data: {
|
||||
artworkId: artworkRecord.id,
|
||||
format: metadata.format || "unknown",
|
||||
width: metadata.width || 0,
|
||||
height: metadata.height || 0,
|
||||
space: metadata.space || "unknown",
|
||||
channels: metadata.channels || 0,
|
||||
depth: metadata.depth || "unknown",
|
||||
density: metadata.density ?? undefined,
|
||||
bitsPerSample: metadata.bitsPerSample ?? undefined,
|
||||
isProgressive: metadata.isProgressive ?? undefined,
|
||||
isPalette: metadata.isPalette ?? undefined,
|
||||
hasProfile: metadata.hasProfile ?? undefined,
|
||||
hasAlpha: metadata.hasAlpha ?? undefined,
|
||||
autoOrientW: metadata.autoOrient?.width ?? undefined,
|
||||
autoOrientH: metadata.autoOrient?.height ?? undefined,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.fileVariant.createMany({
|
||||
data: [
|
||||
{
|
||||
s3Key: originalKey,
|
||||
type: "original",
|
||||
height: metadata.height,
|
||||
width: metadata.width,
|
||||
fileExtension: metadata.format,
|
||||
mimeType: "image/" + metadata.format,
|
||||
sizeBytes: metadata.size,
|
||||
artworkId: artworkRecord.id
|
||||
},
|
||||
{
|
||||
s3Key: modifiedKey,
|
||||
type: "modified",
|
||||
height: modifiedMetadata.height,
|
||||
width: modifiedMetadata.width,
|
||||
fileExtension: modifiedMetadata.format,
|
||||
mimeType: "image/" + modifiedMetadata.format,
|
||||
sizeBytes: modifiedMetadata.size,
|
||||
artworkId: artworkRecord.id
|
||||
},
|
||||
{
|
||||
s3Key: resizedKey,
|
||||
type: "resized",
|
||||
height: resizedMetadata.height,
|
||||
width: resizedMetadata.width,
|
||||
fileExtension: resizedMetadata.format,
|
||||
mimeType: "image/" + resizedMetadata.format,
|
||||
sizeBytes: resizedMetadata.size,
|
||||
artworkId: artworkRecord.id
|
||||
},
|
||||
{
|
||||
s3Key: thumbnailKey,
|
||||
type: "thumbnail",
|
||||
height: thumbnailMetadata.height,
|
||||
width: thumbnailMetadata.width,
|
||||
fileExtension: thumbnailMetadata.format,
|
||||
mimeType: "image/" + thumbnailMetadata.format,
|
||||
sizeBytes: thumbnailMetadata.size,
|
||||
artworkId: artworkRecord.id
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
return artworkRecord
|
||||
}
|
||||
*/
|
||||
@ -8,12 +8,12 @@ import sharp from "sharp";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { generateArtworkColorsForArtwork } from "../artworks/generateArtworkColors";
|
||||
|
||||
// Upload pipeline that generates variants and metadata, then creates artwork records.
|
||||
export async function createImageFromFile(
|
||||
imageFile: File,
|
||||
opts?: { originalName?: string; colorMode?: "inline" | "defer" | "off" },
|
||||
) {
|
||||
if (!(imageFile instanceof File)) {
|
||||
console.log("No image or invalid type");
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ export async function createImageFromFile(
|
||||
name: fileName,
|
||||
fileKey,
|
||||
originalFile: fileName,
|
||||
uploadDate: lastModified,
|
||||
uploadDate: new Date(),
|
||||
fileType: realFileType,
|
||||
fileSize,
|
||||
},
|
||||
|
||||
@ -2,24 +2,20 @@
|
||||
|
||||
import { auth } from "@/lib/auth";
|
||||
import { headers } from "next/headers";
|
||||
import { z } from "zod/v4";
|
||||
import type { SessionWithRole } from "@/types/auth";
|
||||
import { createUserSchema } from "@/schemas/users";
|
||||
import type { CreateUserInput } from "@/schemas/users";
|
||||
|
||||
const schema = z.object({
|
||||
name: z.string().min(1).max(200),
|
||||
email: z.string().email().max(320),
|
||||
password: z.string().min(8).max(128),
|
||||
role: z.enum(["user", "admin"]).default("user"),
|
||||
});
|
||||
|
||||
export async function createUser(input: z.infer<typeof schema>) {
|
||||
// Creates a new user account (admin-only).
|
||||
export async function createUser(input: CreateUserInput) {
|
||||
const session = await auth.api.getSession({ headers: await headers() });
|
||||
const role = (session as any)?.user?.role;
|
||||
const role = (session as SessionWithRole)?.user?.role;
|
||||
|
||||
if (!session || role !== "admin") {
|
||||
throw new Error("Forbidden");
|
||||
}
|
||||
|
||||
const data = schema.parse(input);
|
||||
const data = createUserSchema.parse(input);
|
||||
|
||||
return auth.api.createUser({
|
||||
body: {
|
||||
|
||||
@ -4,13 +4,15 @@ import { auth } from "@/lib/auth";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { headers } from "next/headers";
|
||||
import { z } from "zod/v4";
|
||||
import type { SessionWithRole } from "@/types/auth";
|
||||
|
||||
// Deletes a user account with safety checks (admin-only, cannot delete self or last admin).
|
||||
export async function deleteUser(id: string) {
|
||||
const userId = z.string().min(1).parse(id);
|
||||
|
||||
const session = await auth.api.getSession({ headers: await headers() });
|
||||
const role = (session as any)?.user?.role as string | undefined;
|
||||
const currentUserId = (session as any)?.user?.id as string | undefined;
|
||||
const role = (session as SessionWithRole)?.user?.role;
|
||||
const currentUserId = (session as SessionWithRole)?.user?.id;
|
||||
|
||||
if (!session || role !== "admin") throw new Error("Forbidden");
|
||||
if (!currentUserId) throw new Error("Session missing user id");
|
||||
@ -40,5 +42,5 @@ async function await_attachTarget(userId: string) {
|
||||
select: { id: true, role: true },
|
||||
});
|
||||
if (!target) throw new Error("User not found.");
|
||||
return target as { id: string; role: "admin" | "user" };
|
||||
return target;
|
||||
}
|
||||
|
||||
@ -2,21 +2,14 @@
|
||||
|
||||
import { auth } from "@/lib/auth";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import type { SessionWithRole } from "@/types/auth";
|
||||
import type { UserRole, UsersListRow } from "@/types/users";
|
||||
import { headers } from "next/headers";
|
||||
|
||||
export type UsersListRow = {
|
||||
id: string;
|
||||
name: string | null;
|
||||
email: string;
|
||||
role: "admin" | "user";
|
||||
emailVerified: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
};
|
||||
|
||||
// Returns all users for the admin users table.
|
||||
export async function getUsers(): Promise<UsersListRow[]> {
|
||||
const session = await auth.api.getSession({ headers: await headers() });
|
||||
const role = (session as any)?.user?.role as string | undefined;
|
||||
const role = (session as SessionWithRole)?.user?.role;
|
||||
|
||||
if (!session || role !== "admin") {
|
||||
throw new Error("Forbidden");
|
||||
@ -35,5 +28,16 @@ export async function getUsers(): Promise<UsersListRow[]> {
|
||||
},
|
||||
});
|
||||
|
||||
return rows as UsersListRow[];
|
||||
return rows.map((r) => {
|
||||
if (r.role !== "admin" && r.role !== "user") {
|
||||
throw new Error(`Unexpected user role: ${r.role}`);
|
||||
}
|
||||
|
||||
return {
|
||||
...r,
|
||||
role: r.role as UserRole,
|
||||
createdAt: r.createdAt.toISOString(),
|
||||
updatedAt: r.updatedAt.toISOString(),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@ -2,21 +2,20 @@
|
||||
|
||||
import { auth } from "@/lib/auth";
|
||||
import { headers } from "next/headers";
|
||||
import { z } from "zod/v4";
|
||||
import type { SessionWithRole } from "@/types/auth";
|
||||
import { resendVerificationSchema } from "@/schemas/users";
|
||||
import type { ResendVerificationInput } from "@/schemas/users";
|
||||
|
||||
const schema = z.object({
|
||||
email: z.string().email(),
|
||||
});
|
||||
|
||||
export async function resendVerification(input: z.infer<typeof schema>) {
|
||||
// Resends a verification email for a user (admin-only).
|
||||
export async function resendVerification(input: ResendVerificationInput) {
|
||||
const session = await auth.api.getSession({ headers: await headers() });
|
||||
const role = (session as any)?.user?.role as string | undefined;
|
||||
const role = (session as SessionWithRole)?.user?.role;
|
||||
if (!session || role !== "admin") throw new Error("Forbidden");
|
||||
|
||||
const { email } = schema.parse(input);
|
||||
const { email } = resendVerificationSchema.parse(input);
|
||||
|
||||
// Uses the public auth route (same origin)
|
||||
const res = await fetch("http://localhost/api/auth/send-verification-email", {
|
||||
const res = await fetch(`${process.env.BETTER_AUTH_URL}/api/auth/send-verification-email`, {
|
||||
// NOTE: In production, you should use an absolute URL from env, or use authClient.
|
||||
// This is kept minimal; if you want, I'll refactor to authClient to avoid hostname concerns.
|
||||
method: "POST",
|
||||
|
||||
@ -8,6 +8,7 @@ import ArtworkVariants from "@/components/artworks/single/ArtworkVariants";
|
||||
import DeleteArtworkButton from "@/components/artworks/single/DeleteArtworkButton";
|
||||
import EditArtworkForm from "@/components/artworks/single/EditArtworkForm";
|
||||
|
||||
// Single artwork edit page.
|
||||
export default async function ArtworkSinglePage({ params }: { params: Promise<{ id: string }> }) {
|
||||
const { id } = await params;
|
||||
|
||||
@ -16,30 +17,30 @@ export default async function ArtworkSinglePage({ params }: { params: Promise<{
|
||||
const categories = await getCategoriesWithTags();
|
||||
const tags = await getTags();
|
||||
|
||||
if (!item) return <div>Artwork with this id not found</div>
|
||||
if (!item) return <div>Artwork with this id not found</div>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-4">Edit artwork</h1>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
<div className="space-y-6">
|
||||
<EditArtworkForm artwork={item} tags={tags} categories={categories} />
|
||||
<div>
|
||||
{item ? <EditArtworkForm artwork={item} tags={tags} categories={categories} /> : 'Artwork not found...'}
|
||||
<div className="mt-6">
|
||||
{item && <DeleteArtworkButton artworkId={item.id} />}
|
||||
<DeleteArtworkButton artworkId={item.id} />
|
||||
</div>
|
||||
<div>
|
||||
{item && <ArtworkVariants artworkId={item.id} variants={item.variants} />}
|
||||
<ArtworkTimelapse artworkId={item.id} timelapse={item.timelapse} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
{item && <ArtworkTimelapse artworkId={item.id} timelapse={item.timelapse} />}
|
||||
<ArtworkColors colors={item.colors} artworkId={item.id} />
|
||||
</div>
|
||||
<div>
|
||||
{item && <ArtworkColors colors={item.colors} artworkId={item.id} />}
|
||||
<ArtworkDetails artwork={item} />
|
||||
</div>
|
||||
<div>
|
||||
{item && <ArtworkDetails artwork={item} />}
|
||||
<ArtworkVariants artworkId={item.id} variants={item.variants} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,94 +1,13 @@
|
||||
import { ArtworkColorProcessor } from "@/components/artworks/ArtworkColorProcessor";
|
||||
import { ArtworkGalleryVariantProcessor } from "@/components/artworks/ArtworkGalleryVariantProcessor";
|
||||
import { ArtworksTable } from "@/components/artworks/ArtworksTable";
|
||||
import { getArtworksPage } from "@/lib/queryArtworks";
|
||||
|
||||
export default async function ArtworksPage({
|
||||
searchParams
|
||||
}: {
|
||||
searchParams?: {
|
||||
// type?: string;
|
||||
published?: string;
|
||||
// groupBy?: string;
|
||||
// year?: string;
|
||||
// album?: string;
|
||||
cursor?: string;
|
||||
}
|
||||
}) {
|
||||
const {
|
||||
// type = "all",
|
||||
published = "all",
|
||||
// groupBy = "year",
|
||||
// year,
|
||||
// album,
|
||||
cursor = undefined
|
||||
} = await searchParams ?? {};
|
||||
// const groupMode = groupBy === "album" ? "album" : "year";
|
||||
// const groupId = groupMode === "album" ? album ?? "all" : year ?? "all";
|
||||
|
||||
// Filter by type
|
||||
// if (type !== "all") {
|
||||
// where.typeId = type === "none" ? null : type;
|
||||
// }
|
||||
|
||||
// Filter by published status
|
||||
// if (published === "published") {
|
||||
// where.published = true;
|
||||
// } else if (published === "unpublished") {
|
||||
// where.published = false;
|
||||
// } else if (published === "needsWork") {
|
||||
// where.needsWork = true;
|
||||
// }
|
||||
|
||||
// Filter by group (year or album)
|
||||
// if (groupMode === "year" && groupId !== "all") {
|
||||
// where.year = parseInt(groupId);
|
||||
// } else if (groupMode === "album" && groupId !== "all") {
|
||||
// where.albumId = groupId;
|
||||
// }
|
||||
|
||||
const { items, nextCursor } = await getArtworksPage(
|
||||
{
|
||||
published,
|
||||
cursor,
|
||||
take: 48
|
||||
}
|
||||
)
|
||||
|
||||
// Admin artworks list page.
|
||||
export default async function ArtworksPage() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<h1 className="text-2xl font-bold">Artworks</h1>
|
||||
{/* <ProcessArtworkColorsButton /> */}
|
||||
<ArtworkColorProcessor />
|
||||
<ArtworkGalleryVariantProcessor />
|
||||
<ArtworksTable />
|
||||
</div>
|
||||
// <div>
|
||||
// <div className="flex justify-between pb-4 items-end">
|
||||
// <h1 className="text-2xl font-bold mb-4">Artworks</h1>
|
||||
// <Link href="/uploads/single" className="flex gap-2 items-center cursor-pointer bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded">
|
||||
// <PlusCircleIcon className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all text-primary-foreground" /> Upload new artwork
|
||||
// </Link>
|
||||
// <Link href="/uploads/bulk" className="flex gap-2 items-center cursor-pointer bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded">
|
||||
// <PlusCircleIcon className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all text-primary-foreground" /> Upload many artwork
|
||||
// </Link>
|
||||
// </div>
|
||||
// <FilterBar
|
||||
// // types={types}
|
||||
// // albums={albums}
|
||||
// // years={years}
|
||||
// // currentType={type}
|
||||
// currentPublished={published}
|
||||
// // groupBy={groupMode}
|
||||
// // groupId={groupId}
|
||||
// />
|
||||
// <div className="mt-6">
|
||||
// {items.length > 0 ? (
|
||||
// <ArtworkGallery initialArtworks={items} initialCursor={nextCursor} />
|
||||
// ) : (
|
||||
// <p className="text-muted-foreground italic">No artworks found.</p>
|
||||
// )}
|
||||
// </div>
|
||||
// </div >
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import EditCategoryForm from "@/components/categories/EditCategoryForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Edit category page.
|
||||
export default async function PortfolioCategoriesEditPage({ params }: { params: { id: string } }) {
|
||||
const { id } = await params;
|
||||
const category = await prisma.artCategory.findUnique({
|
||||
where: {
|
||||
id,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import NewCategoryForm from "@/components/categories/NewCategoryForm";
|
||||
|
||||
// Create a new category page.
|
||||
export default function PortfolioCategoriesNewPage() {
|
||||
return (
|
||||
<div>
|
||||
|
||||
@ -4,6 +4,7 @@ import { PlusCircleIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { Suspense } from "react";
|
||||
|
||||
// Admin categories management page.
|
||||
export default async function CategoriesPage() {
|
||||
const items = await getCategoriesWithCount();
|
||||
|
||||
@ -11,7 +12,10 @@ export default async function CategoriesPage() {
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">Art Categories</h1>
|
||||
<Link href="/categories/new" className="flex gap-2 items-center cursor-pointer bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded">
|
||||
<Link
|
||||
href="/categories/new"
|
||||
className="flex gap-2 items-center cursor-pointer bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded"
|
||||
>
|
||||
<PlusCircleIcon className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all text-primary-foreground" /> Add new category
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
44
src/app/(admin)/commissions/custom-cards/[id]/page.tsx
Normal file
44
src/app/(admin)/commissions/custom-cards/[id]/page.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
import EditCustomCardForm from "@/components/commissions/customCards/EditCustomCardForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
// Edit custom commission card page.
|
||||
export default async function CommissionCustomCardEditPage({
|
||||
params,
|
||||
}: {
|
||||
params: { id: string };
|
||||
}) {
|
||||
const { id } = await params;
|
||||
|
||||
const [card, options, extras, tags] = await Promise.all([
|
||||
prisma.commissionCustomCard.findUnique({
|
||||
where: { id },
|
||||
include: {
|
||||
options: { orderBy: { sortIndex: "asc" } },
|
||||
extras: { orderBy: { sortIndex: "asc" } },
|
||||
tags: true,
|
||||
},
|
||||
}),
|
||||
prisma.commissionOption.findMany({ orderBy: [{ sortIndex: "asc" }, { name: "asc" }] }),
|
||||
prisma.commissionExtra.findMany({ orderBy: [{ sortIndex: "asc" }, { name: "asc" }] }),
|
||||
prisma.tag.findMany({ orderBy: [{ sortIndex: "asc" }, { name: "asc" }] }),
|
||||
]);
|
||||
|
||||
if (!card) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">Edit Custom Commission Card</h1>
|
||||
</div>
|
||||
<EditCustomCardForm
|
||||
card={card}
|
||||
allOptions={options}
|
||||
allExtras={extras}
|
||||
allTags={tags}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
20
src/app/(admin)/commissions/custom-cards/new/page.tsx
Normal file
20
src/app/(admin)/commissions/custom-cards/new/page.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import NewCustomCardForm from "@/components/commissions/customCards/NewCustomCardForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// New custom commission card page.
|
||||
export default async function CommissionCustomCardsNewPage() {
|
||||
const [options, extras, tags] = await Promise.all([
|
||||
prisma.commissionOption.findMany({ orderBy: [{ sortIndex: "asc" }, { name: "asc" }] }),
|
||||
prisma.commissionExtra.findMany({ orderBy: [{ sortIndex: "asc" }, { name: "asc" }] }),
|
||||
prisma.tag.findMany({ orderBy: [{ sortIndex: "asc" }, { name: "asc" }] }),
|
||||
]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">New Custom Commission Card</h1>
|
||||
</div>
|
||||
<NewCustomCardForm options={options} extras={extras} tags={tags} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
35
src/app/(admin)/commissions/custom-cards/page.tsx
Normal file
35
src/app/(admin)/commissions/custom-cards/page.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import ListCustomCards from "@/components/commissions/customCards/ListCustomCards";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { PlusCircleIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
// Custom commission cards list page.
|
||||
export default async function CommissionCustomCardsPage() {
|
||||
const cards = await prisma.commissionCustomCard.findMany({
|
||||
include: {
|
||||
options: { include: { option: true }, orderBy: { sortIndex: "asc" } },
|
||||
extras: { include: { extra: true }, orderBy: { sortIndex: "asc" } },
|
||||
},
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">Custom Commission Cards</h1>
|
||||
<Link
|
||||
href="/commissions/custom-cards/new"
|
||||
className="flex gap-2 items-center cursor-pointer bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded"
|
||||
>
|
||||
<PlusCircleIcon className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all text-primary-foreground" />
|
||||
Add new Card
|
||||
</Link>
|
||||
</div>
|
||||
{cards && cards.length > 0 ? (
|
||||
<ListCustomCards cards={cards} />
|
||||
) : (
|
||||
<p className="text-muted-foreground italic">No custom cards found.</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -2,6 +2,7 @@ import { listCommissionExamples } from "@/actions/commissions/examples";
|
||||
import { getActiveGuidelines } from "@/actions/commissions/guidelines/getGuidelines";
|
||||
import GuidelinesEditor from "@/components/commissions/guidelines/Editor";
|
||||
|
||||
// Admin page for editing commission guidelines.
|
||||
export default async function CommissionGuidelinesPage() {
|
||||
const [{ markdown, exampleImageUrl }, examples] = await Promise.all([
|
||||
getActiveGuidelines(),
|
||||
|
||||
@ -4,6 +4,7 @@ import { prisma } from "@/lib/prisma";
|
||||
|
||||
import type { BoardItem, ColumnsState } from "@/types/Board";
|
||||
|
||||
// Admin kanban page for commission requests.
|
||||
export default async function CommissionsBoardPage() {
|
||||
const requests = await prisma.commissionRequest.findMany({
|
||||
where: {
|
||||
|
||||
@ -2,6 +2,7 @@ import { getCommissionRequestById } from "@/actions/commissions/requests/getComm
|
||||
import { CommissionRequestEditor } from "@/components/commissions/requests/CommissionRequestEditor";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
// Admin page for editing a single commission request.
|
||||
export default async function CommissionRequestPage({
|
||||
params,
|
||||
}: {
|
||||
@ -20,7 +21,7 @@ export default async function CommissionRequestPage({
|
||||
Submitted: {new Date(request.createdAt).toLocaleString()} · ID: {request.id}
|
||||
</p>
|
||||
</div>
|
||||
<CommissionRequestEditor request={request as any} />
|
||||
<CommissionRequestEditor request={request} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import RequestsTable from "@/components/commissions/requests/RequestsTable";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Server-rendered commissions list page.
|
||||
export default async function CommissionPage() {
|
||||
const items = await prisma.commissionRequest.findMany({
|
||||
include: {
|
||||
@ -15,7 +16,7 @@ export default async function CommissionPage() {
|
||||
<div>
|
||||
<h1 className="text-2xl font-semibold">Commission Requests</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
List of all incomming requests via website.
|
||||
List of all incoming requests via website.
|
||||
</p>
|
||||
</div>
|
||||
<RequestsTable requests={items} />
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import EditTypeForm from "@/components/commissions/types/EditTypeForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Edit commission type page.
|
||||
export default async function CommissionTypesEditPage({ params }: { params: { id: string } }) {
|
||||
const { id } = await params;
|
||||
const commissionType = await prisma.commissionType.findUnique({
|
||||
@ -11,20 +12,21 @@ export default async function CommissionTypesEditPage({ params }: { params: { id
|
||||
options: { include: { option: true }, orderBy: { sortIndex: "asc" } },
|
||||
extras: { include: { extra: true }, orderBy: { sortIndex: "asc" } },
|
||||
customInputs: { include: { customInput: true }, orderBy: { sortIndex: "asc" } },
|
||||
tags: true,
|
||||
},
|
||||
})
|
||||
});
|
||||
const tags = await prisma.tag.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
});
|
||||
const options = await prisma.commissionOption.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
});
|
||||
const extras = await prisma.commissionExtra.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
})
|
||||
// const customInputs = await prisma.commissionCustomInput.findMany({
|
||||
// orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
// })
|
||||
});
|
||||
|
||||
if (!commissionType) {
|
||||
return <div>Type not found</div>
|
||||
return <div>Type not found</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -32,7 +34,12 @@ export default async function CommissionTypesEditPage({ params }: { params: { id
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">Edit Commission Type</h1>
|
||||
</div>
|
||||
<EditTypeForm type={commissionType} allOptions={options} allExtras={extras} />
|
||||
<EditTypeForm
|
||||
type={commissionType}
|
||||
allOptions={options}
|
||||
allExtras={extras}
|
||||
allTags={tags}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
import { ExtraListClient } from "@/components/commissions/extras/ExtraListClient";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Admin page for managing commission extras.
|
||||
export default async function CommissionTypesExtrasPage() {
|
||||
const extras = await prisma.commissionExtra.findMany({
|
||||
orderBy: [{ createdAt: "asc" }, { name: "asc" }],
|
||||
|
||||
@ -1,24 +1,32 @@
|
||||
import NewTypeForm from "@/components/commissions/types/NewTypeForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Create new commission type page.
|
||||
export default async function CommissionTypesNewPage() {
|
||||
const tags = await prisma.tag.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
});
|
||||
const options = await prisma.commissionOption.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
});
|
||||
const extras = await prisma.commissionExtra.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
})
|
||||
});
|
||||
const customInputs = await prisma.commissionCustomInput.findMany({
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
})
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">New Commission Type</h1>
|
||||
</div>
|
||||
<NewTypeForm options={options} extras={extras} customInputs={customInputs} />
|
||||
<NewTypeForm
|
||||
options={options}
|
||||
extras={extras}
|
||||
customInputs={customInputs}
|
||||
tags={tags}
|
||||
/>
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
import { OptionsListClient } from "@/components/commissions/options/OptionsListClient";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Admin page for managing commission options.
|
||||
export default async function CommissionTypesOptionsPage() {
|
||||
const options = await prisma.commissionOption.findMany({
|
||||
orderBy: [{ createdAt: "asc" }, { name: "asc" }],
|
||||
|
||||
@ -3,6 +3,7 @@ import { prisma } from "@/lib/prisma";
|
||||
import { PlusCircleIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
// Commission types list page.
|
||||
export default async function CommissionTypesPage() {
|
||||
const types = await prisma.commissionType.findMany({
|
||||
include: {
|
||||
@ -17,11 +18,18 @@ export default async function CommissionTypesPage() {
|
||||
<div>
|
||||
<div className="flex gap-4 justify-between pb-8">
|
||||
<h1 className="text-2xl font-bold mb-4">Commission Types</h1>
|
||||
<Link href="/commissions/types/new" className="flex gap-2 items-center cursor-pointer bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded">
|
||||
<Link
|
||||
href="/commissions/types/new"
|
||||
className="flex gap-2 items-center cursor-pointer bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded"
|
||||
>
|
||||
<PlusCircleIcon className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all text-primary-foreground" /> Add new Type
|
||||
</Link>
|
||||
</div>
|
||||
{types && types.length > 0 ? <ListTypes types={types} /> : <p className="text-muted-foreground italic">No types found.</p>}
|
||||
{types && types.length > 0 ? (
|
||||
<ListTypes types={types} />
|
||||
) : (
|
||||
<p className="text-muted-foreground italic">No types found.</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -3,25 +3,15 @@ import Footer from "@/components/global/Footer";
|
||||
import MobileSidebar from "@/components/global/MobileSidebar";
|
||||
import ModeToggle from "@/components/global/ModeToggle";
|
||||
import Sidebar from "@/components/global/Sidebar";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
// Main admin layout with sidebar, header actions, and footer.
|
||||
export default function AdminLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
children: ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
// <div className="flex flex-col min-h-screen min-w-screen">
|
||||
// <header className="sticky top-0 z-50 h-14 w-full border-b bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60 px-4 py-2">
|
||||
// <Header />
|
||||
// </header>
|
||||
// <main className="container mx-auto px-4 py-8">
|
||||
// {children}
|
||||
// </main>
|
||||
// <footer className="mt-auto px-4 py-2 h-14 border-t bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60">
|
||||
// <Footer />
|
||||
// </footer>
|
||||
// <Toaster />
|
||||
// </div>
|
||||
<div className="min-h-screen w-full">
|
||||
<div className="flex min-h-screen w-full">
|
||||
<aside className="hidden md:flex md:w-64 md:flex-col md:border-r md:bg-background">
|
||||
|
||||
@ -6,14 +6,7 @@ import { StatusPill } from "@/components/home/StatusPill";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
|
||||
function fmtDate(d: Date) {
|
||||
return new Intl.DateTimeFormat("de-DE", {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
}).format(d);
|
||||
}
|
||||
|
||||
// Admin dashboard summary page.
|
||||
export default async function HomePage() {
|
||||
const data = await getAdminDashboard();
|
||||
|
||||
@ -28,9 +21,6 @@ export default async function HomePage() {
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{/* <Button asChild variant="secondary">
|
||||
<Link href="/artworks/new">Add artwork</Link>
|
||||
</Button> */}
|
||||
<Button asChild>
|
||||
<Link href="/commissions/requests">Review requests</Link>
|
||||
</Button>
|
||||
@ -80,48 +70,6 @@ export default async function HomePage() {
|
||||
</section>
|
||||
|
||||
<section className="grid gap-4 lg:grid-cols-3">
|
||||
{/* Artwork status */}
|
||||
{/* <Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base">Artwork status</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2">
|
||||
<StatusPill label="Published" value={data.artworks.published} />
|
||||
<StatusPill label="Unpublished" value={data.artworks.unpublished} />
|
||||
<StatusPill label="NSFW" value={data.artworks.nsfw} />
|
||||
<StatusPill label="Set as header" value={data.artworks.header} />
|
||||
</CardContent>
|
||||
</Card> */}
|
||||
|
||||
{/* Color pipeline */}
|
||||
{/* <Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base">Color pipeline</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2">
|
||||
<StatusPill
|
||||
label="Pending"
|
||||
value={data.artworks.colorStatus.PENDING}
|
||||
/>
|
||||
<StatusPill
|
||||
label="Processing"
|
||||
value={data.artworks.colorStatus.PROCESSING}
|
||||
/>
|
||||
<StatusPill
|
||||
label="Ready"
|
||||
value={data.artworks.colorStatus.READY}
|
||||
/>
|
||||
<StatusPill
|
||||
label="Failed"
|
||||
value={data.artworks.colorStatus.FAILED}
|
||||
/>
|
||||
<div className="pt-2 text-sm text-muted-foreground">
|
||||
Tip: keep “Failed” near zero—those typically need a re-run or file
|
||||
fix.
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card> */}
|
||||
|
||||
{/* Commissions status */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
@ -153,84 +101,6 @@ export default async function HomePage() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
</section>
|
||||
|
||||
{/* Recent activity */}
|
||||
{/* <section className="grid gap-4 lg:grid-cols-2">
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between">
|
||||
<CardTitle className="text-base">Recent artworks</CardTitle>
|
||||
<Button asChild variant="ghost" size="sm">
|
||||
<Link href="/artworks">Open</Link>
|
||||
</Button>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
{data.artworks.recent.length === 0 ? (
|
||||
<div className="text-sm text-muted-foreground">No artworks yet.</div>
|
||||
) : (
|
||||
<ul className="space-y-2">
|
||||
{data.artworks.recent.map((a) => (
|
||||
<li
|
||||
key={a.id}
|
||||
className="flex items-center justify-between gap-3 rounded-md border px-3 py-2"
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<div className="truncate font-medium">{a.name}</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
{fmtDate(a.createdAt)} · {a.colorStatus}
|
||||
{a.published ? " · published" : " · draft"}
|
||||
{a.needsWork ? " · needs work" : ""}
|
||||
</div>
|
||||
</div>
|
||||
<Button asChild variant="secondary" size="sm">
|
||||
<Link href={`/artworks/${a.slug}`}>Open</Link>
|
||||
</Button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between">
|
||||
<CardTitle className="text-base">Recent commission requests</CardTitle>
|
||||
<Button asChild variant="ghost" size="sm">
|
||||
<Link href="/commissions/requests">Open</Link>
|
||||
</Button>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
{data.commissions.recent.length === 0 ? (
|
||||
<div className="text-sm text-muted-foreground">
|
||||
No commission requests yet.
|
||||
</div>
|
||||
) : (
|
||||
<ul className="space-y-2">
|
||||
{data.commissions.recent.map((r) => (
|
||||
<li
|
||||
key={r.id}
|
||||
className="flex items-center justify-between gap-3 rounded-md border px-3 py-2"
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<div className="truncate font-medium">
|
||||
{r.customerName}{" "}
|
||||
<span className="text-muted-foreground">
|
||||
({r.customerEmail})
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
{fmtDate(r.createdAt)} · {r.status}
|
||||
</div>
|
||||
</div>
|
||||
<Button asChild variant="secondary" size="sm">
|
||||
<Link href={`/commissions/requests/${r.id}`}>Open</Link>
|
||||
</Button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</section> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,25 +1,46 @@
|
||||
import EditTagForm from "@/components/tags/EditTagForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Edit tag page.
|
||||
export default async function PortfolioTagsEditPage({ params }: { params: { id: string } }) {
|
||||
const { id } = await params;
|
||||
const tag = await prisma.artTag.findUnique({
|
||||
const tag = await prisma.tag.findUnique({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
include: {
|
||||
categories: true,
|
||||
categoryLinks: {
|
||||
include: {
|
||||
category: true,
|
||||
parentTag: { select: { id: true, name: true } },
|
||||
},
|
||||
},
|
||||
aliases: true
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
const categories = await prisma.artCategory.findMany({ include: { tags: true }, orderBy: { sortIndex: "asc" } });
|
||||
const tags = await prisma.artTag.findMany({ where: { isParent: true }, orderBy: { sortIndex: "asc" } });
|
||||
const categories = await prisma.artCategory.findMany({
|
||||
include: { tagLinks: true },
|
||||
orderBy: { sortIndex: "asc" },
|
||||
});
|
||||
const tags = await prisma.tag.findMany({ orderBy: { sortIndex: "asc" } });
|
||||
|
||||
const animalLink =
|
||||
tag?.categoryLinks.find((link) => link.category.name === "Animal Studies") ??
|
||||
null;
|
||||
const tagWithMeta = tag
|
||||
? {
|
||||
...tag,
|
||||
parentId: animalLink?.parentTagId ?? null,
|
||||
isParent: animalLink?.isParent ?? false,
|
||||
showOnAnimalPage: animalLink?.showOnAnimalPage ?? false,
|
||||
}
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold mb-4">Edit Tag</h1>
|
||||
{tag && <EditTagForm tag={tag} categories={categories} allTags={tags} />}
|
||||
{tagWithMeta && <EditTagForm tag={tagWithMeta} categories={categories} allTags={tags} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,9 +1,13 @@
|
||||
import NewTagForm from "@/components/tags/NewTagForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// Create a new tag page.
|
||||
export default async function PortfolioTagsNewPage() {
|
||||
const categories = await prisma.artCategory.findMany({ include: { tags: true }, orderBy: { sortIndex: "asc" } });
|
||||
const tags = await prisma.artTag.findMany({ where: { isParent: true }, orderBy: { sortIndex: "asc" } });
|
||||
const categories = await prisma.artCategory.findMany({
|
||||
include: { tagLinks: true },
|
||||
orderBy: { sortIndex: "asc" },
|
||||
});
|
||||
const tags = await prisma.tag.findMany({ orderBy: { sortIndex: "asc" } });
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@ -4,39 +4,63 @@ import { prisma } from "@/lib/prisma";
|
||||
import { PlusCircleIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
// Admin tags management page.
|
||||
export default async function ArtTagsPage() {
|
||||
const items = await prisma.artTag.findMany({
|
||||
const items = await prisma.tag.findMany({
|
||||
include: {
|
||||
parent: { select: { id: true, name: true } },
|
||||
aliases: { select: { alias: true } },
|
||||
categories: { select: { id: true, name: true } },
|
||||
categoryLinks: {
|
||||
include: {
|
||||
category: { select: { id: true, name: true } },
|
||||
parentTag: { select: { id: true, name: true } },
|
||||
},
|
||||
},
|
||||
_count: { select: { artworks: true } },
|
||||
},
|
||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||
});
|
||||
|
||||
const rows = items.map((tag) => {
|
||||
const categories = tag.categoryLinks.map((link) => link.category);
|
||||
const animalLink = tag.categoryLinks.find(
|
||||
(link) => link.category.name === "Animal Studies",
|
||||
);
|
||||
|
||||
return {
|
||||
id: tag.id,
|
||||
name: tag.name,
|
||||
slug: tag.slug,
|
||||
parent: animalLink?.parentTag ?? null,
|
||||
isParent: animalLink?.isParent ?? false,
|
||||
showOnAnimalPage: animalLink?.showOnAnimalPage ?? false,
|
||||
aliases: tag.aliases,
|
||||
categories,
|
||||
_count: tag._count,
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="mx-auto w-full max-w-7xl px-4 py-6">
|
||||
<header className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
|
||||
<div className="space-y-1">
|
||||
<h1 className="text-2xl font-semibold tracking-tight sm:text-3xl">
|
||||
Art Tags
|
||||
Tags
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Manage tags, aliases, categories, and usage across artworks.
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">Manage tags.</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2 sm:flex-row sm:items-center">
|
||||
<Button asChild className="h-11 gap-2">
|
||||
<Link href="/tags/new">
|
||||
<PlusCircleIcon className="h-4 w-4" />
|
||||
Add new tag
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{items.length > 0 ? (
|
||||
<TagTabs tags={items} />
|
||||
{rows.length > 0 ? (
|
||||
<TagTabs tags={rows} />
|
||||
) : (
|
||||
<p className="text-muted-foreground">
|
||||
There are no tags yet. Consider adding some!
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { getLatestTos } from "@/actions/tos/getTos";
|
||||
import TosEditor from "@/components/tos/Editor";
|
||||
|
||||
// Admin page for editing Terms of Service.
|
||||
export default async function TosPage() {
|
||||
const markdown = await getLatestTos();
|
||||
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import UploadBulkImageForm from "@/components/uploads/UploadBulkImageForm";
|
||||
|
||||
// Bulk image upload page.
|
||||
export default function UploadsBulkPage() {
|
||||
return (
|
||||
<div><UploadBulkImageForm /></div>
|
||||
<div>
|
||||
<UploadBulkImageForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,7 +1,10 @@
|
||||
import UploadImageForm from "@/components/uploads/UploadImageForm";
|
||||
|
||||
// Single image upload page.
|
||||
export default function UploadsSinglePage() {
|
||||
return (
|
||||
<div><UploadImageForm /></div>
|
||||
<div>
|
||||
<UploadImageForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,11 +1,13 @@
|
||||
import { CreateUserForm } from "@/components/users/CreateUserForm";
|
||||
import { auth } from "@/lib/auth";
|
||||
import type { SessionWithRole } from "@/types/auth";
|
||||
import { headers } from "next/headers";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
// Admin-only user creation page.
|
||||
export default async function NewUserPage() {
|
||||
const session = await auth.api.getSession({ headers: await headers() });
|
||||
const role = (session as any)?.user?.role;
|
||||
const role = (session as SessionWithRole)?.user?.role;
|
||||
|
||||
if (!session) redirect("/login");
|
||||
if (role !== "admin") redirect("/");
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import { UsersTable } from "@/components/users/UsersTable";
|
||||
import { auth } from "@/lib/auth";
|
||||
import type { SessionWithRole } from "@/types/auth";
|
||||
import { headers } from "next/headers";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
// Admin users list page.
|
||||
export default async function UsersPage() {
|
||||
const session = await auth.api.getSession({ headers: await headers() });
|
||||
const role = (session as any)?.user?.role as string | undefined;
|
||||
const role = (session as SessionWithRole)?.user?.role;
|
||||
|
||||
if (!session) redirect("/login");
|
||||
if (role !== "admin") redirect("/");
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { ForgotPasswordForm } from "@/components/auth/ForgotPasswordForm";
|
||||
|
||||
// Forgot password page.
|
||||
export default function ForgotPasswordPage() {
|
||||
return (
|
||||
<div className="mx-auto max-w-md p-6">
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
// Layout wrapper for auth routes.
|
||||
export default function AuthLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
children: ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen min-w-screen">
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import LoginForm from "@/components/auth/LoginForm";
|
||||
import { Suspense } from "react";
|
||||
|
||||
// Admin login page.
|
||||
export default function LoginPage() {
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center">
|
||||
|
||||
@ -2,6 +2,7 @@ import { RegisterForm } from "@/components/auth/RegisterForm";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
// One-time admin registration page (only when no users exist).
|
||||
export default async function RegisterPage() {
|
||||
const count = await prisma.user.count();
|
||||
if (count !== 0) redirect("/login");
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { ResetPasswordForm } from "@/components/auth/ResetPasswordForm";
|
||||
import Link from "next/link";
|
||||
|
||||
// Reset password page, expects a token query param.
|
||||
export default async function ResetPasswordPage({
|
||||
searchParams,
|
||||
}: {
|
||||
@ -13,7 +14,7 @@ export default async function ResetPasswordPage({
|
||||
<div className="mx-auto max-w-md p-6">
|
||||
<p>No valid token, please try again or get back to <Link href="/">Home</Link></p>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { getArtworksPage } from "@/lib/queryArtworks";
|
||||
import { NextResponse, type NextRequest } from "next/server";
|
||||
|
||||
// Public API for paginated artworks listing.
|
||||
export async function GET(req: NextRequest) {
|
||||
const publishedParam = req.nextUrl.searchParams.get("published") ?? "all";
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { auth } from "@/lib/auth";
|
||||
import { toNextJsHandler } from "better-auth/next-js";
|
||||
|
||||
// Better Auth route handlers.
|
||||
export const { POST, GET } = toNextJsHandler(auth);
|
||||
@ -1,7 +1,24 @@
|
||||
import { s3 } from "@/lib/s3";
|
||||
import type { S3Body } from "@/types/s3";
|
||||
import { GetObjectCommand } from "@aws-sdk/client-s3";
|
||||
import type { NextRequest } from "next/server";
|
||||
import { Readable } from "node:stream";
|
||||
|
||||
function isWebReadableStream(value: unknown): value is ReadableStream<Uint8Array> {
|
||||
return !!value && typeof (value as ReadableStream<Uint8Array>).getReader === "function";
|
||||
}
|
||||
|
||||
function toBodyInit(body: S3Body): BodyInit {
|
||||
if (body instanceof Readable) {
|
||||
return Readable.toWeb(body) as ReadableStream<Uint8Array>;
|
||||
}
|
||||
if (isWebReadableStream(body)) {
|
||||
return body;
|
||||
}
|
||||
return body as BodyInit;
|
||||
}
|
||||
|
||||
// Streams images from S3 for the admin app.
|
||||
export async function GET(_req: NextRequest, context: { params: Promise<{ key: string[] }> }) {
|
||||
const { key } = await context.params;
|
||||
const s3Key = key.join("/");
|
||||
@ -20,7 +37,7 @@ export async function GET(_req: NextRequest, context: { params: Promise<{ key: s
|
||||
|
||||
const contentType = response.ContentType ?? "application/octet-stream";
|
||||
|
||||
return new Response(response.Body as ReadableStream, {
|
||||
return new Response(toBodyInit(response.Body as S3Body), {
|
||||
headers: {
|
||||
"Content-Type": contentType,
|
||||
"Cache-Control": "public, max-age=3600",
|
||||
@ -28,7 +45,7 @@ export async function GET(_req: NextRequest, context: { params: Promise<{ key: s
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
console.error(err);
|
||||
return new Response("Image not found", { status: 404 });
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user