Compare commits
1 Commits
artworks
...
ai-alt-tex
| Author | SHA1 | Date | |
|---|---|---|---|
|
eb4391d1d7
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -41,4 +41,3 @@ yarn-error.log*
|
|||||||
next-env.d.ts
|
next-env.d.ts
|
||||||
|
|
||||||
/src/generated/prisma
|
/src/generated/prisma
|
||||||
/scripts/
|
|
||||||
|
|||||||
@ -18,12 +18,6 @@ RUN bunx prisma generate
|
|||||||
|
|
||||||
# Uncomment the following line in case you want to disable telemetry during the build.
|
# Uncomment the following line in case you want to disable telemetry during the build.
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
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
|
# Copy the rest of the code
|
||||||
RUN bun run build -d
|
RUN bun run build -d
|
||||||
@ -37,12 +31,6 @@ ENV NEXT_TELEMETRY_DISABLED=1
|
|||||||
ENV NODE_ENV=production \
|
ENV NODE_ENV=production \
|
||||||
PORT=3000 \
|
PORT=3000 \
|
||||||
HOSTNAME="0.0.0.0"
|
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 && \
|
RUN groupadd --system --gid 1001 nodejs && \
|
||||||
useradd --system --uid 1001 --no-log-init -g nodejs nextjs
|
useradd --system --uid 1001 --no-log-init -g nodejs nextjs
|
||||||
|
|||||||
@ -14,16 +14,11 @@ FROM base AS builder
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
COPY . .
|
COPY . .
|
||||||
|
# RUN bunx prisma migrate deploy
|
||||||
RUN bunx prisma generate
|
RUN bunx prisma generate
|
||||||
|
|
||||||
# Uncomment the following line in case you want to disable telemetry during the build.
|
# Uncomment the following line in case you want to disable telemetry during the build.
|
||||||
ENV NEXT_TELEMETRY_DISABLED=1
|
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
|
# Copy the rest of the code
|
||||||
RUN bun run build -d
|
RUN bun run build -d
|
||||||
@ -37,12 +32,6 @@ ENV NEXT_TELEMETRY_DISABLED=1
|
|||||||
ENV NODE_ENV=production \
|
ENV NODE_ENV=production \
|
||||||
PORT=3000 \
|
PORT=3000 \
|
||||||
HOSTNAME="0.0.0.0"
|
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 && \
|
RUN groupadd --system --gid 1001 nodejs && \
|
||||||
useradd --system --uid 1001 --no-log-init -g nodejs nextjs
|
useradd --system --uid 1001 --no-log-init -g nodejs nextjs
|
||||||
|
|||||||
327
bun.lock
327
bun.lock
@ -5,8 +5,8 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "admin.gaertan.art",
|
"name": "admin.gaertan.art",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.980.0",
|
"@aws-sdk/client-s3": "^3.974.0",
|
||||||
"@aws-sdk/s3-request-presigner": "^3.980.0",
|
"@aws-sdk/s3-request-presigner": "^3.974.0",
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@dnd-kit/modifiers": "^9.0.0",
|
"@dnd-kit/modifiers": "^9.0.0",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
@ -39,7 +39,7 @@
|
|||||||
"@radix-ui/react-tooltip": "^1.2.8",
|
"@radix-ui/react-tooltip": "^1.2.8",
|
||||||
"@tanstack/react-table": "^8.21.3",
|
"@tanstack/react-table": "^8.21.3",
|
||||||
"archiver": "^7.0.1",
|
"archiver": "^7.0.1",
|
||||||
"better-auth": "^1.4.18",
|
"better-auth": "^1.4.17",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
@ -48,15 +48,15 @@
|
|||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"lowlight": "^3.3.0",
|
"lowlight": "^3.3.0",
|
||||||
"lucide-react": "^0.561.0",
|
"lucide-react": "^0.561.0",
|
||||||
"next": "16.1.6",
|
"next": "^16.1.4",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"node-vibrant": "^4.0.4",
|
"node-vibrant": "^4.0.3",
|
||||||
"nodemailer": "^7.0.13",
|
"nodemailer": "^7.0.12",
|
||||||
"pg": "^8.18.0",
|
"pg": "^8.17.2",
|
||||||
"platejs": "^52.0.17",
|
"platejs": "^52.0.17",
|
||||||
"react": "19.2.4",
|
"react": "19.2.1",
|
||||||
"react-day-picker": "^9.13.0",
|
"react-day-picker": "^9.13.0",
|
||||||
"react-dom": "19.2.4",
|
"react-dom": "19.2.1",
|
||||||
"react-hook-form": "^7.71.1",
|
"react-hook-form": "^7.71.1",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"remark-math": "^6.0.0",
|
"remark-math": "^6.0.0",
|
||||||
@ -65,7 +65,6 @@
|
|||||||
"tailwind-scrollbar-hide": "^4.0.0",
|
"tailwind-scrollbar-hide": "^4.0.0",
|
||||||
"uuid": "^13.0.0",
|
"uuid": "^13.0.0",
|
||||||
"zod": "^4.3.6",
|
"zod": "^4.3.6",
|
||||||
"zustand": "^5.0.8",
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "2.2.0",
|
"@biomejs/biome": "2.2.0",
|
||||||
@ -74,10 +73,10 @@
|
|||||||
"@types/culori": "^4.0.1",
|
"@types/culori": "^4.0.1",
|
||||||
"@types/date-fns": "^2.6.3",
|
"@types/date-fns": "^2.6.3",
|
||||||
"@types/node": "^20.19.30",
|
"@types/node": "^20.19.30",
|
||||||
"@types/nodemailer": "^7.0.9",
|
"@types/nodemailer": "^7.0.5",
|
||||||
"@types/pg": "^8.16.0",
|
"@types/pg": "^8.16.0",
|
||||||
"@types/react": "19.2.10",
|
"@types/react": "^19.2.9",
|
||||||
"@types/react-dom": "19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@types/uuid": "^11.0.0",
|
"@types/uuid": "^11.0.0",
|
||||||
"prisma": "^7.3.0",
|
"prisma": "^7.3.0",
|
||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.1.18",
|
||||||
@ -86,10 +85,6 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"overrides": {
|
|
||||||
"@types/react": "19.2.10",
|
|
||||||
"@types/react-dom": "19.2.3",
|
|
||||||
},
|
|
||||||
"packages": {
|
"packages": {
|
||||||
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||||
|
|
||||||
@ -107,81 +102,83 @@
|
|||||||
|
|
||||||
"@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-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.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-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-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-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/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/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/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/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.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-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-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-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-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-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-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-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-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-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-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-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-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-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-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/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/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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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/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/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/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/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/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/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/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/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/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/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/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/types": ["@aws-sdk/types@3.973.1", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DwHBiMNOB468JiX6+i34c+THsKHErYUdNQ3HexeXZvVn4zouLjgaS4FejiGSi2HyBuzuyHg7SuOPmjSvoU9NRg=="],
|
"@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/util-arn-parser": ["@aws-sdk/util-arn-parser@3.972.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-VkykWbqMjlSgBFDyrY3nOSqupMc6ivXuGmvci6Q3NnLq5kC+mKQe2QBZ4nrWRE/jqOxeFP2uYzLtwncYYcvQDg=="],
|
"@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-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-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-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-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-locate-window": ["@aws-sdk/util-locate-window@3.953.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-mPxK+I1LcrgC/RSa3G5AMAn8eN2Ay0VOgw8lSRmV1jCtO+iYvNeCqOdxoJUjOW6I5BA4niIRWqVORuRP07776Q=="],
|
"@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.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-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-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/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/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-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/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.2", "", {}, "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg=="],
|
"@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.2", "", {}, "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg=="],
|
||||||
|
|
||||||
"@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/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/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/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/utils": ["@better-auth/utils@0.3.0", "", {}, "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw=="],
|
"@better-auth/utils": ["@better-auth/utils@0.3.0", "", {}, "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw=="],
|
||||||
|
|
||||||
@ -331,23 +328,23 @@
|
|||||||
|
|
||||||
"@mrleebo/prisma-ast": ["@mrleebo/prisma-ast@0.13.1", "", { "dependencies": { "chevrotain": "^10.5.0", "lilconfig": "^2.1.0" } }, "sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw=="],
|
"@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.6", "", {}, "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ=="],
|
"@next/env": ["@next/env@16.1.4", "", {}, "sha512-gkrXnZyxPUy0Gg6SrPQPccbNVLSP3vmW8LU5dwEttEEC1RwDivk8w4O+sZIjFvPrSICXyhQDCG+y3VmjlJf+9A=="],
|
||||||
|
|
||||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.1.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw=="],
|
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.1.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-T8atLKuvk13XQUdVLCv1ZzMPgLPW0+DWWbHSQXs0/3TjPrKNxTmUIhOEaoEyl3Z82k8h/gEtqyuoZGv6+Ugawg=="],
|
||||||
|
|
||||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.1.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ=="],
|
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.1.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-AKC/qVjUGUQDSPI6gESTx0xOnOPQ5gttogNS3o6bA83yiaSZJek0Am5yXy82F1KcZCx3DdOwdGPZpQCluonuxg=="],
|
||||||
|
|
||||||
"@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-gnu": ["@next/swc-linux-arm64-gnu@16.1.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-POQ65+pnYOkZNdngWfMEt7r53bzWiKkVNbjpmCt1Zb3V6lxJNXSsjwRuTQ8P/kguxDC8LRkqaL3vvsFrce4dMQ=="],
|
||||||
|
|
||||||
"@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-arm64-musl": ["@next/swc-linux-arm64-musl@16.1.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-3Wm0zGYVCs6qDFAiSSDL+Z+r46EdtCv/2l+UlIdMbAq9hPJBvGu/rZOeuvCaIUjbArkmXac8HnTyQPJFzFWA0Q=="],
|
||||||
|
|
||||||
"@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-gnu": ["@next/swc-linux-x64-gnu@16.1.4", "", { "os": "linux", "cpu": "x64" }, "sha512-lWAYAezFinaJiD5Gv8HDidtsZdT3CDaCeqoPoJjeB57OqzvMajpIhlZFce5sCAH6VuX4mdkxCRqecCJFwfm2nQ=="],
|
||||||
|
|
||||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg=="],
|
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.1.4", "", { "os": "linux", "cpu": "x64" }, "sha512-fHaIpT7x4gA6VQbdEpYUXRGyge/YbRrkG6DXM60XiBqDM2g2NcrsQaIuj375egnGFkJow4RHacgBOEsHfGbiUw=="],
|
||||||
|
|
||||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.1.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw=="],
|
"@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-x64-msvc": ["@next/swc-win32-x64-msvc@16.1.6", "", { "os": "win32", "cpu": "x64" }, "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A=="],
|
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-JSVlm9MDhmTXw/sO2PE/MRj+G6XOSMZB+BcZ0a7d6KwVFZVpkHcb2okyoYFBaco6LeiL53BBklRlOrDDbOeE5w=="],
|
||||||
|
|
||||||
"@noble/ciphers": ["@noble/ciphers@2.1.1", "", {}, "sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw=="],
|
"@noble/ciphers": ["@noble/ciphers@2.1.1", "", {}, "sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw=="],
|
||||||
|
|
||||||
@ -499,7 +496,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/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.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/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/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=="],
|
"@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=="],
|
||||||
|
|
||||||
@ -529,9 +526,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-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.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-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-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-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-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=="],
|
"@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=="],
|
||||||
|
|
||||||
@ -555,7 +552,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/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.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/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/types": ["@smithy/types@4.12.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw=="],
|
"@smithy/types": ["@smithy/types@4.12.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw=="],
|
||||||
|
|
||||||
@ -571,9 +568,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-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.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-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-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-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-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=="],
|
"@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=="],
|
||||||
|
|
||||||
@ -657,11 +654,11 @@
|
|||||||
|
|
||||||
"@types/node": ["@types/node@20.19.30", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g=="],
|
"@types/node": ["@types/node@20.19.30", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g=="],
|
||||||
|
|
||||||
"@types/nodemailer": ["@types/nodemailer@7.0.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-vI8oF1M+8JvQhsId0Pc38BdUP2evenIIys7c7p+9OZXSPOH5c1dyINP1jT8xQ2xPuBUXmIC87s+91IZMDjH8Ow=="],
|
"@types/nodemailer": ["@types/nodemailer@7.0.5", "", { "dependencies": { "@aws-sdk/client-sesv2": "^3.839.0", "@types/node": "*" } }, "sha512-7WtR4MFJUNN2UFy0NIowBRJswj5KXjXDhlZY43Hmots5eGu5q/dTeFd/I6GgJA/qj3RqO6dDy4SvfcV3fOVeIA=="],
|
||||||
|
|
||||||
"@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/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.10", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw=="],
|
"@types/react": ["@types/react@19.2.9", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA=="],
|
||||||
|
|
||||||
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
||||||
|
|
||||||
@ -677,27 +674,27 @@
|
|||||||
|
|
||||||
"@udecode/utils": ["@udecode/utils@52.0.1", "", {}, "sha512-T/qa4++J2MMY9CbhZ05ONpcpkvsRV0uBvOfMhhYWKkAND4DSVAVzmZTV7WQ5fjGq81agAped0WQxcqsEg617uQ=="],
|
"@udecode/utils": ["@udecode/utils@52.0.1", "", {}, "sha512-T/qa4++J2MMY9CbhZ05ONpcpkvsRV0uBvOfMhhYWKkAND4DSVAVzmZTV7WQ5fjGq81agAped0WQxcqsEg617uQ=="],
|
||||||
|
|
||||||
"@vibrant/color": ["@vibrant/color@4.0.4", "", {}, "sha512-Fq2tAszz4QOPWfHZ+KuEAchXUD8i594BM2fOJt8dI/fvYbiVoBycBF/BlNH6F4IWBubxXoPqD4JmmAHvFYbNew=="],
|
"@vibrant/color": ["@vibrant/color@4.0.0", "", {}, "sha512-S9ItdqS1135wTXoIIqAJu8df9dqlOo6Boc5Y4MGsBTu9UmUOvOwfj5b4Ga6S5yrLAKmKYIactkz7zYJdMddkig=="],
|
||||||
|
|
||||||
"@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/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/generator": ["@vibrant/generator@4.0.4", "", { "dependencies": { "@vibrant/color": "^4.0.4", "@vibrant/types": "^4.0.4" } }, "sha512-rwq8PnlpKdch4YqaA1FAwdm71gKE2cMrUsbu72TqRFGa8rpP1roaZlQCVXIIwElXVc3r9axZyAcqyTLaMjhrTg=="],
|
"@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-default": ["@vibrant/generator-default@4.0.4", "", { "dependencies": { "@vibrant/color": "^4.0.4", "@vibrant/generator": "^4.0.4" } }, "sha512-QeVDeH2dz9lityvJCb84Ml4hlBTElwCpU7SVpiDFBh6gPoCLnzcb1H9G4NgG3hOlAPyrBM+Ivq1Pg+1lZj5Ywg=="],
|
"@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/image": ["@vibrant/image@4.0.4", "", { "dependencies": { "@vibrant/color": "^4.0.4" } }, "sha512-NBIJj7umfDRVpFjJHQo1AFSCWCzQyjfil+Yxu7W62PEL72GPCif0CDiglPkvVF8QhDLmnx/x1k3LIBb9jWF2sw=="],
|
"@vibrant/image": ["@vibrant/image@4.0.0", "", { "dependencies": { "@vibrant/color": "^4.0.0" } }, "sha512-Asv/7R/L701norosgvbjOVkodFiwcFihkXixA/gbAd6C+5GCts1Wm1NPk14FNKnM7eKkfAN+0wwPkdOH+PY/YA=="],
|
||||||
|
|
||||||
"@vibrant/image-browser": ["@vibrant/image-browser@4.0.4", "", { "dependencies": { "@vibrant/image": "^4.0.4" } }, "sha512-7qVyAm+z9t98iwMDzUgGCwgRg0KBB5RXQFgiO2Um5Izd1wO7BKC0SHVEz2k7sRx3XNfBf+JExp8quPrvSz17gg=="],
|
"@vibrant/image-browser": ["@vibrant/image-browser@4.0.0", "", { "dependencies": { "@vibrant/image": "^4.0.0" } }, "sha512-mXckzvJWiP575Y/wNtP87W/TPgyJoGlPBjW4E9YmNS6n4Jb6RqyHQA0ZVulqDslOxjSsihDzY7gpAORRclaoLg=="],
|
||||||
|
|
||||||
"@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/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/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": ["@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-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/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/types": ["@vibrant/types@4.0.4", "", {}, "sha512-Qq3mVTJamn7yD4OBgBEUKaxfDlm3sxBK55N7dH3XzI9Ey7KR00R06uwtqOcEJMsziWTEXdYN3VUlYaj2Tkt7hw=="],
|
"@vibrant/types": ["@vibrant/types@4.0.0", "", {}, "sha512-tA5TAbuROXcPkt+PWjmGfoaiEXyySVaNnCZovf6vXhCbMdrTTCQXvNCde2geiVl6YwtuU/Qrj9iZxS5jZ6yVIw=="],
|
||||||
|
|
||||||
"@vibrant/worker": ["@vibrant/worker@4.0.4", "", { "dependencies": { "@vibrant/types": "^4.0.4" } }, "sha512-Q/R6PYhSMWCXEk/IcXbWIzIu7Z4b58ABkGvcdF8Y+q/7g+KnpxKW5x/jfQ/6ciyYSby13wZZoEdNr3QQVgsdBQ=="],
|
"@vibrant/worker": ["@vibrant/worker@4.0.0", "", { "dependencies": { "@vibrant/types": "^4.0.0" } }, "sha512-nSaZZwWQKOgN/nPYUAIRF0/uoa7KpK91A+gjLmZZDgfN1enqxaiihmn+75ayNadW0c6cxAEpEFEHTONR5u9tMw=="],
|
||||||
|
|
||||||
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
|
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
|
||||||
|
|
||||||
@ -733,7 +730,7 @@
|
|||||||
|
|
||||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.9.11", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ=="],
|
"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.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-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-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=="],
|
"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=="],
|
||||||
|
|
||||||
@ -1117,7 +1114,7 @@
|
|||||||
|
|
||||||
"nanostores": ["nanostores@1.1.0", "", {}, "sha512-yJBmDJr18xy47dbNVlHcgdPrulSn1nhSE6Ns9vTG+Nx9VPT6iV1MD6aQFp/t52zpf82FhLLTXAXr30NuCnxvwA=="],
|
"nanostores": ["nanostores@1.1.0", "", {}, "sha512-yJBmDJr18xy47dbNVlHcgdPrulSn1nhSE6Ns9vTG+Nx9VPT6iV1MD6aQFp/t52zpf82FhLLTXAXr30NuCnxvwA=="],
|
||||||
|
|
||||||
"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": ["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-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=="],
|
"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=="],
|
||||||
|
|
||||||
@ -1125,9 +1122,9 @@
|
|||||||
|
|
||||||
"node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="],
|
"node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="],
|
||||||
|
|
||||||
"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=="],
|
"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=="],
|
||||||
|
|
||||||
"nodemailer": ["nodemailer@7.0.13", "", {}, "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw=="],
|
"nodemailer": ["nodemailer@7.0.12", "", {}, "sha512-H+rnK5bX2Pi/6ms3sN4/jRQvYSMltV6vqup/0SFOrxYYY/qoNvhXPlYq3e+Pm9RFJRwrMGbMIwi81M4dxpomhA=="],
|
||||||
|
|
||||||
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
|
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
|
||||||
|
|
||||||
@ -1155,11 +1152,11 @@
|
|||||||
|
|
||||||
"perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="],
|
"perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="],
|
||||||
|
|
||||||
"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": ["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-cloudflare": ["pg-cloudflare@1.3.0", "", {}, "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ=="],
|
"pg-cloudflare": ["pg-cloudflare@1.3.0", "", {}, "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ=="],
|
||||||
|
|
||||||
"pg-connection-string": ["pg-connection-string@2.11.0", "", {}, "sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ=="],
|
"pg-connection-string": ["pg-connection-string@2.10.1", "", {}, "sha512-iNzslsoeSH2/gmDDKiyMqF64DATUCWj3YJ0wP14kqcsf2TUklwimd+66yYojKwZCA7h2yRNLGug71hCBA2a4sw=="],
|
||||||
|
|
||||||
"pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
|
"pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
|
||||||
|
|
||||||
@ -1207,13 +1204,13 @@
|
|||||||
|
|
||||||
"rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="],
|
"rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="],
|
||||||
|
|
||||||
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
|
"react": ["react@19.2.1", "", {}, "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw=="],
|
||||||
|
|
||||||
"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-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-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.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
|
"react-dom": ["react-dom@19.2.1", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.1" } }, "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg=="],
|
||||||
|
|
||||||
"react-hook-form": ["react-hook-form@7.71.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w=="],
|
"react-hook-form": ["react-hook-form@7.71.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w=="],
|
||||||
|
|
||||||
@ -1429,12 +1426,82 @@
|
|||||||
|
|
||||||
"@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-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=="],
|
"@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=="],
|
"@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/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=="],
|
"@prisma/fetch-engine/@prisma/get-platform": ["@prisma/get-platform@7.3.0", "", { "dependencies": { "@prisma/debug": "7.3.0" } }, "sha512-N7c6m4/I0Q6JYmWKP2RCD/sM9eWiyCPY98g5c0uEktObNSZnugW2U/PO+pwL0UaqzxqTXt7gTsYsb0FnMnJNbg=="],
|
||||||
@ -1521,9 +1588,65 @@
|
|||||||
|
|
||||||
"@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-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=="],
|
||||||
|
|
||||||
"@prisma/adapter-pg/pg/pg-connection-string": ["pg-connection-string@2.10.1", "", {}, "sha512-iNzslsoeSH2/gmDDKiyMqF64DATUCWj3YJ0wP14kqcsf2TUklwimd+66yYojKwZCA7h2yRNLGug71hCBA2a4sw=="],
|
"@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-protocol": ["pg-protocol@1.11.0", "", {}, "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g=="],
|
"@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=="],
|
||||||
|
|
||||||
"lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
"lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||||
|
|
||||||
@ -1542,5 +1665,25 @@
|
|||||||
"@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/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-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=="],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8880
package-lock.json
generated
8880
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
33
package.json
33
package.json
@ -1,19 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "admin.gaertan.art",
|
"name": "admin.gaertan.art",
|
||||||
"version": "1.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "PORT=3001 NODE_OPTIONS='--max-old-space-size=4096' next dev",
|
"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": "next build",
|
||||||
"build:version": "NEXT_PUBLIC_GIT_SHA=$(git rev-parse --short HEAD) NEXT_PUBLIC_DEPLOY_ENV=prod bun run build",
|
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "biome check",
|
"lint": "biome check",
|
||||||
"format": "biome format --write"
|
"format": "biome format --write"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.980.0",
|
"@aws-sdk/client-s3": "^3.974.0",
|
||||||
"@aws-sdk/s3-request-presigner": "^3.980.0",
|
"@aws-sdk/s3-request-presigner": "^3.974.0",
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@dnd-kit/modifiers": "^9.0.0",
|
"@dnd-kit/modifiers": "^9.0.0",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
@ -46,7 +44,7 @@
|
|||||||
"@radix-ui/react-tooltip": "^1.2.8",
|
"@radix-ui/react-tooltip": "^1.2.8",
|
||||||
"@tanstack/react-table": "^8.21.3",
|
"@tanstack/react-table": "^8.21.3",
|
||||||
"archiver": "^7.0.1",
|
"archiver": "^7.0.1",
|
||||||
"better-auth": "^1.4.18",
|
"better-auth": "^1.4.17",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
@ -55,15 +53,15 @@
|
|||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"lowlight": "^3.3.0",
|
"lowlight": "^3.3.0",
|
||||||
"lucide-react": "^0.561.0",
|
"lucide-react": "^0.561.0",
|
||||||
"next": "16.1.6",
|
"next": "^16.1.4",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"node-vibrant": "^4.0.4",
|
"node-vibrant": "^4.0.3",
|
||||||
"nodemailer": "^7.0.13",
|
"nodemailer": "^7.0.12",
|
||||||
"pg": "^8.18.0",
|
"pg": "^8.17.2",
|
||||||
"platejs": "^52.0.17",
|
"platejs": "^52.0.17",
|
||||||
"react": "19.2.4",
|
"react": "19.2.1",
|
||||||
"react-day-picker": "^9.13.0",
|
"react-day-picker": "^9.13.0",
|
||||||
"react-dom": "19.2.4",
|
"react-dom": "19.2.1",
|
||||||
"react-hook-form": "^7.71.1",
|
"react-hook-form": "^7.71.1",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"remark-math": "^6.0.0",
|
"remark-math": "^6.0.0",
|
||||||
@ -71,7 +69,6 @@
|
|||||||
"tailwind-merge": "^3.4.0",
|
"tailwind-merge": "^3.4.0",
|
||||||
"tailwind-scrollbar-hide": "^4.0.0",
|
"tailwind-scrollbar-hide": "^4.0.0",
|
||||||
"uuid": "^13.0.0",
|
"uuid": "^13.0.0",
|
||||||
"zustand": "^5.0.8",
|
|
||||||
"zod": "^4.3.6"
|
"zod": "^4.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -81,18 +78,14 @@
|
|||||||
"@types/culori": "^4.0.1",
|
"@types/culori": "^4.0.1",
|
||||||
"@types/date-fns": "^2.6.3",
|
"@types/date-fns": "^2.6.3",
|
||||||
"@types/node": "^20.19.30",
|
"@types/node": "^20.19.30",
|
||||||
"@types/nodemailer": "^7.0.9",
|
"@types/nodemailer": "^7.0.5",
|
||||||
"@types/pg": "^8.16.0",
|
"@types/pg": "^8.16.0",
|
||||||
"@types/react": "19.2.10",
|
"@types/react": "^19.2.9",
|
||||||
"@types/react-dom": "19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@types/uuid": "^11.0.0",
|
"@types/uuid": "^11.0.0",
|
||||||
"prisma": "^7.3.0",
|
"prisma": "^7.3.0",
|
||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.1.18",
|
||||||
"tw-animate-css": "^1.4.0",
|
"tw-animate-css": "^1.4.0",
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
},
|
|
||||||
"overrides": {
|
|
||||||
"@types/react": "19.2.10",
|
|
||||||
"@types/react-dom": "19.2.3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,65 +0,0 @@
|
|||||||
-- 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;
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
-- 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;
|
|
||||||
@ -1,140 +0,0 @@
|
|||||||
-- 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;
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
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;
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
-- 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[]
|
albums Album[]
|
||||||
categories ArtCategory[]
|
categories ArtCategory[]
|
||||||
colors ArtworkColor[]
|
colors ArtworkColor[]
|
||||||
tags Tag[] @relation("ArtworkTags")
|
tags ArtTag[]
|
||||||
variants FileVariant[]
|
variants FileVariant[]
|
||||||
|
|
||||||
@@index([colorStatus])
|
@@index([colorStatus])
|
||||||
@ -101,7 +101,43 @@ model ArtCategory {
|
|||||||
description String?
|
description String?
|
||||||
|
|
||||||
artworks Artwork[]
|
artworks Artwork[]
|
||||||
tagLinks TagCategory[]
|
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])
|
||||||
}
|
}
|
||||||
|
|
||||||
model Color {
|
model Color {
|
||||||
@ -212,72 +248,6 @@ model FileVariant {
|
|||||||
@@unique([artworkId, type])
|
@@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 {
|
model Commission {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
@ -295,35 +265,12 @@ model CommissionType {
|
|||||||
|
|
||||||
description String?
|
description String?
|
||||||
|
|
||||||
tags Tag[] @relation("CommissionTypeTags")
|
|
||||||
|
|
||||||
options CommissionTypeOption[]
|
options CommissionTypeOption[]
|
||||||
extras CommissionTypeExtra[]
|
extras CommissionTypeExtra[]
|
||||||
customInputs CommissionTypeCustomInput[]
|
customInputs CommissionTypeCustomInput[]
|
||||||
requests CommissionRequest[]
|
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 {
|
model CommissionOption {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
@ -335,7 +282,6 @@ model CommissionOption {
|
|||||||
description String?
|
description String?
|
||||||
|
|
||||||
types CommissionTypeOption[]
|
types CommissionTypeOption[]
|
||||||
customCards CommissionCustomCardOption[]
|
|
||||||
requests CommissionRequest[]
|
requests CommissionRequest[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +316,6 @@ model CommissionExtra {
|
|||||||
|
|
||||||
requests CommissionRequest[]
|
requests CommissionRequest[]
|
||||||
types CommissionTypeExtra[]
|
types CommissionTypeExtra[]
|
||||||
customCards CommissionCustomCardExtra[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model CommissionTypeExtra {
|
model CommissionTypeExtra {
|
||||||
@ -392,25 +337,6 @@ model CommissionTypeExtra {
|
|||||||
@@unique([typeId, extraId])
|
@@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 {
|
model CommissionCustomInput {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
@ -442,25 +368,6 @@ model CommissionTypeCustomInput {
|
|||||||
@@unique([typeId, customInputId])
|
@@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 {
|
model CommissionRequest {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
index Int @default(autoincrement())
|
index Int @default(autoincrement())
|
||||||
@ -479,10 +386,8 @@ model CommissionRequest {
|
|||||||
|
|
||||||
optionId String?
|
optionId String?
|
||||||
typeId String?
|
typeId String?
|
||||||
customCardId String?
|
|
||||||
option CommissionOption? @relation(fields: [optionId], references: [id])
|
option CommissionOption? @relation(fields: [optionId], references: [id])
|
||||||
type CommissionType? @relation(fields: [typeId], references: [id])
|
type CommissionType? @relation(fields: [typeId], references: [id])
|
||||||
customCard CommissionCustomCard? @relation(fields: [customCardId], references: [id])
|
|
||||||
|
|
||||||
extras CommissionExtra[]
|
extras CommissionExtra[]
|
||||||
files CommissionRequestFile[]
|
files CommissionRequestFile[]
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import { prisma } from "@/lib/prisma";
|
|||||||
import { s3 } from "@/lib/s3";
|
import { s3 } from "@/lib/s3";
|
||||||
import { DeleteObjectCommand } from "@aws-sdk/client-s3";
|
import { DeleteObjectCommand } from "@aws-sdk/client-s3";
|
||||||
|
|
||||||
// Deletes an artwork and all related assets and records.
|
|
||||||
export async function deleteArtwork(artworkId: string) {
|
export async function deleteArtwork(artworkId: string) {
|
||||||
const artwork = await prisma.artwork.findUnique({
|
const artwork = await prisma.artwork.findUnique({
|
||||||
where: { id: artworkId },
|
where: { id: artworkId },
|
||||||
|
|||||||
86
src/actions/artworks/generateAltText.ts
Normal file
86
src/actions/artworks/generateAltText.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
"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,49 +1,36 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import type { VibrantSwatch } from "@/types/VibrantSwatch";
|
import { VibrantSwatch } from "@/types/VibrantSwatch";
|
||||||
import { getImageBufferFromS3Key } from "@/utils/getImageBufferFromS3";
|
import { getImageBufferFromS3Key } from "@/utils/getImageBufferFromS3";
|
||||||
import { generateColorName, rgbToHex } from "@/utils/uploadHelper";
|
import { generateColorName, rgbToHex } from "@/utils/uploadHelper";
|
||||||
import { converter, parse } from "culori";
|
import { converter, parse } from "culori";
|
||||||
import { Vibrant } from "node-vibrant/node";
|
import { Vibrant } from "node-vibrant/node";
|
||||||
|
|
||||||
const toOklab = converter("oklab");
|
const toOklab = converter("oklab");
|
||||||
const A_MIN = -0.5,
|
const A_MIN = -0.5, A_MAX = 0.5;
|
||||||
A_MAX = 0.5;
|
const B_MIN = -0.5, B_MAX = 0.5;
|
||||||
const B_MIN = -0.5,
|
|
||||||
B_MAX = 0.5;
|
|
||||||
|
|
||||||
function clamp01(x: number) {
|
function clamp01(x: number) { return Math.max(0, Math.min(1, x)); }
|
||||||
return Math.max(0, Math.min(1, x));
|
function norm(x: number, lo: number, hi: number) { return clamp01((x - lo) / (hi - lo)); }
|
||||||
}
|
|
||||||
function norm(x: number, lo: number, hi: number) {
|
|
||||||
return clamp01((x - lo) / (hi - lo));
|
|
||||||
}
|
|
||||||
|
|
||||||
function hilbertIndex15(x01: number, y01: number): number {
|
function hilbertIndex15(x01: number, y01: number): number {
|
||||||
let x = Math.floor(clamp01(x01) * 32767);
|
let x = Math.floor(clamp01(x01) * 32767);
|
||||||
let y = Math.floor(clamp01(y01) * 32767);
|
let y = Math.floor(clamp01(y01) * 32767);
|
||||||
let index = 0;
|
let index = 0;
|
||||||
for (let s = 1 << 14; s > 0; s >>= 1) {
|
for (let s = 1 << 14; s > 0; s >>= 1) {
|
||||||
const rx = x & s ? 1 : 0;
|
const rx = (x & s) ? 1 : 0;
|
||||||
const ry = y & s ? 1 : 0;
|
const ry = (y & s) ? 1 : 0;
|
||||||
index += s * s * ((3 * rx) ^ ry);
|
index += s * s * ((3 * rx) ^ ry);
|
||||||
if (ry === 0) {
|
if (ry === 0) {
|
||||||
if (rx === 1) {
|
if (rx === 1) { x = 32767 - x; y = 32767 - y; }
|
||||||
x = 32767 - x;
|
const t = x; x = y; y = t;
|
||||||
y = 32767 - y;
|
|
||||||
}
|
|
||||||
const t = x;
|
|
||||||
x = y;
|
|
||||||
y = t;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return index >>> 0;
|
return index >>> 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function centroidFromPaletteHexes(
|
function centroidFromPaletteHexes(hexByType: Record<string, string | undefined>) {
|
||||||
hexByType: Record<string, string | undefined>,
|
|
||||||
) {
|
|
||||||
const weights: Record<string, number> = {
|
const weights: Record<string, number> = {
|
||||||
Vibrant: 0.7,
|
Vibrant: 0.7,
|
||||||
Muted: 0.15,
|
Muted: 0.15,
|
||||||
@ -54,27 +41,21 @@ function centroidFromPaletteHexes(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fallbackHex =
|
const fallbackHex =
|
||||||
hexByType.Vibrant ||
|
hexByType["Vibrant"] ||
|
||||||
hexByType.Muted ||
|
hexByType["Muted"] ||
|
||||||
hexByType.DarkVibrant ||
|
hexByType["DarkVibrant"] ||
|
||||||
hexByType.DarkMuted ||
|
hexByType["DarkMuted"] ||
|
||||||
hexByType.LightVibrant ||
|
hexByType["LightVibrant"] ||
|
||||||
hexByType.LightMuted;
|
hexByType["LightMuted"];
|
||||||
|
|
||||||
let L = 0,
|
let L = 0, A = 0, B = 0, W = 0;
|
||||||
A = 0,
|
|
||||||
B = 0,
|
|
||||||
W = 0;
|
|
||||||
|
|
||||||
for (const [type, w] of Object.entries(weights)) {
|
for (const [type, w] of Object.entries(weights)) {
|
||||||
const hex = hexByType[type] ?? fallbackHex;
|
const hex = hexByType[type] ?? fallbackHex;
|
||||||
if (!hex || w <= 0) continue;
|
if (!hex || w <= 0) continue;
|
||||||
const c = toOklab(parse(hex));
|
const c = toOklab(parse(hex));
|
||||||
if (!c) continue;
|
if (!c) continue;
|
||||||
L += c.l * w;
|
L += c.l * w; A += c.a * w; B += c.b * w; W += w;
|
||||||
A += c.a * w;
|
|
||||||
B += c.b * w;
|
|
||||||
W += w;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (W === 0) return { l: 0.5, a: 0, b: 0 };
|
if (W === 0) return { l: 0.5, a: 0, b: 0 };
|
||||||
@ -97,11 +78,7 @@ export async function generateArtworkColorsForArtwork(artworkId: string) {
|
|||||||
where: { id: artworkId },
|
where: { id: artworkId },
|
||||||
select: {
|
select: {
|
||||||
file: { select: { fileKey: true } },
|
file: { select: { fileKey: true } },
|
||||||
variants: {
|
variants: { where: { type: "original" }, select: { s3Key: true }, take: 1 },
|
||||||
where: { type: "original" },
|
|
||||||
select: { s3Key: true },
|
|
||||||
take: 1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (!artwork) throw new Error("Artwork not found");
|
if (!artwork) throw new Error("Artwork not found");
|
||||||
@ -123,9 +100,7 @@ export async function generateArtworkColorsForArtwork(artworkId: string) {
|
|||||||
for (const { type, hex } of vibrantHexes) {
|
for (const { type, hex } of vibrantHexes) {
|
||||||
if (!hex) continue;
|
if (!hex) continue;
|
||||||
|
|
||||||
const match = hex.match(/\w\w/g);
|
const [r, g, b] = hex.match(/\w\w/g)!.map((h) => parseInt(h, 16));
|
||||||
if (!match) continue;
|
|
||||||
const [r, g, b] = match.map((h) => parseInt(h, 16));
|
|
||||||
const name = generateColorName(hex);
|
const name = generateColorName(hex);
|
||||||
|
|
||||||
const color = await prisma.color.upsert({
|
const color = await prisma.color.upsert({
|
||||||
@ -142,14 +117,11 @@ export async function generateArtworkColorsForArtwork(artworkId: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hexByType: Record<string, string | undefined> = Object.fromEntries(
|
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 { l, a, b } = centroidFromPaletteHexes(hexByType);
|
||||||
const sortKey = hilbertIndex15(
|
const sortKey = hilbertIndex15(norm(a, A_MIN, A_MAX), norm(b, B_MIN, B_MAX));
|
||||||
norm(a, A_MIN, A_MAX),
|
|
||||||
norm(b, B_MIN, B_MAX),
|
|
||||||
);
|
|
||||||
|
|
||||||
await prisma.artwork.update({
|
await prisma.artwork.update({
|
||||||
where: { id: artworkId },
|
where: { id: artworkId },
|
||||||
@ -172,9 +144,6 @@ export async function generateArtworkColorsForArtwork(artworkId: string) {
|
|||||||
colorError: e instanceof Error ? e.message : "Color generation failed",
|
colorError: e instanceof Error ? e.message : "Color generation failed",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return {
|
return { ok: false as const, error: e instanceof Error ? e.message : "Color generation failed" };
|
||||||
ok: false as const,
|
|
||||||
error: e instanceof Error ? e.message : "Color generation failed",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import sharp from "sharp";
|
|||||||
|
|
||||||
const GALLERY_TARGET_SIZE = 300;
|
const GALLERY_TARGET_SIZE = 300;
|
||||||
|
|
||||||
// Generates a gallery-sized variant for a single artwork.
|
|
||||||
export async function generateGalleryVariant(
|
export async function generateGalleryVariant(
|
||||||
artworkId: string,
|
artworkId: string,
|
||||||
opts?: { force?: boolean },
|
opts?: { force?: boolean },
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Returns color swatches for a given artwork.
|
|
||||||
export async function getArtworkColors(artworkId: string) {
|
export async function getArtworkColors(artworkId: string) {
|
||||||
return prisma.artworkColor.findMany({
|
return prisma.artworkColor.findMany({
|
||||||
where: { artworkId },
|
where: { artworkId },
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Returns album/category options for artwork filters.
|
|
||||||
export async function getArtworkFilterOptions() {
|
export async function getArtworkFilterOptions() {
|
||||||
const [albums, categories] = await Promise.all([
|
const [albums, categories] = await Promise.all([
|
||||||
prisma.album.findMany({ select: { id: true, name: true }, orderBy: { name: "asc" } }),
|
prisma.album.findMany({ select: { id: true, name: true }, orderBy: { name: "asc" } }),
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
"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) {
|
export async function getSingleArtwork(id: string) {
|
||||||
return prisma.artwork.findUnique({
|
return await prisma.artwork.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
include: {
|
include: {
|
||||||
// album: true,
|
// album: true,
|
||||||
@ -18,7 +17,7 @@ export async function getSingleArtwork(id: string) {
|
|||||||
// sortContexts: true,
|
// sortContexts: true,
|
||||||
tags: true,
|
tags: true,
|
||||||
variants: true,
|
variants: true,
|
||||||
timelapse: true,
|
timelapse: true
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
@ -1,19 +1,15 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import type { Prisma } from "@/generated/prisma/client";
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { type ArtworkTableInput, artworkTableInputSchema, artworkTableOutputSchema } from "@/schemas/artworks/tableSchema";
|
import { 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 {
|
function triToBool(tri: "any" | "true" | "false"): boolean | undefined {
|
||||||
if (tri === "any") return undefined;
|
if (tri === "any") return undefined;
|
||||||
return tri === "true";
|
return tri === "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapSortingToOrderBy(
|
function mapSortingToOrderBy(sorting: ArtworkTableInput["sorting"]) {
|
||||||
sorting: ArtworkTableInput["sorting"]
|
const allowed: Record<string, (desc: boolean) => any> = {
|
||||||
): Prisma.ArtworkOrderByWithRelationInput[] {
|
|
||||||
const allowed: Record<string, (desc: boolean) => Prisma.ArtworkOrderByWithRelationInput> = {
|
|
||||||
createdAt: (desc) => ({ createdAt: desc ? "desc" : "asc" }),
|
createdAt: (desc) => ({ createdAt: desc ? "desc" : "asc" }),
|
||||||
updatedAt: (desc) => ({ updatedAt: desc ? "desc" : "asc" }),
|
updatedAt: (desc) => ({ updatedAt: desc ? "desc" : "asc" }),
|
||||||
sortIndex: (desc) => ({ sortIndex: desc ? "desc" : "asc" }),
|
sortIndex: (desc) => ({ sortIndex: desc ? "desc" : "asc" }),
|
||||||
@ -29,10 +25,9 @@ function mapSortingToOrderBy(
|
|||||||
tagsCount: (desc) => ({ tags: { _count: desc ? "desc" : "asc" } }),
|
tagsCount: (desc) => ({ tags: { _count: desc ? "desc" : "asc" } }),
|
||||||
};
|
};
|
||||||
|
|
||||||
const orderBy = sorting.flatMap((s) => {
|
const orderBy = sorting
|
||||||
const mapper = allowed[s.id];
|
.map((s) => allowed[s.id]?.(s.desc))
|
||||||
return mapper ? [mapper(s.desc)] : [];
|
.filter(Boolean);
|
||||||
});
|
|
||||||
|
|
||||||
orderBy.push({ id: "desc" });
|
orderBy.push({ id: "desc" });
|
||||||
return orderBy;
|
return orderBy;
|
||||||
@ -49,7 +44,7 @@ export async function getArtworksTablePage(input: unknown) {
|
|||||||
const nsfw = triToBool(filters.nsfw);
|
const nsfw = triToBool(filters.nsfw);
|
||||||
const needsWork = triToBool(filters.needsWork);
|
const needsWork = triToBool(filters.needsWork);
|
||||||
|
|
||||||
const where: Prisma.ArtworkWhereInput = {
|
const where: any = {
|
||||||
...(typeof published === "boolean" ? { published } : {}),
|
...(typeof published === "boolean" ? { published } : {}),
|
||||||
...(typeof nsfw === "boolean" ? { nsfw } : {}),
|
...(typeof nsfw === "boolean" ? { nsfw } : {}),
|
||||||
...(typeof needsWork === "boolean" ? { needsWork } : {}),
|
...(typeof needsWork === "boolean" ? { needsWork } : {}),
|
||||||
|
|||||||
@ -1,9 +1,13 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import type { GalleryVariantStats } from "@/types/Artwork";
|
|
||||||
|
|
||||||
// Returns counts for gallery variant presence.
|
export type GalleryVariantStats = {
|
||||||
|
total: number;
|
||||||
|
withGallery: number;
|
||||||
|
missing: number;
|
||||||
|
};
|
||||||
|
|
||||||
export async function getGalleryVariantStats(): Promise<GalleryVariantStats> {
|
export async function getGalleryVariantStats(): Promise<GalleryVariantStats> {
|
||||||
const [total, withGallery] = await Promise.all([
|
const [total, withGallery] = await Promise.all([
|
||||||
prisma.artwork.count(),
|
prisma.artwork.count(),
|
||||||
|
|||||||
@ -2,30 +2,25 @@
|
|||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { s3 } from "@/lib/s3";
|
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 { PutObjectCommand, DeleteObjectCommand } from "@aws-sdk/client-s3";
|
||||||
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
||||||
import { revalidatePath } from "next/cache";
|
import { revalidatePath } from "next/cache";
|
||||||
|
import { z } from "zod/v4";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
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
|
* Creates a presigned PUT url so the client can upload large timelapse videos directly to S3
|
||||||
* (avoids Next.js body-size/proxy limits).
|
* (avoids Next.js body-size/proxy limits).
|
||||||
*/
|
*/
|
||||||
export async function createArtworkTimelapseUpload(input: CreateArtworkTimelapseUploadInput) {
|
export async function createArtworkTimelapseUpload(input: z.infer<typeof createUploadSchema>) {
|
||||||
const { artworkId, fileName, mimeType, sizeBytes } =
|
const { artworkId, fileName, mimeType, sizeBytes } = createUploadSchema.parse(input);
|
||||||
createArtworkTimelapseUploadSchema.parse(input);
|
|
||||||
|
|
||||||
const ext = fileName.includes(".") ? fileName.split(".").pop() : undefined;
|
const ext = fileName.includes(".") ? fileName.split(".").pop() : undefined;
|
||||||
const suffix = ext ? `.${ext}` : "";
|
const suffix = ext ? `.${ext}` : "";
|
||||||
@ -46,10 +41,17 @@ export async function createArtworkTimelapseUpload(input: CreateArtworkTimelapse
|
|||||||
return { uploadUrl, s3Key, fileName, mimeType, sizeBytes };
|
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). */
|
/** Persist uploaded timelapse metadata in DB (upsert by artworkId). */
|
||||||
export async function confirmArtworkTimelapseUpload(input: ConfirmArtworkTimelapseUploadInput) {
|
export async function confirmArtworkTimelapseUpload(input: z.infer<typeof confirmSchema>) {
|
||||||
const { artworkId, s3Key, fileName, mimeType, sizeBytes } =
|
const { artworkId, s3Key, fileName, mimeType, sizeBytes } = confirmSchema.parse(input);
|
||||||
confirmArtworkTimelapseUploadSchema.parse(input);
|
|
||||||
|
|
||||||
// If an old timelapse exists, delete the old object so you don't leak storage.
|
// If an old timelapse exists, delete the old object so you don't leak storage.
|
||||||
const existing = await prisma.artworkTimelapse.findUnique({ where: { artworkId } });
|
const existing = await prisma.artworkTimelapse.findUnique({ where: { artworkId } });
|
||||||
@ -89,8 +91,13 @@ export async function confirmArtworkTimelapseUpload(input: ConfirmArtworkTimelap
|
|||||||
return { ok: true };
|
return { ok: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setArtworkTimelapseEnabled(input: SetArtworkTimelapseEnabledInput) {
|
const enabledSchema = z.object({
|
||||||
const { artworkId, enabled } = setArtworkTimelapseEnabledSchema.parse(input);
|
artworkId: z.string().min(1),
|
||||||
|
enabled: z.boolean(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function setArtworkTimelapseEnabled(input: z.infer<typeof enabledSchema>) {
|
||||||
|
const { artworkId, enabled } = enabledSchema.parse(input);
|
||||||
|
|
||||||
await prisma.artworkTimelapse.update({
|
await prisma.artworkTimelapse.update({
|
||||||
where: { artworkId },
|
where: { artworkId },
|
||||||
@ -101,8 +108,12 @@ export async function setArtworkTimelapseEnabled(input: SetArtworkTimelapseEnabl
|
|||||||
return { ok: true };
|
return { ok: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteArtworkTimelapse(input: DeleteArtworkTimelapseInput) {
|
const deleteSchema = z.object({
|
||||||
const { artworkId } = deleteArtworkTimelapseSchema.parse(input);
|
artworkId: z.string().min(1),
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function deleteArtworkTimelapse(input: z.infer<typeof deleteSchema>) {
|
||||||
|
const { artworkId } = deleteSchema.parse(input);
|
||||||
|
|
||||||
const existing = await prisma.artworkTimelapse.findUnique({ where: { artworkId } });
|
const existing = await prisma.artworkTimelapse.findUnique({ where: { artworkId } });
|
||||||
if (!existing) return { ok: true };
|
if (!existing) return { ok: true };
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { artworkSchema } from "@/schemas/artworks/imageSchema";
|
import { artworkSchema } from "@/schemas/artworks/imageSchema";
|
||||||
import { normalizeNames, slugify } from "@/utils/artworkHelpers";
|
import { normalizeNames, slugify } from "@/utils/artworkHelpers";
|
||||||
import type { z } from "zod/v4";
|
import { z } from "zod/v4";
|
||||||
|
|
||||||
// Updates an artwork and its tag/category relationships.
|
|
||||||
export async function updateArtwork(
|
export async function updateArtwork(
|
||||||
values: z.infer<typeof artworkSchema>,
|
values: z.infer<typeof artworkSchema>,
|
||||||
id: string
|
id: string
|
||||||
@ -37,11 +36,12 @@ export async function updateArtwork(
|
|||||||
const categoriesToCreate = normalizeNames(newCategoryNames);
|
const categoriesToCreate = normalizeNames(newCategoryNames);
|
||||||
|
|
||||||
const updatedArtwork = await prisma.$transaction(async (tx) => {
|
const updatedArtwork = await prisma.$transaction(async (tx) => {
|
||||||
if (setAsHeader) {
|
|
||||||
|
if(setAsHeader) {
|
||||||
await tx.artwork.updateMany({
|
await tx.artwork.updateMany({
|
||||||
where: { setAsHeader: true },
|
where: { setAsHeader: true },
|
||||||
data: { setAsHeader: false },
|
data: { setAsHeader: false },
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const tagsRelation =
|
const tagsRelation =
|
||||||
@ -73,7 +73,7 @@ export async function updateArtwork(
|
|||||||
: {};
|
: {};
|
||||||
|
|
||||||
return tx.artwork.update({
|
return tx.artwork.update({
|
||||||
where: { id },
|
where: { id: id },
|
||||||
data: {
|
data: {
|
||||||
name,
|
name,
|
||||||
slug: slugify(name),
|
slug: slugify(name),
|
||||||
|
|||||||
@ -2,25 +2,28 @@
|
|||||||
|
|
||||||
import { auth } from "@/lib/auth";
|
import { auth } from "@/lib/auth";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import type { RegisterFirstUserInput } from "@/schemas/auth";
|
import { z } from "zod/v4";
|
||||||
import { registerFirstUserSchema } from "@/schemas/auth";
|
|
||||||
import type { SignUpResponse } from "@/types/auth";
|
|
||||||
|
|
||||||
// Registers the very first user and upgrades them to admin.
|
const schema = z.object({
|
||||||
export async function registerFirstUser(input: RegisterFirstUserInput) {
|
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>) {
|
||||||
const count = await prisma.user.count();
|
const count = await prisma.user.count();
|
||||||
if (count !== 0) throw new Error("Registration is disabled.");
|
if (count !== 0) throw new Error("Registration is disabled.");
|
||||||
|
|
||||||
const { name, email, password } = registerFirstUserSchema.parse(input);
|
const { name, email, password } = schema.parse(input);
|
||||||
|
|
||||||
const res = (await auth.api.signUpEmail({
|
const res = await auth.api.signUpEmail({
|
||||||
body: { name, email, password },
|
body: { name, email, password },
|
||||||
})) as SignUpResponse;
|
});
|
||||||
|
|
||||||
const userId =
|
const userId =
|
||||||
res.user?.id ??
|
(res as any)?.user?.id ??
|
||||||
res.data?.user?.id ??
|
(res as any)?.data?.user?.id ??
|
||||||
res.data?.id;
|
(res as any)?.data?.id;
|
||||||
|
|
||||||
if (!userId) throw new Error("Signup failed: no user id returned.");
|
if (!userId) throw new Error("Signup failed: no user id returned.");
|
||||||
|
|
||||||
|
|||||||
@ -1,27 +1,25 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma"
|
||||||
import { categorySchema } from "@/schemas/artworks/categorySchema";
|
import { categorySchema } from "@/schemas/artworks/categorySchema"
|
||||||
import type * as z from "zod/v4";
|
|
||||||
|
|
||||||
// Creates a new artwork category.
|
export async function createCategory(formData: categorySchema) {
|
||||||
export async function createCategory(formData: z.infer<typeof categorySchema>) {
|
const parsed = categorySchema.safeParse(formData)
|
||||||
const parsed = categorySchema.safeParse(formData);
|
|
||||||
|
|
||||||
if (!parsed.success) {
|
if (!parsed.success) {
|
||||||
console.error("Validation failed", parsed.error);
|
console.error("Validation failed", parsed.error)
|
||||||
throw new Error("Invalid input");
|
throw new Error("Invalid input")
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = parsed.data;
|
const data = parsed.data
|
||||||
|
|
||||||
const created = await prisma.artCategory.create({
|
const created = await prisma.artCategory.create({
|
||||||
data: {
|
data: {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
slug: data.slug,
|
slug: data.slug,
|
||||||
description: data.description,
|
description: data.description
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
return created;
|
return created
|
||||||
}
|
}
|
||||||
@ -3,7 +3,6 @@
|
|||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { revalidatePath } from "next/cache";
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
// Deletes a category if it is not referenced by artworks or tags.
|
|
||||||
export async function deleteCategory(catId: string) {
|
export async function deleteCategory(catId: string) {
|
||||||
const cat = await prisma.artCategory.findUnique({
|
const cat = await prisma.artCategory.findUnique({
|
||||||
where: { id: catId },
|
where: { id: catId },
|
||||||
@ -11,8 +10,8 @@ export async function deleteCategory(catId: string) {
|
|||||||
id: true,
|
id: true,
|
||||||
_count: {
|
_count: {
|
||||||
select: {
|
select: {
|
||||||
tagLinks: true,
|
tags: true,
|
||||||
artworks: true,
|
artworks: true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -26,7 +25,7 @@ export async function deleteCategory(catId: string) {
|
|||||||
throw new Error("Cannot delete category: it is used by artworks.");
|
throw new Error("Cannot delete category: it is used by artworks.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cat._count.tagLinks > 0) {
|
if (cat._count.tags > 0) {
|
||||||
throw new Error("Cannot delete category: it is used by tags.");
|
throw new Error("Cannot delete category: it is used by tags.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,16 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma"
|
||||||
|
|
||||||
// Category data fetchers for admin pages.
|
|
||||||
export async function getCategoriesWithTags() {
|
export async function getCategoriesWithTags() {
|
||||||
return prisma.artCategory.findMany({
|
return await prisma.artCategory.findMany({ include: { tags: true }, orderBy: { sortIndex: "asc" } })
|
||||||
include: { tagLinks: { include: { tag: true } } },
|
|
||||||
orderBy: { sortIndex: "asc" },
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getCategoriesWithCount() {
|
export async function getCategoriesWithCount() {
|
||||||
return prisma.artCategory.findMany({
|
return await prisma.artCategory.findMany({
|
||||||
include: {
|
include: {
|
||||||
_count: { select: { artworks: true, tagLinks: true } },
|
_count: { select: { artworks: true, tags: true } },
|
||||||
},
|
},
|
||||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
@ -1,28 +1,27 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from '@/lib/prisma';
|
||||||
import { categorySchema } from "@/schemas/artworks/categorySchema";
|
import { categorySchema } from '@/schemas/artworks/categorySchema';
|
||||||
import type * as z from "zod/v4";
|
import { z } from 'zod/v4';
|
||||||
|
|
||||||
// Updates an artwork category by id.
|
|
||||||
export async function updateCategory(id: string, rawData: z.infer<typeof categorySchema>) {
|
export async function updateCategory(id: string, rawData: z.infer<typeof categorySchema>) {
|
||||||
const parsed = categorySchema.safeParse(rawData);
|
const parsed = categorySchema.safeParse(rawData)
|
||||||
|
|
||||||
if (!parsed.success) {
|
if (!parsed.success) {
|
||||||
console.error("Validation failed", parsed.error);
|
console.error("Validation failed", parsed.error)
|
||||||
throw new Error("Invalid input");
|
throw new Error("Invalid input")
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = parsed.data;
|
const data = parsed.data
|
||||||
|
|
||||||
const updated = await prisma.artCategory.update({
|
const updated = await prisma.artCategory.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
slug: data.slug,
|
slug: data.slug,
|
||||||
description: data.description,
|
description: data.description
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
return updated;
|
return updated
|
||||||
}
|
}
|
||||||
@ -1,9 +1,16 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import type { ArtworkColorStats } from "@/types/colors";
|
|
||||||
|
|
||||||
// Aggregates color-processing status counts for artworks.
|
export type ArtworkColorStats = {
|
||||||
|
total: number;
|
||||||
|
ready: number;
|
||||||
|
pending: number;
|
||||||
|
processing: number;
|
||||||
|
failed: number;
|
||||||
|
missingSortKey: number;
|
||||||
|
};
|
||||||
|
|
||||||
export async function getArtworkColorStats(): Promise<ArtworkColorStats> {
|
export async function getArtworkColorStats(): Promise<ArtworkColorStats> {
|
||||||
const [
|
const [
|
||||||
total,
|
total,
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import type { Prisma } from "@/generated/prisma/client";
|
import { Prisma } from "@/generated/prisma/client";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { generateArtworkColorsForArtwork } from "../artworks/generateArtworkColors";
|
import { generateArtworkColorsForArtwork } from "../artworks/generateArtworkColors";
|
||||||
import type { ProcessColorsResult } from "@/types/colors";
|
|
||||||
|
|
||||||
// Processes pending/failed artwork colors with a configurable batch size.
|
export type ProcessColorsResult = {
|
||||||
|
picked: number;
|
||||||
|
processed: number;
|
||||||
|
ok: number;
|
||||||
|
failed: number;
|
||||||
|
results: Array<{ artworkId: string; ok: boolean; error?: string }>;
|
||||||
|
};
|
||||||
|
|
||||||
export async function processPendingArtworkColors(args?: {
|
export async function processPendingArtworkColors(args?: {
|
||||||
limit?: number;
|
limit?: number;
|
||||||
includeFailed?: boolean;
|
includeFailed?: boolean;
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
"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 },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
"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,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
"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;
|
|
||||||
}
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
"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;
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
"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,7 +1,6 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { s3 } from "@/lib/s3";
|
import { s3 } from "@/lib/s3";
|
||||||
import type { CommissionExampleItem } from "@/types/commissions";
|
|
||||||
import {
|
import {
|
||||||
DeleteObjectCommand,
|
DeleteObjectCommand,
|
||||||
ListObjectsV2Command,
|
ListObjectsV2Command,
|
||||||
@ -10,6 +9,13 @@ import {
|
|||||||
|
|
||||||
const PREFIX = "commissions/examples/";
|
const PREFIX = "commissions/examples/";
|
||||||
|
|
||||||
|
export type CommissionExampleItem = {
|
||||||
|
key: string;
|
||||||
|
url: string;
|
||||||
|
size: number | null;
|
||||||
|
lastModified: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
function buildImageUrl(key: string) {
|
function buildImageUrl(key: string) {
|
||||||
return `/api/image/${encodeURI(key)}`;
|
return `/api/image/${encodeURI(key)}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
"use server";
|
'use server';
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Returns the latest active commission guidelines (markdown + example image).
|
|
||||||
export async function getActiveGuidelines(): Promise<{
|
export async function getActiveGuidelines(): Promise<{
|
||||||
markdown: string | null;
|
markdown: string | null;
|
||||||
exampleImageUrl: string | null;
|
exampleImageUrl: string | null;
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
"use server";
|
'use server';
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Deactivates existing guidelines and creates a new active version.
|
|
||||||
export async function saveGuidelines(markdown: string, exampleImageUrl: string | null) {
|
export async function saveGuidelines(markdown: string, exampleImageUrl: string | null) {
|
||||||
await prisma.commissionGuidelines.updateMany({
|
await prisma.commissionGuidelines.updateMany({
|
||||||
where: { isActive: true },
|
where: { isActive: true },
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { z } from "zod/v4";
|
import { z } from "zod";
|
||||||
|
|
||||||
// Deletes a commission request by id.
|
|
||||||
export async function deleteCommissionRequest(id: string) {
|
export async function deleteCommissionRequest(id: string) {
|
||||||
const parsed = z.string().min(1).parse(id);
|
const parsed = z.string().min(1).parse(id);
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { calculatePriceRange, type PriceSource } from "@/utils/commissionPricing";
|
import { calculatePriceRange, PriceSource } from "@/utils/commissionPricing";
|
||||||
|
|
||||||
// Loads a commission request with related data and computed price estimate.
|
|
||||||
export async function getCommissionRequestById(id: string) {
|
export async function getCommissionRequestById(id: string) {
|
||||||
const req = await prisma.commissionRequest.findUnique({
|
const req = await prisma.commissionRequest.findUnique({
|
||||||
where: { id },
|
where: { id },
|
||||||
|
|||||||
@ -1,24 +1,39 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import type { Prisma } from "@/generated/prisma/client";
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { commissionRequestTableRowSchema } from "@/schemas/commissions/requests";
|
import {
|
||||||
import type {
|
commissionRequestTableRowSchema,
|
||||||
CommissionRequestsTableFilters,
|
commissionStatusSchema,
|
||||||
CommissionRequestsTableSorting,
|
} from "@/schemas/commissions/requests";
|
||||||
} from "@/schemas/commissions/requestsTable";
|
import { z } from "zod";
|
||||||
import type { CursorPagination } from "@/types/pagination";
|
|
||||||
import { z } from "zod/v4";
|
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"),
|
||||||
|
});
|
||||||
|
|
||||||
// Builds a paginated, filtered, and sorted commission-requests table payload for the admin UI.
|
|
||||||
export async function getCommissionRequestsTablePage(input: {
|
export async function getCommissionRequestsTablePage(input: {
|
||||||
pagination: CursorPagination;
|
pagination: CursorPagination;
|
||||||
sorting: CommissionRequestsTableSorting;
|
sorting: z.infer<typeof sortingSchema>;
|
||||||
filters: CommissionRequestsTableFilters;
|
filters: z.infer<typeof filtersSchema>;
|
||||||
}) {
|
}) {
|
||||||
const { pagination, sorting, filters } = input;
|
const { pagination, sorting, filters } = input;
|
||||||
|
|
||||||
const where: Prisma.CommissionRequestWhereInput = {};
|
const where: any = {};
|
||||||
|
|
||||||
if (filters.q) {
|
if (filters.q) {
|
||||||
const q = filters.q.trim();
|
const q = filters.q.trim();
|
||||||
@ -45,7 +60,7 @@ export async function getCommissionRequestsTablePage(input: {
|
|||||||
|
|
||||||
// sorting
|
// sorting
|
||||||
const sort = sorting?.[0] ?? { id: "createdAt", desc: true };
|
const sort = sorting?.[0] ?? { id: "createdAt", desc: true };
|
||||||
const orderBy: Prisma.CommissionRequestOrderByWithRelationInput =
|
const orderBy: any =
|
||||||
sort.id === "createdAt"
|
sort.id === "createdAt"
|
||||||
? { createdAt: sort.desc ? "desc" : "asc" }
|
? { createdAt: sort.desc ? "desc" : "asc" }
|
||||||
: sort.id === "status"
|
: sort.id === "status"
|
||||||
@ -79,7 +94,7 @@ export async function getCommissionRequestsTablePage(input: {
|
|||||||
customerName: r.customerName,
|
customerName: r.customerName,
|
||||||
customerEmail: r.customerEmail,
|
customerEmail: r.customerEmail,
|
||||||
customerSocials: r.customerSocials ?? null,
|
customerSocials: r.customerSocials ?? null,
|
||||||
status: r.status,
|
status: r.status as any,
|
||||||
fileCount: r._count.files,
|
fileCount: r._count.files,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@ -2,9 +2,8 @@
|
|||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { commissionStatusSchema } from "@/schemas/commissions/requests";
|
import { commissionStatusSchema } from "@/schemas/commissions/requests";
|
||||||
import { z } from "zod/v4";
|
import { z } from "zod";
|
||||||
|
|
||||||
// Sets a commission request status (admin action).
|
|
||||||
export async function setCommissionRequestStatus(input: {
|
export async function setCommissionRequestStatus(input: {
|
||||||
id: string;
|
id: string;
|
||||||
status: z.infer<typeof commissionStatusSchema>;
|
status: z.infer<typeof commissionStatusSchema>;
|
||||||
|
|||||||
@ -1,14 +1,20 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import {
|
import { commissionStatusSchema } from "@/schemas/commissions/requests";
|
||||||
updateCommissionRequestSchema,
|
import { z } from "zod/v4";
|
||||||
} from "@/schemas/commissions/updateRequest";
|
|
||||||
import type { UpdateCommissionRequestInput } from "@/schemas/commissions/updateRequest";
|
|
||||||
|
|
||||||
// Updates editable fields on a commission request.
|
const updateSchema = z.object({
|
||||||
export async function updateCommissionRequest(input: UpdateCommissionRequestInput) {
|
id: z.string().min(1),
|
||||||
const data = updateCommissionRequestSchema.parse(input);
|
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);
|
||||||
|
|
||||||
await prisma.commissionRequest.update({
|
await prisma.commissionRequest.update({
|
||||||
where: { id: data.id },
|
where: { id: data.id },
|
||||||
|
|||||||
@ -1,18 +1,21 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { revalidatePath } from "next/cache";
|
import { revalidatePath } from "next/cache";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { COMMISSION_STATUSES } from "@/lib/commissions/kanban";
|
||||||
import {
|
import { prisma } from "@/lib/prisma"; // adjust to your prisma import
|
||||||
updateCommissionRequestStatusSchema,
|
// import { requireAdmin } from "@/lib/auth/requireAdmin"; // recommended if you have it
|
||||||
} from "@/schemas/commissions/updateRequestStatus";
|
|
||||||
import type { UpdateCommissionRequestStatusInput } from "@/schemas/commissions/updateRequestStatus";
|
|
||||||
|
|
||||||
// Updates a commission request status and revalidates the kanban page.
|
const schema = z.object({
|
||||||
export async function updateCommissionRequestStatus(
|
id: z.string().min(1),
|
||||||
input: UpdateCommissionRequestStatusInput
|
status: z.enum(COMMISSION_STATUSES),
|
||||||
) {
|
});
|
||||||
const { id, status } = updateCommissionRequestStatusSchema.parse(input);
|
|
||||||
|
export async function updateCommissionRequestStatus(input: z.infer<typeof schema>) {
|
||||||
|
// await requireAdmin(); // enforce auth/role check here
|
||||||
|
|
||||||
|
const { id, status } = schema.parse(input);
|
||||||
|
|
||||||
await prisma.commissionRequest.update({
|
await prisma.commissionRequest.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
@ -20,5 +23,5 @@ export async function updateCommissionRequestStatus(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// revalidate the board page so a refresh always reflects server truth
|
// revalidate the board page so a refresh always reflects server truth
|
||||||
revalidatePath("/commissions/kanban");
|
revalidatePath("/commissions/board");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,19 @@
|
|||||||
"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) {
|
export async function deleteCommissionType(typeId: string) {
|
||||||
|
|
||||||
await prisma.commissionTypeOption.deleteMany({
|
await prisma.commissionTypeOption.deleteMany({
|
||||||
where: { typeId },
|
where: { typeId },
|
||||||
});
|
})
|
||||||
|
|
||||||
await prisma.commissionTypeExtra.deleteMany({
|
await prisma.commissionTypeExtra.deleteMany({
|
||||||
where: { typeId },
|
where: { typeId },
|
||||||
});
|
})
|
||||||
|
|
||||||
await prisma.commissionType.delete({
|
await prisma.commissionType.delete({
|
||||||
where: { id: typeId },
|
where: { id: typeId },
|
||||||
});
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -4,9 +4,8 @@ import { prisma } from "@/lib/prisma";
|
|||||||
import { commissionExtraSchema } from "@/schemas/commissionType";
|
import { commissionExtraSchema } from "@/schemas/commissionType";
|
||||||
import { revalidatePath } from "next/cache";
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
const LIST_PATH = "/commissions/types/extras";
|
const LIST_PATH = "/commissions/extras";
|
||||||
|
|
||||||
// CRUD helpers for commission extras (admin-only pages).
|
|
||||||
export async function createCommissionExtra(input: unknown) {
|
export async function createCommissionExtra(input: unknown) {
|
||||||
const data = commissionExtraSchema.parse(input);
|
const data = commissionExtraSchema.parse(input);
|
||||||
const created = await prisma.commissionExtra.create({ data });
|
const created = await prisma.commissionExtra.create({ data });
|
||||||
@ -25,6 +24,7 @@ export async function deleteCommissionExtra(id: string) {
|
|||||||
// Optional safety:
|
// Optional safety:
|
||||||
// const used = await prisma.commissionTypeExtra.count({ where: { extraId: id } });
|
// const used = await prisma.commissionTypeExtra.count({ where: { extraId: id } });
|
||||||
// if (used > 0) throw new Error("Extra is linked to types.");
|
// if (used > 0) throw new Error("Extra is linked to types.");
|
||||||
await prisma.commissionExtra.delete({ where: { id } });
|
console.log("TBD");
|
||||||
revalidatePath(LIST_PATH);
|
// await prisma.commissionExtra.delete({ where: { id } });
|
||||||
|
// revalidatePath(LIST_PATH);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,65 +1,54 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma"
|
||||||
import { commissionTypeSchema } from "@/schemas/commissionType";
|
import { commissionTypeSchema } from "@/schemas/commissionType"
|
||||||
import type * as z from "zod/v4";
|
|
||||||
|
|
||||||
// Creates a commission option entry.
|
|
||||||
export async function createCommissionOption(data: { name: string }) {
|
export async function createCommissionOption(data: { name: string }) {
|
||||||
return prisma.commissionOption.create({
|
return await prisma.commissionOption.create({
|
||||||
data: {
|
data: {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a commission extra entry.
|
|
||||||
export async function createCommissionExtra(data: { name: string }) {
|
export async function createCommissionExtra(data: { name: string }) {
|
||||||
return prisma.commissionExtra.create({
|
return await prisma.commissionExtra.create({
|
||||||
data: {
|
data: {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
description: "",
|
description: "",
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a commission custom input entry.
|
|
||||||
export async function createCommissionCustomInput(data: {
|
export async function createCommissionCustomInput(data: {
|
||||||
name: string;
|
name: string
|
||||||
fieldId: string;
|
fieldId: string
|
||||||
}) {
|
}) {
|
||||||
return prisma.commissionCustomInput.create({
|
return await prisma.commissionCustomInput.create({
|
||||||
data: {
|
data: {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
fieldId: data.fieldId,
|
fieldId: data.fieldId,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a commission type with nested options/extras/custom inputs.
|
export async function createCommissionType(formData: commissionTypeSchema) {
|
||||||
export async function createCommissionType(
|
const parsed = commissionTypeSchema.safeParse(formData)
|
||||||
formData: z.infer<typeof commissionTypeSchema>
|
|
||||||
) {
|
|
||||||
const parsed = commissionTypeSchema.safeParse(formData);
|
|
||||||
|
|
||||||
if (!parsed.success) {
|
if (!parsed.success) {
|
||||||
console.error("Validation failed", parsed.error);
|
console.error("Validation failed", parsed.error)
|
||||||
throw new Error("Invalid input");
|
throw new Error("Invalid input")
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = parsed.data;
|
const data = parsed.data
|
||||||
|
|
||||||
const created = await prisma.commissionType.create({
|
const created = await prisma.commissionType.create({
|
||||||
data: {
|
data: {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
description: data.description,
|
description: data.description,
|
||||||
tags: data.tagIds?.length
|
|
||||||
? { connect: data.tagIds.map((id) => ({ id })) }
|
|
||||||
: undefined,
|
|
||||||
options: {
|
options: {
|
||||||
create:
|
create: data.options?.map((opt, index) => ({
|
||||||
data.options?.map((opt, index) => ({
|
|
||||||
option: { connect: { id: opt.optionId } },
|
option: { connect: { id: opt.optionId } },
|
||||||
price: opt.price,
|
price: opt.price,
|
||||||
pricePercent: opt.pricePercent,
|
pricePercent: opt.pricePercent,
|
||||||
@ -68,8 +57,7 @@ export async function createCommissionType(
|
|||||||
})) || [],
|
})) || [],
|
||||||
},
|
},
|
||||||
extras: {
|
extras: {
|
||||||
create:
|
create: data.extras?.map((ext, index) => ({
|
||||||
data.extras?.map((ext, index) => ({
|
|
||||||
extra: { connect: { id: ext.extraId } },
|
extra: { connect: { id: ext.extraId } },
|
||||||
price: ext.price,
|
price: ext.price,
|
||||||
pricePercent: ext.pricePercent,
|
pricePercent: ext.pricePercent,
|
||||||
@ -78,8 +66,7 @@ export async function createCommissionType(
|
|||||||
})) || [],
|
})) || [],
|
||||||
},
|
},
|
||||||
customInputs: {
|
customInputs: {
|
||||||
create:
|
create: data.customInputs?.map((c, index) => ({
|
||||||
data.customInputs?.map((c, index) => ({
|
|
||||||
customInput: { connect: { id: c.customInputId } },
|
customInput: { connect: { id: c.customInputId } },
|
||||||
label: c.label,
|
label: c.label,
|
||||||
inputType: c.inputType,
|
inputType: c.inputType,
|
||||||
@ -88,7 +75,7 @@ export async function createCommissionType(
|
|||||||
})) || [],
|
})) || [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
return created;
|
return created
|
||||||
}
|
}
|
||||||
@ -4,9 +4,13 @@ import { prisma } from "@/lib/prisma";
|
|||||||
import { commissionOptionSchema } from "@/schemas/commissionType";
|
import { commissionOptionSchema } from "@/schemas/commissionType";
|
||||||
import { revalidatePath } from "next/cache";
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
const LIST_PATH = "/commissions/types/options";
|
const LIST_PATH = "/commissions/options";
|
||||||
|
|
||||||
|
function toInt(v: string) {
|
||||||
|
const n = Number.parseInt(v, 10);
|
||||||
|
return Number.isFinite(n) ? n : 0;
|
||||||
|
}
|
||||||
|
|
||||||
// CRUD helpers for commission options (admin-only pages).
|
|
||||||
export async function createCommissionOption(input: unknown) {
|
export async function createCommissionOption(input: unknown) {
|
||||||
const data = commissionOptionSchema.parse(input);
|
const data = commissionOptionSchema.parse(input);
|
||||||
const created = await prisma.commissionOption.create({
|
const created = await prisma.commissionOption.create({
|
||||||
@ -33,6 +37,7 @@ export async function updateCommissionOption(id: string, input: unknown) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteCommissionOption(id: string) {
|
export async function deleteCommissionOption(id: string) {
|
||||||
await prisma.commissionOption.delete({ where: { id } });
|
console.log("TBD");
|
||||||
revalidatePath(LIST_PATH);
|
// await prisma.commissionOption.delete({ where: { id } });
|
||||||
|
// revalidatePath(LIST_PATH);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Updates sort order for commission types.
|
|
||||||
export async function updateCommissionTypeSortOrder(
|
export async function updateCommissionTypeSortOrder(
|
||||||
ordered: { id: string; sortIndex: number }[]
|
ordered: { id: string; sortIndex: number }[]
|
||||||
) {
|
) {
|
||||||
@ -11,7 +10,7 @@ export async function updateCommissionTypeSortOrder(
|
|||||||
where: { id },
|
where: { id },
|
||||||
data: { sortIndex },
|
data: { sortIndex },
|
||||||
})
|
})
|
||||||
);
|
)
|
||||||
|
|
||||||
await Promise.all(updates);
|
await Promise.all(updates)
|
||||||
}
|
}
|
||||||
@ -1,27 +1,20 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma"
|
||||||
import { commissionTypeSchema } from "@/schemas/commissionType";
|
import { commissionTypeSchema } from "@/schemas/commissionType"
|
||||||
import type * as z from "zod/v4";
|
import * as z from "zod/v4"
|
||||||
|
|
||||||
// Updates a commission type and resets related nested records.
|
|
||||||
export async function updateCommissionType(
|
export async function updateCommissionType(
|
||||||
id: string,
|
id: string,
|
||||||
rawData: z.infer<typeof commissionTypeSchema>
|
rawData: z.infer<typeof commissionTypeSchema>
|
||||||
) {
|
) {
|
||||||
const data = commissionTypeSchema.parse(rawData);
|
const data = commissionTypeSchema.parse(rawData)
|
||||||
|
|
||||||
const updated = await prisma.commissionType.update({
|
const updated = await prisma.commissionType.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
description: data.description,
|
description: data.description,
|
||||||
tags: data.tagIds
|
|
||||||
? {
|
|
||||||
set: [],
|
|
||||||
connect: data.tagIds.map((id) => ({ id })),
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
options: {
|
options: {
|
||||||
deleteMany: {},
|
deleteMany: {},
|
||||||
create: data.options?.map((opt, index) => ({
|
create: data.options?.map((opt, index) => ({
|
||||||
@ -44,8 +37,7 @@ export async function updateCommissionType(
|
|||||||
},
|
},
|
||||||
customInputs: {
|
customInputs: {
|
||||||
deleteMany: {},
|
deleteMany: {},
|
||||||
create:
|
create: data.customInputs?.map((c, index) => ({
|
||||||
data.customInputs?.map((c, index) => ({
|
|
||||||
customInput: { connect: { id: c.customInputId } },
|
customInput: { connect: { id: c.customInputId } },
|
||||||
label: c.label,
|
label: c.label,
|
||||||
inputType: c.inputType,
|
inputType: c.inputType,
|
||||||
@ -59,7 +51,7 @@ export async function updateCommissionType(
|
|||||||
extras: true,
|
extras: true,
|
||||||
customInputs: true,
|
customInputs: true,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
return updated;
|
return updated
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import type { CountRow } from "@/types/dashboard";
|
|
||||||
|
|
||||||
// Aggregates dashboard stats for admin overview cards and tables.
|
type CountRow<K extends string> = {
|
||||||
function toCountMapSafe<K extends string>(rows: Array<CountRow<K>>, key: K) {
|
[P in K]: string;
|
||||||
|
} & { _count: { _all: number } };
|
||||||
|
|
||||||
|
function toCountMapSafe(rows: any[], key: string) {
|
||||||
const out: Record<string, number> = {};
|
const out: Record<string, number> = {};
|
||||||
for (const r of rows) out[String(r[key])] = Number(r?._count?._all ?? 0);
|
for (const r of rows) out[String(r[key])] = Number(r?._count?._all ?? 0);
|
||||||
return out;
|
return out;
|
||||||
|
|||||||
@ -1,48 +1,46 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma"
|
||||||
import { tagSchema } from "@/schemas/artworks/tagSchema";
|
import { TagFormInput, 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) {
|
export async function createTag(formData: TagFormInput) {
|
||||||
const parsed = tagSchema.safeParse(formData);
|
const parsed = tagSchema.safeParse(formData)
|
||||||
|
|
||||||
if (!parsed.success) {
|
if (!parsed.success) {
|
||||||
console.error("Validation failed", parsed.error);
|
console.error("Validation failed", parsed.error)
|
||||||
throw new Error("Invalid input");
|
throw new Error("Invalid input")
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = parsed.data;
|
const data = parsed.data
|
||||||
|
|
||||||
const parentId = data.parentId ?? null;
|
const parentId = data.parentId ?? null;
|
||||||
const tagSlug = data.name.toLowerCase().replace(/\s+/g, "-");
|
const tagSlug = data.name.toLowerCase().replace(/\s+/g, "-");
|
||||||
|
|
||||||
const created = await prisma.$transaction(async (tx) => {
|
const created = await prisma.$transaction(async (tx) => {
|
||||||
const tag = await tx.tag.create({
|
const tag = await tx.artTag.create({
|
||||||
data: {
|
data: {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
slug: tagSlug,
|
slug: tagSlug,
|
||||||
description: data.description,
|
description: data.description,
|
||||||
isVisible: data.isVisible ?? true,
|
isParent: data.isParent,
|
||||||
|
showOnAnimalPage: data.showOnAnimalPage,
|
||||||
|
parentId
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (data.categoryIds) {
|
if (data.categoryIds) {
|
||||||
await tx.tagCategory.createMany({
|
await tx.artTag.update({
|
||||||
data: data.categoryIds.map((categoryId) => ({
|
where: { id: tag.id },
|
||||||
tagId: tag.id,
|
data: {
|
||||||
categoryId,
|
categories: {
|
||||||
isParent: data.isParent,
|
set: data.categoryIds.map(id => ({ id }))
|
||||||
showOnAnimalPage: data.showOnAnimalPage,
|
}
|
||||||
parentTagId: parentId,
|
}
|
||||||
})),
|
|
||||||
skipDuplicates: true,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.aliases && data.aliases.length > 0) {
|
if (data.aliases && data.aliases.length > 0) {
|
||||||
await tx.tagAlias.createMany({
|
await tx.artTagAlias.createMany({
|
||||||
data: data.aliases.map((alias) => ({
|
data: data.aliases.map((alias) => ({
|
||||||
tagId: tag.id,
|
tagId: tag.id,
|
||||||
alias,
|
alias,
|
||||||
@ -54,5 +52,5 @@ export async function createTag(formData: TagFormInput) {
|
|||||||
return tag;
|
return tag;
|
||||||
});
|
});
|
||||||
|
|
||||||
return created;
|
return created
|
||||||
}
|
}
|
||||||
@ -3,15 +3,15 @@
|
|||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { revalidatePath } from "next/cache";
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
// Deletes a tag if it has no artwork references or child tags.
|
|
||||||
export async function deleteTag(tagId: string) {
|
export async function deleteTag(tagId: string) {
|
||||||
const tag = await prisma.tag.findUnique({
|
const tag = await prisma.artTag.findUnique({
|
||||||
where: { id: tagId },
|
where: { id: tagId },
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
_count: {
|
_count: {
|
||||||
select: {
|
select: {
|
||||||
artworks: true,
|
artworks: true,
|
||||||
|
children: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -25,18 +25,13 @@ export async function deleteTag(tagId: string) {
|
|||||||
throw new Error("Cannot delete tag: it is used by artworks.");
|
throw new Error("Cannot delete tag: it is used by artworks.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentUsage = await prisma.tagCategory.count({
|
if (tag._count.children > 0) {
|
||||||
where: { parentTagId: tagId },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (parentUsage > 0) {
|
|
||||||
throw new Error("Cannot delete tag: it has child tags.");
|
throw new Error("Cannot delete tag: it has child tags.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await prisma.$transaction(async (tx) => {
|
await prisma.$transaction(async (tx) => {
|
||||||
await tx.tagAlias.deleteMany({ where: { tagId } });
|
await tx.artTagAlias.deleteMany({ where: { tagId } });
|
||||||
await tx.tagCategory.deleteMany({ where: { tagId } });
|
await tx.artTag.delete({ where: { id: tagId } });
|
||||||
await tx.tag.delete({ where: { id: tagId } });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
revalidatePath("/tags");
|
revalidatePath("/tags");
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma"
|
||||||
|
|
||||||
// Returns tags ordered by sortIndex.
|
|
||||||
export async function getTags() {
|
export async function getTags() {
|
||||||
return prisma.tag.findMany({ orderBy: { sortIndex: "asc" } });
|
return await prisma.artTag.findMany({ orderBy: { sortIndex: "asc" } })
|
||||||
}
|
}
|
||||||
@ -1,28 +1,21 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
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> {
|
export async function isDescendant(tagId: string, possibleAncestorId: string): Promise<boolean> {
|
||||||
// Walk upwards across any category hierarchy; if we hit tagId, it's a cycle.
|
// Walk upwards from possibleAncestorId; if we hit tagId, it's a cycle.
|
||||||
const visited = new Set<string>();
|
let current: string | null = possibleAncestorId;
|
||||||
const queue: string[] = [possibleAncestorId];
|
|
||||||
|
|
||||||
while (queue.length > 0) {
|
while (current) {
|
||||||
const current = queue.shift();
|
|
||||||
if (!current) continue;
|
|
||||||
if (current === tagId) return true;
|
if (current === tagId) return true;
|
||||||
if (visited.has(current)) continue;
|
|
||||||
visited.add(current);
|
|
||||||
|
|
||||||
const parents = await prisma.tagCategory.findMany({
|
const t: { parentId: string | null } | null =
|
||||||
where: { tagId: current, parentTagId: { not: null } },
|
await prisma.artTag.findUnique({
|
||||||
select: { parentTagId: true },
|
where: { id: current },
|
||||||
|
select: { parentId: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const p of parents) {
|
current = t?.parentId ?? null;
|
||||||
if (p.parentTagId) queue.push(p.parentTagId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -1,20 +1,18 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from '@/lib/prisma';
|
||||||
import { tagSchema } from "@/schemas/artworks/tagSchema";
|
import { TagFormInput, tagSchema } from '@/schemas/artworks/tagSchema';
|
||||||
import type { TagFormInput } from "@/schemas/artworks/tagSchema";
|
import { isDescendant } from './isDescendant';
|
||||||
import { isDescendant } from "./isDescendant";
|
|
||||||
|
|
||||||
// Updates a tag and its category/alias relationships.
|
|
||||||
export async function updateTag(id: string, rawData: TagFormInput) {
|
export async function updateTag(id: string, rawData: TagFormInput) {
|
||||||
const parsed = tagSchema.safeParse(rawData);
|
const parsed = tagSchema.safeParse(rawData)
|
||||||
|
|
||||||
if (!parsed.success) {
|
if (!parsed.success) {
|
||||||
console.error("Validation failed", parsed.error);
|
console.error("Validation failed", parsed.error)
|
||||||
throw new Error("Invalid input");
|
throw new Error("Invalid input")
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = parsed.data;
|
const data = parsed.data
|
||||||
|
|
||||||
const parentId = data.parentId ?? null;
|
const parentId = data.parentId ?? null;
|
||||||
const tagSlug = data.name.toLowerCase().replace(/\s+/g, "-");
|
const tagSlug = data.name.toLowerCase().replace(/\s+/g, "-");
|
||||||
@ -29,62 +27,22 @@ export async function updateTag(id: string, rawData: TagFormInput) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const updated = await prisma.$transaction(async (tx) => {
|
const updated = await prisma.$transaction(async (tx) => {
|
||||||
const tag = await tx.tag.update({
|
const tag = await tx.artTag.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
slug: tagSlug,
|
slug: tagSlug,
|
||||||
description: data.description,
|
description: data.description,
|
||||||
isVisible: data.isVisible ?? true,
|
isParent: data.isParent,
|
||||||
|
showOnAnimalPage: data.showOnAnimalPage,
|
||||||
|
parentId,
|
||||||
|
categories: data.categoryIds
|
||||||
|
? { set: data.categoryIds.map((cid) => ({ id: cid })) }
|
||||||
|
: undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (data.categoryIds) {
|
const existing = await tx.artTagAlias.findMany({
|
||||||
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 },
|
where: { tagId: id },
|
||||||
select: { id: true, alias: true },
|
select: { id: true, alias: true },
|
||||||
});
|
});
|
||||||
@ -98,13 +56,13 @@ export async function updateTag(id: string, rawData: TagFormInput) {
|
|||||||
.map((a) => a.id);
|
.map((a) => a.id);
|
||||||
|
|
||||||
if (toDeleteIds.length > 0) {
|
if (toDeleteIds.length > 0) {
|
||||||
await tx.tagAlias.deleteMany({
|
await tx.artTagAlias.deleteMany({
|
||||||
where: { id: { in: toDeleteIds } },
|
where: { id: { in: toDeleteIds } },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toCreate.length > 0) {
|
if (toCreate.length > 0) {
|
||||||
await tx.tagAlias.createMany({
|
await tx.artTagAlias.createMany({
|
||||||
data: toCreate.map((alias) => ({ tagId: id, alias })),
|
data: toCreate.map((alias) => ({ tagId: id, alias })),
|
||||||
skipDuplicates: true,
|
skipDuplicates: true,
|
||||||
});
|
});
|
||||||
@ -113,5 +71,5 @@ export async function updateTag(id: string, rawData: TagFormInput) {
|
|||||||
return tag;
|
return tag;
|
||||||
});
|
});
|
||||||
|
|
||||||
return updated;
|
return updated
|
||||||
}
|
}
|
||||||
@ -1,11 +1,10 @@
|
|||||||
"use server";
|
'use server';
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Returns the most recent Terms of Service markdown.
|
|
||||||
export async function getLatestTos(): Promise<string | null> {
|
export async function getLatestTos(): Promise<string | null> {
|
||||||
const tos = await prisma.termsOfService.findFirst({
|
const tos = await prisma.termsOfService.findFirst({
|
||||||
orderBy: { createdAt: "desc" },
|
orderBy: { createdAt: 'desc' },
|
||||||
});
|
});
|
||||||
return tos?.markdown ?? null;
|
return tos?.markdown ?? null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
"use server";
|
'use server';
|
||||||
|
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Saves a new Terms of Service version.
|
|
||||||
export async function saveTosAction(markdown: string) {
|
export async function saveTosAction(markdown: string) {
|
||||||
await prisma.termsOfService.create({
|
await prisma.termsOfService.create({
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
"use server";
|
|
||||||
|
|
||||||
import { createImageFromFile } from "./createImageFromFile";
|
import { createImageFromFile } from "./createImageFromFile";
|
||||||
import type { BulkResult } from "@/types/uploads";
|
|
||||||
|
|
||||||
// Bulk image upload server action used by the admin UI.
|
type BulkResult =
|
||||||
|
| { ok: true; artworkId: string; name: string }
|
||||||
|
| { ok: false; name: string; error: string };
|
||||||
|
|
||||||
export async function createImagesBulk(formData: FormData): Promise<BulkResult[]> {
|
export async function createImagesBulk(formData: FormData): Promise<BulkResult[]> {
|
||||||
const entries = formData.getAll("file");
|
const entries = formData.getAll("file");
|
||||||
const files = entries.filter((x): x is File => x instanceof File);
|
const files = entries.filter((x): x is File => x instanceof File);
|
||||||
|
|||||||
@ -1,12 +1,203 @@
|
|||||||
"use server";
|
"use server"
|
||||||
|
|
||||||
import type { fileUploadSchema } from "@/schemas/artworks/imageSchema";
|
import { fileUploadSchema } from "@/schemas/artworks/imageSchema";
|
||||||
import "dotenv/config";
|
import "dotenv/config";
|
||||||
import type { z } from "zod/v4";
|
import { z } from "zod/v4";
|
||||||
import { createImageFromFile } from "./createImageFromFile";
|
import { createImageFromFile } from "./createImageFromFile";
|
||||||
|
|
||||||
// Creates a single artwork image using the shared upload pipeline.
|
|
||||||
export async function createImage(values: z.infer<typeof fileUploadSchema>) {
|
export async function createImage(values: z.infer<typeof fileUploadSchema>) {
|
||||||
const imageFile = values.file[0];
|
const imageFile = values.file[0];
|
||||||
return createImageFromFile(imageFile, { colorMode: "inline" });
|
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 { v4 as uuidv4 } from "uuid";
|
||||||
import { generateArtworkColorsForArtwork } from "../artworks/generateArtworkColors";
|
import { generateArtworkColorsForArtwork } from "../artworks/generateArtworkColors";
|
||||||
|
|
||||||
// Upload pipeline that generates variants and metadata, then creates artwork records.
|
|
||||||
export async function createImageFromFile(
|
export async function createImageFromFile(
|
||||||
imageFile: File,
|
imageFile: File,
|
||||||
opts?: { originalName?: string; colorMode?: "inline" | "defer" | "off" },
|
opts?: { originalName?: string; colorMode?: "inline" | "defer" | "off" },
|
||||||
) {
|
) {
|
||||||
if (!(imageFile instanceof File)) {
|
if (!(imageFile instanceof File)) {
|
||||||
|
console.log("No image or invalid type");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ export async function createImageFromFile(
|
|||||||
name: fileName,
|
name: fileName,
|
||||||
fileKey,
|
fileKey,
|
||||||
originalFile: fileName,
|
originalFile: fileName,
|
||||||
uploadDate: new Date(),
|
uploadDate: lastModified,
|
||||||
fileType: realFileType,
|
fileType: realFileType,
|
||||||
fileSize,
|
fileSize,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,20 +2,24 @@
|
|||||||
|
|
||||||
import { auth } from "@/lib/auth";
|
import { auth } from "@/lib/auth";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import type { SessionWithRole } from "@/types/auth";
|
import { z } from "zod/v4";
|
||||||
import { createUserSchema } from "@/schemas/users";
|
|
||||||
import type { CreateUserInput } from "@/schemas/users";
|
|
||||||
|
|
||||||
// Creates a new user account (admin-only).
|
const schema = z.object({
|
||||||
export async function createUser(input: CreateUserInput) {
|
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>) {
|
||||||
const session = await auth.api.getSession({ headers: await headers() });
|
const session = await auth.api.getSession({ headers: await headers() });
|
||||||
const role = (session as SessionWithRole)?.user?.role;
|
const role = (session as any)?.user?.role;
|
||||||
|
|
||||||
if (!session || role !== "admin") {
|
if (!session || role !== "admin") {
|
||||||
throw new Error("Forbidden");
|
throw new Error("Forbidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = createUserSchema.parse(input);
|
const data = schema.parse(input);
|
||||||
|
|
||||||
return auth.api.createUser({
|
return auth.api.createUser({
|
||||||
body: {
|
body: {
|
||||||
|
|||||||
@ -4,15 +4,13 @@ import { auth } from "@/lib/auth";
|
|||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import { z } from "zod/v4";
|
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) {
|
export async function deleteUser(id: string) {
|
||||||
const userId = z.string().min(1).parse(id);
|
const userId = z.string().min(1).parse(id);
|
||||||
|
|
||||||
const session = await auth.api.getSession({ headers: await headers() });
|
const session = await auth.api.getSession({ headers: await headers() });
|
||||||
const role = (session as SessionWithRole)?.user?.role;
|
const role = (session as any)?.user?.role as string | undefined;
|
||||||
const currentUserId = (session as SessionWithRole)?.user?.id;
|
const currentUserId = (session as any)?.user?.id as string | undefined;
|
||||||
|
|
||||||
if (!session || role !== "admin") throw new Error("Forbidden");
|
if (!session || role !== "admin") throw new Error("Forbidden");
|
||||||
if (!currentUserId) throw new Error("Session missing user id");
|
if (!currentUserId) throw new Error("Session missing user id");
|
||||||
@ -42,5 +40,5 @@ async function await_attachTarget(userId: string) {
|
|||||||
select: { id: true, role: true },
|
select: { id: true, role: true },
|
||||||
});
|
});
|
||||||
if (!target) throw new Error("User not found.");
|
if (!target) throw new Error("User not found.");
|
||||||
return target;
|
return target as { id: string; role: "admin" | "user" };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,14 +2,21 @@
|
|||||||
|
|
||||||
import { auth } from "@/lib/auth";
|
import { auth } from "@/lib/auth";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import type { SessionWithRole } from "@/types/auth";
|
|
||||||
import type { UserRole, UsersListRow } from "@/types/users";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
// Returns all users for the admin users table.
|
export type UsersListRow = {
|
||||||
|
id: string;
|
||||||
|
name: string | null;
|
||||||
|
email: string;
|
||||||
|
role: "admin" | "user";
|
||||||
|
emailVerified: boolean;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
};
|
||||||
|
|
||||||
export async function getUsers(): Promise<UsersListRow[]> {
|
export async function getUsers(): Promise<UsersListRow[]> {
|
||||||
const session = await auth.api.getSession({ headers: await headers() });
|
const session = await auth.api.getSession({ headers: await headers() });
|
||||||
const role = (session as SessionWithRole)?.user?.role;
|
const role = (session as any)?.user?.role as string | undefined;
|
||||||
|
|
||||||
if (!session || role !== "admin") {
|
if (!session || role !== "admin") {
|
||||||
throw new Error("Forbidden");
|
throw new Error("Forbidden");
|
||||||
@ -28,16 +35,5 @@ export async function getUsers(): Promise<UsersListRow[]> {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return rows.map((r) => {
|
return rows as UsersListRow[];
|
||||||
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,20 +2,21 @@
|
|||||||
|
|
||||||
import { auth } from "@/lib/auth";
|
import { auth } from "@/lib/auth";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import type { SessionWithRole } from "@/types/auth";
|
import { z } from "zod/v4";
|
||||||
import { resendVerificationSchema } from "@/schemas/users";
|
|
||||||
import type { ResendVerificationInput } from "@/schemas/users";
|
|
||||||
|
|
||||||
// Resends a verification email for a user (admin-only).
|
const schema = z.object({
|
||||||
export async function resendVerification(input: ResendVerificationInput) {
|
email: z.string().email(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function resendVerification(input: z.infer<typeof schema>) {
|
||||||
const session = await auth.api.getSession({ headers: await headers() });
|
const session = await auth.api.getSession({ headers: await headers() });
|
||||||
const role = (session as SessionWithRole)?.user?.role;
|
const role = (session as any)?.user?.role as string | undefined;
|
||||||
if (!session || role !== "admin") throw new Error("Forbidden");
|
if (!session || role !== "admin") throw new Error("Forbidden");
|
||||||
|
|
||||||
const { email } = resendVerificationSchema.parse(input);
|
const { email } = schema.parse(input);
|
||||||
|
|
||||||
// Uses the public auth route (same origin)
|
// Uses the public auth route (same origin)
|
||||||
const res = await fetch(`${process.env.BETTER_AUTH_URL}/api/auth/send-verification-email`, {
|
const res = await fetch("http://localhost/api/auth/send-verification-email", {
|
||||||
// NOTE: In production, you should use an absolute URL from env, or use authClient.
|
// 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.
|
// This is kept minimal; if you want, I'll refactor to authClient to avoid hostname concerns.
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import ArtworkVariants from "@/components/artworks/single/ArtworkVariants";
|
|||||||
import DeleteArtworkButton from "@/components/artworks/single/DeleteArtworkButton";
|
import DeleteArtworkButton from "@/components/artworks/single/DeleteArtworkButton";
|
||||||
import EditArtworkForm from "@/components/artworks/single/EditArtworkForm";
|
import EditArtworkForm from "@/components/artworks/single/EditArtworkForm";
|
||||||
|
|
||||||
// Single artwork edit page.
|
|
||||||
export default async function ArtworkSinglePage({ params }: { params: Promise<{ id: string }> }) {
|
export default async function ArtworkSinglePage({ params }: { params: Promise<{ id: string }> }) {
|
||||||
const { id } = await params;
|
const { id } = await params;
|
||||||
|
|
||||||
@ -17,30 +16,30 @@ export default async function ArtworkSinglePage({ params }: { params: Promise<{
|
|||||||
const categories = await getCategoriesWithTags();
|
const categories = await getCategoriesWithTags();
|
||||||
const tags = await getTags();
|
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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-bold mb-4">Edit artwork</h1>
|
<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="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||||
<div className="space-y-6">
|
|
||||||
<EditArtworkForm artwork={item} tags={tags} categories={categories} />
|
|
||||||
<div>
|
<div>
|
||||||
<DeleteArtworkButton artworkId={item.id} />
|
{item ? <EditArtworkForm artwork={item} tags={tags} categories={categories} /> : 'Artwork not found...'}
|
||||||
|
<div className="mt-6">
|
||||||
|
{item && <DeleteArtworkButton artworkId={item.id} />}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<ArtworkTimelapse artworkId={item.id} timelapse={item.timelapse} />
|
{item && <ArtworkVariants artworkId={item.id} variants={item.variants} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<ArtworkColors colors={item.colors} artworkId={item.id} />
|
{item && <ArtworkTimelapse artworkId={item.id} timelapse={item.timelapse} />}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<ArtworkDetails artwork={item} />
|
{item && <ArtworkColors colors={item.colors} artworkId={item.id} />}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<ArtworkVariants artworkId={item.id} variants={item.variants} />
|
{item && <ArtworkDetails artwork={item} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,13 +1,94 @@
|
|||||||
import { ArtworkColorProcessor } from "@/components/artworks/ArtworkColorProcessor";
|
import { ArtworkColorProcessor } from "@/components/artworks/ArtworkColorProcessor";
|
||||||
|
import { ArtworkGalleryVariantProcessor } from "@/components/artworks/ArtworkGalleryVariantProcessor";
|
||||||
import { ArtworksTable } from "@/components/artworks/ArtworksTable";
|
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 (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<h1 className="text-2xl font-bold">Artworks</h1>
|
<h1 className="text-2xl font-bold">Artworks</h1>
|
||||||
|
{/* <ProcessArtworkColorsButton /> */}
|
||||||
<ArtworkColorProcessor />
|
<ArtworkColorProcessor />
|
||||||
|
<ArtworkGalleryVariantProcessor />
|
||||||
<ArtworksTable />
|
<ArtworksTable />
|
||||||
</div>
|
</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,14 +1,13 @@
|
|||||||
import EditCategoryForm from "@/components/categories/EditCategoryForm";
|
import EditCategoryForm from "@/components/categories/EditCategoryForm";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Edit category page.
|
|
||||||
export default async function PortfolioCategoriesEditPage({ params }: { params: { id: string } }) {
|
export default async function PortfolioCategoriesEditPage({ params }: { params: { id: string } }) {
|
||||||
const { id } = await params;
|
const { id } = await params;
|
||||||
const category = await prisma.artCategory.findUnique({
|
const category = await prisma.artCategory.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id,
|
id,
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import NewCategoryForm from "@/components/categories/NewCategoryForm";
|
import NewCategoryForm from "@/components/categories/NewCategoryForm";
|
||||||
|
|
||||||
// Create a new category page.
|
|
||||||
export default function PortfolioCategoriesNewPage() {
|
export default function PortfolioCategoriesNewPage() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import { PlusCircleIcon } from "lucide-react";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
|
|
||||||
// Admin categories management page.
|
|
||||||
export default async function CategoriesPage() {
|
export default async function CategoriesPage() {
|
||||||
const items = await getCategoriesWithCount();
|
const items = await getCategoriesWithCount();
|
||||||
|
|
||||||
@ -12,10 +11,7 @@ export default async function CategoriesPage() {
|
|||||||
<div>
|
<div>
|
||||||
<div className="flex gap-4 justify-between pb-8">
|
<div className="flex gap-4 justify-between pb-8">
|
||||||
<h1 className="text-2xl font-bold mb-4">Art Categories</h1>
|
<h1 className="text-2xl font-bold mb-4">Art Categories</h1>
|
||||||
<Link
|
<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">
|
||||||
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
|
<PlusCircleIcon className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all text-primary-foreground" /> Add new category
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,44 +0,0 @@
|
|||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
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,7 +2,6 @@ import { listCommissionExamples } from "@/actions/commissions/examples";
|
|||||||
import { getActiveGuidelines } from "@/actions/commissions/guidelines/getGuidelines";
|
import { getActiveGuidelines } from "@/actions/commissions/guidelines/getGuidelines";
|
||||||
import GuidelinesEditor from "@/components/commissions/guidelines/Editor";
|
import GuidelinesEditor from "@/components/commissions/guidelines/Editor";
|
||||||
|
|
||||||
// Admin page for editing commission guidelines.
|
|
||||||
export default async function CommissionGuidelinesPage() {
|
export default async function CommissionGuidelinesPage() {
|
||||||
const [{ markdown, exampleImageUrl }, examples] = await Promise.all([
|
const [{ markdown, exampleImageUrl }, examples] = await Promise.all([
|
||||||
getActiveGuidelines(),
|
getActiveGuidelines(),
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import { prisma } from "@/lib/prisma";
|
|||||||
|
|
||||||
import type { BoardItem, ColumnsState } from "@/types/Board";
|
import type { BoardItem, ColumnsState } from "@/types/Board";
|
||||||
|
|
||||||
// Admin kanban page for commission requests.
|
|
||||||
export default async function CommissionsBoardPage() {
|
export default async function CommissionsBoardPage() {
|
||||||
const requests = await prisma.commissionRequest.findMany({
|
const requests = await prisma.commissionRequest.findMany({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { getCommissionRequestById } from "@/actions/commissions/requests/getComm
|
|||||||
import { CommissionRequestEditor } from "@/components/commissions/requests/CommissionRequestEditor";
|
import { CommissionRequestEditor } from "@/components/commissions/requests/CommissionRequestEditor";
|
||||||
import { notFound } from "next/navigation";
|
import { notFound } from "next/navigation";
|
||||||
|
|
||||||
// Admin page for editing a single commission request.
|
|
||||||
export default async function CommissionRequestPage({
|
export default async function CommissionRequestPage({
|
||||||
params,
|
params,
|
||||||
}: {
|
}: {
|
||||||
@ -21,7 +20,7 @@ export default async function CommissionRequestPage({
|
|||||||
Submitted: {new Date(request.createdAt).toLocaleString()} · ID: {request.id}
|
Submitted: {new Date(request.createdAt).toLocaleString()} · ID: {request.id}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<CommissionRequestEditor request={request} />
|
<CommissionRequestEditor request={request as any} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import RequestsTable from "@/components/commissions/requests/RequestsTable";
|
import RequestsTable from "@/components/commissions/requests/RequestsTable";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Server-rendered commissions list page.
|
|
||||||
export default async function CommissionPage() {
|
export default async function CommissionPage() {
|
||||||
const items = await prisma.commissionRequest.findMany({
|
const items = await prisma.commissionRequest.findMany({
|
||||||
include: {
|
include: {
|
||||||
@ -16,7 +15,7 @@ export default async function CommissionPage() {
|
|||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-semibold">Commission Requests</h1>
|
<h1 className="text-2xl font-semibold">Commission Requests</h1>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
List of all incoming requests via website.
|
List of all incomming requests via website.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<RequestsTable requests={items} />
|
<RequestsTable requests={items} />
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import EditTypeForm from "@/components/commissions/types/EditTypeForm";
|
import EditTypeForm from "@/components/commissions/types/EditTypeForm";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Edit commission type page.
|
|
||||||
export default async function CommissionTypesEditPage({ params }: { params: { id: string } }) {
|
export default async function CommissionTypesEditPage({ params }: { params: { id: string } }) {
|
||||||
const { id } = await params;
|
const { id } = await params;
|
||||||
const commissionType = await prisma.commissionType.findUnique({
|
const commissionType = await prisma.commissionType.findUnique({
|
||||||
@ -12,21 +11,20 @@ export default async function CommissionTypesEditPage({ params }: { params: { id
|
|||||||
options: { include: { option: true }, orderBy: { sortIndex: "asc" } },
|
options: { include: { option: true }, orderBy: { sortIndex: "asc" } },
|
||||||
extras: { include: { extra: true }, orderBy: { sortIndex: "asc" } },
|
extras: { include: { extra: true }, orderBy: { sortIndex: "asc" } },
|
||||||
customInputs: { include: { customInput: 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({
|
const options = await prisma.commissionOption.findMany({
|
||||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||||
});
|
});
|
||||||
const extras = await prisma.commissionExtra.findMany({
|
const extras = await prisma.commissionExtra.findMany({
|
||||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||||
});
|
})
|
||||||
|
// const customInputs = await prisma.commissionCustomInput.findMany({
|
||||||
|
// orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||||
|
// })
|
||||||
|
|
||||||
if (!commissionType) {
|
if (!commissionType) {
|
||||||
return <div>Type not found</div>;
|
return <div>Type not found</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -34,12 +32,7 @@ export default async function CommissionTypesEditPage({ params }: { params: { id
|
|||||||
<div className="flex gap-4 justify-between pb-8">
|
<div className="flex gap-4 justify-between pb-8">
|
||||||
<h1 className="text-2xl font-bold mb-4">Edit Commission Type</h1>
|
<h1 className="text-2xl font-bold mb-4">Edit Commission Type</h1>
|
||||||
</div>
|
</div>
|
||||||
<EditTypeForm
|
<EditTypeForm type={commissionType} allOptions={options} allExtras={extras} />
|
||||||
type={commissionType}
|
|
||||||
allOptions={options}
|
|
||||||
allExtras={extras}
|
|
||||||
allTags={tags}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1,7 +1,6 @@
|
|||||||
import { ExtraListClient } from "@/components/commissions/extras/ExtraListClient";
|
import { ExtraListClient } from "@/components/commissions/extras/ExtraListClient";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Admin page for managing commission extras.
|
|
||||||
export default async function CommissionTypesExtrasPage() {
|
export default async function CommissionTypesExtrasPage() {
|
||||||
const extras = await prisma.commissionExtra.findMany({
|
const extras = await prisma.commissionExtra.findMany({
|
||||||
orderBy: [{ createdAt: "asc" }, { name: "asc" }],
|
orderBy: [{ createdAt: "asc" }, { name: "asc" }],
|
||||||
|
|||||||
@ -1,32 +1,24 @@
|
|||||||
import NewTypeForm from "@/components/commissions/types/NewTypeForm";
|
import NewTypeForm from "@/components/commissions/types/NewTypeForm";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Create new commission type page.
|
|
||||||
export default async function CommissionTypesNewPage() {
|
export default async function CommissionTypesNewPage() {
|
||||||
const tags = await prisma.tag.findMany({
|
|
||||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
|
||||||
});
|
|
||||||
const options = await prisma.commissionOption.findMany({
|
const options = await prisma.commissionOption.findMany({
|
||||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||||
});
|
});
|
||||||
const extras = await prisma.commissionExtra.findMany({
|
const extras = await prisma.commissionExtra.findMany({
|
||||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||||
});
|
})
|
||||||
const customInputs = await prisma.commissionCustomInput.findMany({
|
const customInputs = await prisma.commissionCustomInput.findMany({
|
||||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
||||||
});
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="flex gap-4 justify-between pb-8">
|
<div className="flex gap-4 justify-between pb-8">
|
||||||
<h1 className="text-2xl font-bold mb-4">New Commission Type</h1>
|
<h1 className="text-2xl font-bold mb-4">New Commission Type</h1>
|
||||||
</div>
|
</div>
|
||||||
<NewTypeForm
|
<NewTypeForm options={options} extras={extras} customInputs={customInputs} />
|
||||||
options={options}
|
|
||||||
extras={extras}
|
|
||||||
customInputs={customInputs}
|
|
||||||
tags={tags}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1,7 +1,6 @@
|
|||||||
import { OptionsListClient } from "@/components/commissions/options/OptionsListClient";
|
import { OptionsListClient } from "@/components/commissions/options/OptionsListClient";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Admin page for managing commission options.
|
|
||||||
export default async function CommissionTypesOptionsPage() {
|
export default async function CommissionTypesOptionsPage() {
|
||||||
const options = await prisma.commissionOption.findMany({
|
const options = await prisma.commissionOption.findMany({
|
||||||
orderBy: [{ createdAt: "asc" }, { name: "asc" }],
|
orderBy: [{ createdAt: "asc" }, { name: "asc" }],
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import { prisma } from "@/lib/prisma";
|
|||||||
import { PlusCircleIcon } from "lucide-react";
|
import { PlusCircleIcon } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
// Commission types list page.
|
|
||||||
export default async function CommissionTypesPage() {
|
export default async function CommissionTypesPage() {
|
||||||
const types = await prisma.commissionType.findMany({
|
const types = await prisma.commissionType.findMany({
|
||||||
include: {
|
include: {
|
||||||
@ -18,18 +17,11 @@ export default async function CommissionTypesPage() {
|
|||||||
<div>
|
<div>
|
||||||
<div className="flex gap-4 justify-between pb-8">
|
<div className="flex gap-4 justify-between pb-8">
|
||||||
<h1 className="text-2xl font-bold mb-4">Commission Types</h1>
|
<h1 className="text-2xl font-bold mb-4">Commission Types</h1>
|
||||||
<Link
|
<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">
|
||||||
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
|
<PlusCircleIcon className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all text-primary-foreground" /> Add new Type
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
{types && types.length > 0 ? (
|
{types && types.length > 0 ? <ListTypes types={types} /> : <p className="text-muted-foreground italic">No types found.</p>}
|
||||||
<ListTypes types={types} />
|
|
||||||
) : (
|
|
||||||
<p className="text-muted-foreground italic">No types found.</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -3,15 +3,25 @@ import Footer from "@/components/global/Footer";
|
|||||||
import MobileSidebar from "@/components/global/MobileSidebar";
|
import MobileSidebar from "@/components/global/MobileSidebar";
|
||||||
import ModeToggle from "@/components/global/ModeToggle";
|
import ModeToggle from "@/components/global/ModeToggle";
|
||||||
import Sidebar from "@/components/global/Sidebar";
|
import Sidebar from "@/components/global/Sidebar";
|
||||||
import type { ReactNode } from "react";
|
|
||||||
|
|
||||||
// Main admin layout with sidebar, header actions, and footer.
|
|
||||||
export default function AdminLayout({
|
export default function AdminLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
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="min-h-screen w-full">
|
||||||
<div className="flex 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">
|
<aside className="hidden md:flex md:w-64 md:flex-col md:border-r md:bg-background">
|
||||||
|
|||||||
@ -6,7 +6,14 @@ import { StatusPill } from "@/components/home/StatusPill";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
|
||||||
// Admin dashboard summary page.
|
function fmtDate(d: Date) {
|
||||||
|
return new Intl.DateTimeFormat("de-DE", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
}).format(d);
|
||||||
|
}
|
||||||
|
|
||||||
export default async function HomePage() {
|
export default async function HomePage() {
|
||||||
const data = await getAdminDashboard();
|
const data = await getAdminDashboard();
|
||||||
|
|
||||||
@ -21,6 +28,9 @@ export default async function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{/* <Button asChild variant="secondary">
|
||||||
|
<Link href="/artworks/new">Add artwork</Link>
|
||||||
|
</Button> */}
|
||||||
<Button asChild>
|
<Button asChild>
|
||||||
<Link href="/commissions/requests">Review requests</Link>
|
<Link href="/commissions/requests">Review requests</Link>
|
||||||
</Button>
|
</Button>
|
||||||
@ -70,6 +80,48 @@ export default async function HomePage() {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="grid gap-4 lg:grid-cols-3">
|
<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 */}
|
{/* Commissions status */}
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
@ -101,6 +153,84 @@ export default async function HomePage() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</section>
|
</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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,46 +1,25 @@
|
|||||||
import EditTagForm from "@/components/tags/EditTagForm";
|
import EditTagForm from "@/components/tags/EditTagForm";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Edit tag page.
|
|
||||||
export default async function PortfolioTagsEditPage({ params }: { params: { id: string } }) {
|
export default async function PortfolioTagsEditPage({ params }: { params: { id: string } }) {
|
||||||
const { id } = await params;
|
const { id } = await params;
|
||||||
const tag = await prisma.tag.findUnique({
|
const tag = await prisma.artTag.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
include: {
|
include: {
|
||||||
categoryLinks: {
|
categories: true,
|
||||||
include: {
|
|
||||||
category: true,
|
|
||||||
parentTag: { select: { id: true, name: true } },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
aliases: true
|
aliases: true
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
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;
|
})
|
||||||
|
|
||||||
|
const categories = await prisma.artCategory.findMany({ include: { tags: true }, orderBy: { sortIndex: "asc" } });
|
||||||
|
const tags = await prisma.artTag.findMany({ where: { isParent: true }, orderBy: { sortIndex: "asc" } });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-bold mb-4">Edit Tag</h1>
|
<h1 className="text-2xl font-bold mb-4">Edit Tag</h1>
|
||||||
{tagWithMeta && <EditTagForm tag={tagWithMeta} categories={categories} allTags={tags} />}
|
{tag && <EditTagForm tag={tag} categories={categories} allTags={tags} />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1,13 +1,9 @@
|
|||||||
import NewTagForm from "@/components/tags/NewTagForm";
|
import NewTagForm from "@/components/tags/NewTagForm";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
// Create a new tag page.
|
|
||||||
export default async function PortfolioTagsNewPage() {
|
export default async function PortfolioTagsNewPage() {
|
||||||
const categories = await prisma.artCategory.findMany({
|
const categories = await prisma.artCategory.findMany({ include: { tags: true }, orderBy: { sortIndex: "asc" } });
|
||||||
include: { tagLinks: true },
|
const tags = await prisma.artTag.findMany({ where: { isParent: true }, orderBy: { sortIndex: "asc" } });
|
||||||
orderBy: { sortIndex: "asc" },
|
|
||||||
});
|
|
||||||
const tags = await prisma.tag.findMany({ orderBy: { sortIndex: "asc" } });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -4,63 +4,39 @@ import { prisma } from "@/lib/prisma";
|
|||||||
import { PlusCircleIcon } from "lucide-react";
|
import { PlusCircleIcon } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
// Admin tags management page.
|
|
||||||
export default async function ArtTagsPage() {
|
export default async function ArtTagsPage() {
|
||||||
const items = await prisma.tag.findMany({
|
const items = await prisma.artTag.findMany({
|
||||||
include: {
|
include: {
|
||||||
|
parent: { select: { id: true, name: true } },
|
||||||
aliases: { select: { alias: true } },
|
aliases: { select: { alias: true } },
|
||||||
categoryLinks: {
|
categories: { select: { id: true, name: true } },
|
||||||
include: {
|
|
||||||
category: { select: { id: true, name: true } },
|
|
||||||
parentTag: { select: { id: true, name: true } },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
_count: { select: { artworks: true } },
|
_count: { select: { artworks: true } },
|
||||||
},
|
},
|
||||||
orderBy: [{ sortIndex: "asc" }, { name: "asc" }],
|
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 (
|
return (
|
||||||
<div className="mx-auto w-full max-w-7xl px-4 py-6">
|
<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">
|
<header className="mb-6 flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<h1 className="text-2xl font-semibold tracking-tight sm:text-3xl">
|
<h1 className="text-2xl font-semibold tracking-tight sm:text-3xl">
|
||||||
Tags
|
Art Tags
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-sm text-muted-foreground">Manage tags.</p>
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Manage tags, aliases, categories, and usage across artworks.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-2 sm:flex-row sm:items-center">
|
|
||||||
<Button asChild className="h-11 gap-2">
|
<Button asChild className="h-11 gap-2">
|
||||||
<Link href="/tags/new">
|
<Link href="/tags/new">
|
||||||
<PlusCircleIcon className="h-4 w-4" />
|
<PlusCircleIcon className="h-4 w-4" />
|
||||||
Add new tag
|
Add new tag
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{rows.length > 0 ? (
|
{items.length > 0 ? (
|
||||||
<TagTabs tags={rows} />
|
<TagTabs tags={items} />
|
||||||
) : (
|
) : (
|
||||||
<p className="text-muted-foreground">
|
<p className="text-muted-foreground">
|
||||||
There are no tags yet. Consider adding some!
|
There are no tags yet. Consider adding some!
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { getLatestTos } from "@/actions/tos/getTos";
|
import { getLatestTos } from "@/actions/tos/getTos";
|
||||||
import TosEditor from "@/components/tos/Editor";
|
import TosEditor from "@/components/tos/Editor";
|
||||||
|
|
||||||
// Admin page for editing Terms of Service.
|
|
||||||
export default async function TosPage() {
|
export default async function TosPage() {
|
||||||
const markdown = await getLatestTos();
|
const markdown = await getLatestTos();
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
import UploadBulkImageForm from "@/components/uploads/UploadBulkImageForm";
|
import UploadBulkImageForm from "@/components/uploads/UploadBulkImageForm";
|
||||||
|
|
||||||
// Bulk image upload page.
|
|
||||||
export default function UploadsBulkPage() {
|
export default function UploadsBulkPage() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div><UploadBulkImageForm /></div>
|
||||||
<UploadBulkImageForm />
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1,10 +1,7 @@
|
|||||||
import UploadImageForm from "@/components/uploads/UploadImageForm";
|
import UploadImageForm from "@/components/uploads/UploadImageForm";
|
||||||
|
|
||||||
// Single image upload page.
|
|
||||||
export default function UploadsSinglePage() {
|
export default function UploadsSinglePage() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div><UploadImageForm /></div>
|
||||||
<UploadImageForm />
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1,13 +1,11 @@
|
|||||||
import { CreateUserForm } from "@/components/users/CreateUserForm";
|
import { CreateUserForm } from "@/components/users/CreateUserForm";
|
||||||
import { auth } from "@/lib/auth";
|
import { auth } from "@/lib/auth";
|
||||||
import type { SessionWithRole } from "@/types/auth";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
// Admin-only user creation page.
|
|
||||||
export default async function NewUserPage() {
|
export default async function NewUserPage() {
|
||||||
const session = await auth.api.getSession({ headers: await headers() });
|
const session = await auth.api.getSession({ headers: await headers() });
|
||||||
const role = (session as SessionWithRole)?.user?.role;
|
const role = (session as any)?.user?.role;
|
||||||
|
|
||||||
if (!session) redirect("/login");
|
if (!session) redirect("/login");
|
||||||
if (role !== "admin") redirect("/");
|
if (role !== "admin") redirect("/");
|
||||||
|
|||||||
@ -1,13 +1,11 @@
|
|||||||
import { UsersTable } from "@/components/users/UsersTable";
|
import { UsersTable } from "@/components/users/UsersTable";
|
||||||
import { auth } from "@/lib/auth";
|
import { auth } from "@/lib/auth";
|
||||||
import type { SessionWithRole } from "@/types/auth";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
// Admin users list page.
|
|
||||||
export default async function UsersPage() {
|
export default async function UsersPage() {
|
||||||
const session = await auth.api.getSession({ headers: await headers() });
|
const session = await auth.api.getSession({ headers: await headers() });
|
||||||
const role = (session as SessionWithRole)?.user?.role;
|
const role = (session as any)?.user?.role as string | undefined;
|
||||||
|
|
||||||
if (!session) redirect("/login");
|
if (!session) redirect("/login");
|
||||||
if (role !== "admin") redirect("/");
|
if (role !== "admin") redirect("/");
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { ForgotPasswordForm } from "@/components/auth/ForgotPasswordForm";
|
import { ForgotPasswordForm } from "@/components/auth/ForgotPasswordForm";
|
||||||
|
|
||||||
// Forgot password page.
|
|
||||||
export default function ForgotPasswordPage() {
|
export default function ForgotPasswordPage() {
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto max-w-md p-6">
|
<div className="mx-auto max-w-md p-6">
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
import type { ReactNode } from "react";
|
|
||||||
|
|
||||||
// Layout wrapper for auth routes.
|
|
||||||
export default function AuthLayout({
|
export default function AuthLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col min-h-screen min-w-screen">
|
<div className="flex flex-col min-h-screen min-w-screen">
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import LoginForm from "@/components/auth/LoginForm";
|
import LoginForm from "@/components/auth/LoginForm";
|
||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
|
|
||||||
// Admin login page.
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen items-center justify-center">
|
<div className="flex min-h-screen items-center justify-center">
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { RegisterForm } from "@/components/auth/RegisterForm";
|
|||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
// One-time admin registration page (only when no users exist).
|
|
||||||
export default async function RegisterPage() {
|
export default async function RegisterPage() {
|
||||||
const count = await prisma.user.count();
|
const count = await prisma.user.count();
|
||||||
if (count !== 0) redirect("/login");
|
if (count !== 0) redirect("/login");
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { ResetPasswordForm } from "@/components/auth/ResetPasswordForm";
|
import { ResetPasswordForm } from "@/components/auth/ResetPasswordForm";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
// Reset password page, expects a token query param.
|
|
||||||
export default async function ResetPasswordPage({
|
export default async function ResetPasswordPage({
|
||||||
searchParams,
|
searchParams,
|
||||||
}: {
|
}: {
|
||||||
@ -14,7 +13,7 @@ export default async function ResetPasswordPage({
|
|||||||
<div className="mx-auto max-w-md p-6">
|
<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>
|
<p>No valid token, please try again or get back to <Link href="/">Home</Link></p>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { getArtworksPage } from "@/lib/queryArtworks";
|
import { getArtworksPage } from "@/lib/queryArtworks";
|
||||||
import { NextResponse, type NextRequest } from "next/server";
|
import { NextResponse, type NextRequest } from "next/server";
|
||||||
|
|
||||||
// Public API for paginated artworks listing.
|
|
||||||
export async function GET(req: NextRequest) {
|
export async function GET(req: NextRequest) {
|
||||||
const publishedParam = req.nextUrl.searchParams.get("published") ?? "all";
|
const publishedParam = req.nextUrl.searchParams.get("published") ?? "all";
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { auth } from "@/lib/auth";
|
import { auth } from "@/lib/auth";
|
||||||
import { toNextJsHandler } from "better-auth/next-js";
|
import { toNextJsHandler } from "better-auth/next-js";
|
||||||
|
|
||||||
// Better Auth route handlers.
|
|
||||||
export const { POST, GET } = toNextJsHandler(auth);
|
export const { POST, GET } = toNextJsHandler(auth);
|
||||||
@ -1,24 +1,7 @@
|
|||||||
import { s3 } from "@/lib/s3";
|
import { s3 } from "@/lib/s3";
|
||||||
import type { S3Body } from "@/types/s3";
|
|
||||||
import { GetObjectCommand } from "@aws-sdk/client-s3";
|
import { GetObjectCommand } from "@aws-sdk/client-s3";
|
||||||
import type { NextRequest } from "next/server";
|
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[] }> }) {
|
export async function GET(_req: NextRequest, context: { params: Promise<{ key: string[] }> }) {
|
||||||
const { key } = await context.params;
|
const { key } = await context.params;
|
||||||
const s3Key = key.join("/");
|
const s3Key = key.join("/");
|
||||||
@ -37,7 +20,7 @@ export async function GET(_req: NextRequest, context: { params: Promise<{ key: s
|
|||||||
|
|
||||||
const contentType = response.ContentType ?? "application/octet-stream";
|
const contentType = response.ContentType ?? "application/octet-stream";
|
||||||
|
|
||||||
return new Response(toBodyInit(response.Body as S3Body), {
|
return new Response(response.Body as ReadableStream, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": contentType,
|
"Content-Type": contentType,
|
||||||
"Cache-Control": "public, max-age=3600",
|
"Cache-Control": "public, max-age=3600",
|
||||||
@ -45,7 +28,7 @@ export async function GET(_req: NextRequest, context: { params: Promise<{ key: s
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.log(err)
|
||||||
return new Response("Image not found", { status: 404 });
|
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