feat: update environment variable handling and dependencies

- Added @t3-oss/env-nextjs for improved environment variable management.
- Updated zod to version 4.1.12 for enhanced validation capabilities.
- Upgraded jiti to version 2.6.1 for better module loading.
- Refactored environment variable imports from env.mjs to env.ts.
- Removed deprecated env.mjs file and replaced it with a new env.ts file using @t3-oss/env-nextjs.
- Adjusted various components and API routes to utilize the new environment variable structure.
- Updated next.config.js to support the new environment variable management.
- Modified Docker configuration to align with new BASE_URL handling.
This commit is contained in:
Marco Pedone 2025-10-20 16:22:20 +02:00
parent 60e3f26fd8
commit 699579b432
44 changed files with 279 additions and 282 deletions

View file

@ -1,5 +1,7 @@
.gitignore
.git
.env
.env.marcopedone
.env.infoalloggi
dev-tester.yml
nginx.conf

View file

@ -1,5 +1,4 @@
#BASE_URL="https://www.infoalloggi.it"
NEXT_PUBLIC_BASE_URL = "https://info.marcopedone.it"
BASE_URL="https://www.infoalloggi.it"
INTERNAL_BASE_URL = "http://web:3000"
#Api key for the mail service
SENDGRID_API_KEY='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'

View file

@ -1,5 +1,4 @@
#BASE_URL="https://info.marcopedone.it"
NEXT_PUBLIC_BASE_URL = "https://info.marcopedone.it"
BASE_URL="https://info.marcopedone.it"
INTERNAL_BASE_URL = "http://web:3000"
#Api key for the mail service
SENDGRID_API_KEY='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'

2
.gitignore vendored
View file

@ -1,4 +1,6 @@
.env
.env.marcopedone
.env.infoalloggi
build_logs.txt
infoalloggi_old/

View file

@ -25,8 +25,9 @@ ENV NEXT_TELEMETRY_DISABLED=1
ENV SKIP_REDIS="true"
# Only essential build-time variables
ARG NEXT_PUBLIC_BASE_URL
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
ARG BASE_URL
ENV BASE_URL=$BASE_URL
ENV NEXT_PUBLIC_BASE_URL=$BASE_URL
ARG NEXT_PUBLIC_STRIPE_PUBLIC_KEY
ENV NEXT_PUBLIC_STRIPE_PUBLIC_KEY=$NEXT_PUBLIC_STRIPE_PUBLIC_KEY
@ -81,8 +82,9 @@ ENV NEXT_TELEMETRY_DISABLED=1
ENV SKIP_REDIS="false"
# Essential runtime variables
ARG NEXT_PUBLIC_BASE_URL
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
ARG BASE_URL
ENV BASE_URL=$BASE_URL
ENV NEXT_PUBLIC_BASE_URL=$BASE_URL
ARG INTERNAL_BASE_URL
ENV INTERNAL_BASE_URL=$INTERNAL_BASE_URL
ARG POSTGRES_USER

View file

@ -1,100 +0,0 @@
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation.
* This is especially useful for Docker builds.
*/
import { env } from "node:process";
/** @type {import("next").NextConfig} */
const nextConfig = {
compiler: {
removeConsole: false,
},
experimental: {
// esmExternals: "loose", // This if react-pdf gives compilation issues
},
env: {
NEXT_PUBLIC_BUILD_ID: Math.random().toString(36).slice(2, 8),
},
devIndicators: false,
headers: async () => {
return [
{
headers: [
{
key: "X-Frame-Options",
value: "",
},
],
source: "/:path*",
},
];
},
i18n: {
defaultLocale: "it",
locales: ["it", "en"],
localeDetection: false,
},
images: {
minimumCacheTTL: 7200,
remotePatterns: [
{
hostname: "*.googleusercontent.com",
pathname: "**",
port: "",
protocol: "https",
},
{
hostname: `${env.BACKENDSERVER_URL}`,
},
],
},
output: env.NODE_ENV === "production" ? "standalone" : undefined, // This is for docker builds
reactStrictMode: true,
rewrites: async () => {
return [
{
destination: env.NODE_ENV === "production" ? "/404" : "/api/panel",
source: "/api/panel",
},
{
destination: `${env.BACKENDSERVER_URL}/images/get/:slug*`,
source: "/go-api/images/get/:slug*",
},
{
destination: `${env.BACKENDSERVER_URL}/storage/get/:slug*`,
has: [
{ key: "access_token", type: "cookie" },
{
key: "token",
type: "query",
value:
"(?<token>^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$)",
},
],
source: "/go-api/storage/get/:slug*",
},
{
destination: `${env.BACKENDSERVER_URL}/storage/upload:slug*`,
has: [
{ key: "access_token", type: "cookie" },
{
key: "token",
type: "query",
value:
"(?<token>^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$)",
},
],
source: "/go-api/storage/upload:slug*",
},
];
},
typescript: {
ignoreBuildErrors: true,
},
};
export default nextConfig;

View file

@ -0,0 +1,109 @@
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation.
* This is especially useful for Docker builds.
*/
import { env } from "node:process";
import { fileURLToPath } from "node:url";
import type { NextConfig } from "next";
async function createNextConfig(): Promise<NextConfig> {
const { createJiti } = await import("jiti");
const jiti = createJiti(fileURLToPath(import.meta.url));
await jiti.import("./src/env.ts");
return {
compiler: {
removeConsole: false,
},
experimental: {
// esmExternals: "loose", // This if react-pdf gives compilation issues
},
env: {
NEXT_PUBLIC_BUILD_ID: Math.random().toString(36).slice(2, 8),
},
devIndicators: false,
headers: async () => {
return [
{
headers: [
{
key: "X-Frame-Options",
value: "",
},
],
source: "/:path*",
},
];
},
i18n: {
defaultLocale: "it",
locales: ["it", "en"],
localeDetection: false,
},
images: {
minimumCacheTTL: 7200,
remotePatterns: [
{
hostname: "*.googleusercontent.com",
pathname: "**",
port: "",
protocol: "https",
},
{
hostname: `${env.BACKENDSERVER_URL}`,
},
],
},
output: env.NODE_ENV === "production" ? "standalone" : undefined, // This is for docker builds
transpilePackages: ["@t3-oss/env-nextjs", "@t3-oss/env-core"],
reactStrictMode: true,
rewrites: async () => {
return [
{
destination: env.NODE_ENV === "production" ? "/404" : "/api/panel",
source: "/api/panel",
},
{
destination: `${env.BACKENDSERVER_URL}/images/get/:slug*`,
source: "/go-api/images/get/:slug*",
},
{
destination: `${env.BACKENDSERVER_URL}/storage/get/:slug*`,
has: [
{ key: "access_token", type: "cookie" },
{
key: "token",
type: "query",
value:
"(?<token>^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$)",
},
],
source: "/go-api/storage/get/:slug*",
},
{
destination: `${env.BACKENDSERVER_URL}/storage/upload:slug*`,
has: [
{ key: "access_token", type: "cookie" },
{
key: "token",
type: "query",
value:
"(?<token>^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$)",
},
],
source: "/go-api/storage/upload:slug*",
},
];
},
typescript: {
ignoreBuildErrors: true,
},
};
}
export default (async () => await createNextConfig())();

View file

@ -18,6 +18,7 @@
"@react-email/render": "^1.1.4",
"@stripe/react-stripe-js": "^3.9.0",
"@stripe/stripe-js": "^7.8.0",
"@t3-oss/env-nextjs": "^0.13.8",
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/postcss": "^4.1.11",
"@tailwindcss/typography": "^0.5.16",
@ -87,7 +88,7 @@
"uuid": "^11.1.0",
"vaul": "^1.1.2",
"yaml": "^2.8.1",
"zod": "^4.0.15"
"zod": "^4.1.12"
},
"devDependencies": {
"@biomejs/biome": "2.2.2",
@ -105,7 +106,7 @@
"@types/react-is": "^19.0.0",
"@types/uuid": "^10.0.0",
"cross-env": "^10.0.0",
"jiti": "^2.5.1",
"jiti": "^2.6.1",
"kanel": "^3.14.2",
"kanel-kysely": "^0.7.1",
"knip": "^5.62.0",
@ -8175,6 +8176,61 @@
"tslib": "^2.8.0"
}
},
"node_modules/@t3-oss/env-core": {
"version": "0.13.8",
"resolved": "https://registry.npmjs.org/@t3-oss/env-core/-/env-core-0.13.8.tgz",
"integrity": "sha512-L1inmpzLQyYu4+Q1DyrXsGJYCXbtXjC4cICw1uAKv0ppYPQv656lhZPU91Qd1VS6SO/bou1/q5ufVzBGbNsUpw==",
"license": "MIT",
"peerDependencies": {
"arktype": "^2.1.0",
"typescript": ">=5.0.0",
"valibot": "^1.0.0-beta.7 || ^1.0.0",
"zod": "^3.24.0 || ^4.0.0-beta.0"
},
"peerDependenciesMeta": {
"arktype": {
"optional": true
},
"typescript": {
"optional": true
},
"valibot": {
"optional": true
},
"zod": {
"optional": true
}
}
},
"node_modules/@t3-oss/env-nextjs": {
"version": "0.13.8",
"resolved": "https://registry.npmjs.org/@t3-oss/env-nextjs/-/env-nextjs-0.13.8.tgz",
"integrity": "sha512-QmTLnsdQJ8BiQad2W2nvV6oUpH4oMZMqnFEjhVpzU0h3sI9hn8zb8crjWJ1Amq453mGZs6A4v4ihIeBFDOrLeQ==",
"license": "MIT",
"dependencies": {
"@t3-oss/env-core": "0.13.8"
},
"peerDependencies": {
"arktype": "^2.1.0",
"typescript": ">=5.0.0",
"valibot": "^1.0.0-beta.7 || ^1.0.0",
"zod": "^3.24.0 || ^4.0.0-beta.0"
},
"peerDependenciesMeta": {
"arktype": {
"optional": true
},
"typescript": {
"optional": true
},
"valibot": {
"optional": true
},
"zod": {
"optional": true
}
}
},
"node_modules/@tailwindcss/forms": {
"version": "0.5.10",
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz",
@ -12912,9 +12968,9 @@
}
},
"node_modules/jiti": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
"integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==",
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
"license": "MIT",
"bin": {
"jiti": "lib/jiti-cli.mjs"
@ -19085,9 +19141,9 @@
"license": "MIT"
},
"node_modules/zod": {
"version": "4.0.17",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.0.17.tgz",
"integrity": "sha512-1PHjlYRevNxxdy2JZ8JcNAw7rX8V9P1AKkP+x/xZfxB0K5FYfuV+Ug6P/6NVSR2jHQ+FzDDoDHS04nYUsOIyLQ==",
"version": "4.1.12",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz",
"integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"

View file

@ -29,6 +29,7 @@
"@react-email/render": "^1.1.4",
"@stripe/react-stripe-js": "^3.9.0",
"@stripe/stripe-js": "^7.8.0",
"@t3-oss/env-nextjs": "^0.13.8",
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/postcss": "^4.1.11",
"@tailwindcss/typography": "^0.5.16",
@ -98,7 +99,7 @@
"uuid": "^11.1.0",
"vaul": "^1.1.2",
"yaml": "^2.8.1",
"zod": "^4.0.15"
"zod": "^4.1.12"
},
"devDependencies": {
"@biomejs/biome": "2.2.2",
@ -116,7 +117,7 @@
"@types/react-is": "^19.0.0",
"@types/uuid": "^10.0.0",
"cross-env": "^10.0.0",
"jiti": "^2.5.1",
"jiti": "^2.6.1",
"kanel": "^3.14.2",
"kanel-kysely": "^0.7.1",
"knip": "^5.62.0",

View file

@ -14,7 +14,7 @@ import { LoadingPage } from "~/components/loading";
import { Status500 } from "~/components/status-page";
import { Button } from "~/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import { env } from "~/env.mjs";
import { env } from "~/env";
import { formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import type { PaymentsId } from "~/schemas/public/Payments";

View file

@ -11,7 +11,7 @@ import {
} from "react-hook-form";
import { Label } from "src/components/ui/label";
import { cn } from "src/lib/utils";
import { env } from "~/env.mjs";
import { env } from "~/env";
const Form = FormProvider;

View file

@ -39,7 +39,7 @@ import {
TooltipContent,
TooltipTrigger,
} from "~/components/ui/tooltip";
import { env } from "~/env.mjs";
import { env } from "~/env";
import type { AnnunciId } from "~/schemas/public/Annunci";
import type { Servizio, ServizioServizioId } from "~/schemas/public/Servizio";
import type { UsersId } from "~/schemas/public/Users";
@ -70,7 +70,7 @@ export const TabServizio = ({
toast.error(error.message);
},
onSuccess: async () => {
toast.success("Servizio rimosso con successo");
toast.success("Email onboarding inviata con successo");
await utils.servizio.getUserServizi.invalidate();
},
});

View file

@ -1,123 +0,0 @@
// @ts-nocheck
import { z } from "zod/v4";
/**
* Specify your server-side environment variables schema here. This way you can ensure the app isn't
* built with invalid env vars.
*/
const server = z.object({
ARUBA_PASS: z.string(),
ARUBA_USER: z.string(),
BACKENDSERVER_URL: z.string(),
EXP_API_PASS: z.string(),
EXP_API_USER: z.string(),
FIC_ACCESS_TOKEN: z.string(),
FIC_CLIENT_ID: z.string(),
FIC_COMPANY_ID: z.string(),
INTERNAL_BASE_URL: z.url(),
JWT_SECRET: z.string(),
KEYDB_URL: z.string(),
NODE_ENV: z.enum(["development", "test", "production"]),
PGHOST: z.string(),
PGPORT: z.string(),
POSTGRES_DB: z.string(),
POSTGRES_PASSWORD: z.string(),
POSTGRES_USER: z.string(),
SKIP_REDIS: z.string(),
STRIPE_SECRET_KEY: z.string(),
STRIPE_WEBHOOK_SECRET: z.string(),
TILES_URL: z.string(),
SKEBBY_USER: z.string(),
SKEBBY_PASS: z.string(),
REVALIDATION_SECRET: z.string(),
});
/**
* Specify your client-side environment variables schema here. This way you can ensure the app isn't
* built with invalid env vars. To expose them to the client, prefix them with `NEXT_PUBLIC_`.
*/
const client = z.object({
NEXT_PUBLIC_BASE_URL: z.string(),
NEXT_PUBLIC_STRIPE_PUBLIC_KEY: z.string(),
});
/**
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
* middlewares) or client-side so we need to destruct manually.
*
* @type {Record<keyof z.infer<typeof server> | keyof z.infer<typeof client>, string | undefined>}
*/
const processEnv = {
ARUBA_PASS: process.env.ARUBA_PASS,
ARUBA_USER: process.env.ARUBA_USER,
BACKENDSERVER_URL: process.env.BACKENDSERVER_URL,
EXP_API_PASS: process.env.EXP_API_PASS,
EXP_API_USER: process.env.EXP_API_USER,
FIC_ACCESS_TOKEN: process.env.FIC_ACCESS_TOKEN,
FIC_CLIENT_ID: process.env.FIC_CLIENT_ID,
FIC_COMPANY_ID: process.env.FIC_COMPANY_ID,
INTERNAL_BASE_URL: process.env.INTERNAL_BASE_URL,
JWT_SECRET: process.env.JWT_SECRET,
KEYDB_URL: process.env.KEYDB_URL,
NEXT_PUBLIC_BASE_URL: process.env.NEXT_PUBLIC_BASE_URL,
NEXT_PUBLIC_STRIPE_PUBLIC_KEY: process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY,
NODE_ENV: process.env.NODE_ENV,
PGHOST: process.env.PGHOST,
PGPORT: process.env.PGPORT,
POSTGRES_DB: process.env.POSTGRES_DB,
POSTGRES_PASSWORD: process.env.POSTGRES_PASSWORD,
POSTGRES_USER: process.env.POSTGRES_USER,
SKIP_REDIS: process.env.SKIP_REDIS,
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
TILES_URL: process.env.TILES_URL,
SKEBBY_USER: process.env.SKEBBY_USER,
SKEBBY_PASS: process.env.SKEBBY_PASS,
REVALIDATION_SECRET: process.env.REVALIDATION_SECRET,
};
// Don't touch the part below
// --------------------------
const merged = server.merge(client);
/** @typedef {z.input<typeof merged>} MergedInput */
/** @typedef {z.infer<typeof merged>} MergedOutput */
/** @typedef {z.SafeParseReturnType<MergedInput, MergedOutput>} MergedSafeParseReturn */
let env = /** @type {MergedOutput} */ (process.env);
if (!!process.env.SKIP_ENV_VALIDATION === false) {
const isServer = typeof window === "undefined";
const parsed = /** @type {MergedSafeParseReturn} */ (
isServer
? merged.safeParse(processEnv) // on server we can validate all env vars
: client.safeParse(processEnv) // on client we can only validate the ones that are exposed
);
if (parsed.success === false) {
console.error(
"❌ Invalid environment variables:",
z.treeifyError(parsed.error).fieldErrors,
);
throw new Error("Invalid environment variables");
}
env = new Proxy(parsed.data, {
get(target, prop) {
if (typeof prop !== "string") return undefined;
// Throw a descriptive error if a server-side env var is accessed on the client
// Otherwise it would just be returning `undefined` and be annoying to debug
if (!isServer && !prop.startsWith("NEXT_PUBLIC_"))
throw new Error(
process.env.NODE_ENV === "production"
? "❌ Attempted to access a server-side environment variable on the client"
: `❌ Attempted to access server-side environment variable '${prop}' on the client`,
);
return target[/** @type {keyof typeof target} */ (prop)];
},
});
}
export { env };

View file

@ -0,0 +1,44 @@
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
BASE_URL: z.string(),
ARUBA_PASS: z.string(),
ARUBA_USER: z.string(),
BACKENDSERVER_URL: z.string(),
EXP_API_PASS: z.string(),
EXP_API_USER: z.string(),
FIC_ACCESS_TOKEN: z.string(),
FIC_CLIENT_ID: z.string(),
FIC_COMPANY_ID: z.string(),
INTERNAL_BASE_URL: z.string(),
JWT_SECRET: z.string(),
KEYDB_URL: z.string(),
NODE_ENV: z.enum(["development", "test", "production"]),
PGHOST: z.string(),
PGPORT: z.string(),
POSTGRES_DB: z.string(),
POSTGRES_PASSWORD: z.string(),
POSTGRES_USER: z.string(),
SKIP_REDIS: z.string(),
STRIPE_SECRET_KEY: z.string(),
STRIPE_WEBHOOK_SECRET: z.string(),
TILES_URL: z.string(),
SKEBBY_USER: z.string(),
SKEBBY_PASS: z.string(),
REVALIDATION_SECRET: z.string(),
},
client: {
NEXT_PUBLIC_BASE_URL: z.string(),
NEXT_PUBLIC_STRIPE_PUBLIC_KEY: z.string(),
},
// shared: {
// NEXT_PUBLIC_BASE_URL: z.string(),
// },
// If you're using Next.js < 13.4.4, you'll need to specify the runtimeEnv manually
experimental__runtimeEnv: {
NEXT_PUBLIC_BASE_URL: process.env.NEXT_PUBLIC_BASE_URL,
NEXT_PUBLIC_STRIPE_PUBLIC_KEY: process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY,
},
});

View file

@ -15,7 +15,7 @@ import Input from "~/components/custom_ui/input";
import { LoadingSpinner } from "~/components/spinner";
import { Button } from "~/components/ui/button";
import { Checkbox } from "~/components/ui/checkbox";
import { env } from "~/env.mjs";
import { env } from "~/env";
import { useZodForm } from "~/lib/zodForm";
import { useTranslation } from "~/providers/I18nProvider";
import { api } from "~/utils/api";

View file

@ -1,5 +1,5 @@
import { type NextRequest, NextResponse } from "next/server";
import { env } from "~/env.mjs";
import { env } from "~/env";
export const apisMiddleware = async (req: NextRequest) => {
const path = req.nextUrl.pathname;

View file

@ -45,7 +45,7 @@ import {
} from "~/components/ui/dialog";
import { Label } from "~/components/ui/label";
import { VideoPlayer } from "~/components/videoPlayer";
import { env } from "~/env.mjs";
import { env } from "~/env";
import {
type CaratteristicheFiltered,
filteredCaratteristiche,

View file

@ -1,5 +1,5 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { env } from "~/env.mjs";
import { env } from "~/env";
export default async function handler(
req: NextApiRequest,

View file

@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from "next";
import Stripe from "stripe";
import { env } from "~/env.mjs";
import { env } from "~/env";
import type { PaymentsId } from "~/schemas/public/Payments";
import { appRouter } from "~/server/api/root";
import { createTRPCContext, t } from "~/server/api/trpc";

View file

@ -1,6 +1,6 @@
import Redis from "ioredis";
import type { NextApiRequest, NextApiResponse } from "next";
import { env } from "~/env.mjs";
import { env } from "~/env";
let tiles: Redis | null = null;

View file

@ -1,6 +1,6 @@
import { createNextApiHandler } from "@trpc/server/adapters/next";
import { env } from "~/env.mjs";
import { env } from "~/env";
import { appRouter } from "~/server/api/root";
import { createTRPCContext } from "~/server/api/trpc";

View file

@ -8,7 +8,7 @@ import { PricingChoice } from "~/components/prezzi";
import { HeroSvg, LogoSvg } from "~/components/svgs";
import { Button } from "~/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import { env } from "~/env.mjs";
import { env } from "~/env";
import type { LangDict } from "~/i18n/locales";
import { useTranslation } from "~/providers/I18nProvider";

View file

@ -8,7 +8,7 @@ import { useEffect, useState } from "react";
import PaymentStatus from "~/components/payment_status";
import { ProgressRedirect } from "~/components/progress_redirect";
import { Button, buttonVariants } from "~/components/ui/button";
import { env } from "~/env.mjs";
import { env } from "~/env";
import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum";

View file

@ -4,7 +4,7 @@ import { AcquistoProcessing } from "~/components/acquisto_processing";
import { AreaRiservataLayout } from "~/components/Layout";
import { LoadingPage } from "~/components/loading";
import { Status500 } from "~/components/status-page";
import { env } from "~/env.mjs";
import { env } from "~/env";
import type { NextPageWithLayout } from "~/pages/_app";
import { useTranslation } from "~/providers/I18nProvider";
import type { OrdiniOrdineId } from "~/schemas/public/Ordini";

View file

@ -1,5 +1,5 @@
import type { GetServerSideProps } from "next";
import { env } from "~/env.mjs";
import { env } from "~/env";
import { generateSSGHelper } from "~/server/utils/ssgHelper";
async function generateSiteMap() {

View file

@ -2,7 +2,7 @@ import {
ClientsApi,
Configuration,
} from "@fattureincloud/fattureincloud-ts-sdk";
import { env } from "~/env.mjs";
import { env } from "~/env";
const apiConfig = new Configuration({
accessToken: env.FIC_ACCESS_TOKEN,

View file

@ -1,6 +1,6 @@
import { TRPCError } from "@trpc/server";
import z from "zod/v4";
import { env } from "~/env.mjs";
import { env } from "~/env";
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
import { db } from "~/server/db";
import {

View file

@ -1,6 +1,6 @@
import { TRPCError } from "@trpc/server";
import { z } from "zod/v4";
import { env } from "~/env.mjs";
import { env } from "~/env";
import type { BannersIdbanner } from "~/schemas/public/Banners";
import {
adminProcedure,

View file

@ -12,7 +12,7 @@ import type { CreateNextContextOptions } from "@trpc/server/adapters/next";
import type { NextApiRequest, NextApiResponse } from "next";
import superjson from "superjson";
import z, { ZodError } from "zod/v4";
import { env } from "~/env.mjs";
import { env } from "~/env";
import { verifyToken } from "~/server/auth/jwt";
import { zUserId } from "~/server/utils/zod_types";
import { TOKEN_CONFIG } from "../auth/configs";

View file

@ -1,6 +1,6 @@
import { TRPCError } from "@trpc/server";
import { jwtVerify, SignJWT } from "jose";
import { env } from "~/env.mjs";
import { env } from "~/env";
import { type Session, sessionSchema } from "~/server/api/trpc";
const secret = new TextEncoder().encode(env.JWT_SECRET);

View file

@ -1,5 +1,5 @@
import { TRPCError } from "@trpc/server";
import { env } from "~/env.mjs";
import { env } from "~/env";
import type {
Annunci,
AnnunciId,

View file

@ -4,7 +4,7 @@ import { sql } from "kysely";
import { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/postgres";
import { z } from "zod/v4";
import type { PurchaseData } from "~/components/acquisto_receipt";
import { env } from "~/env.mjs";
import { env } from "~/env";
import type { AnnunciId } from "~/schemas/public/Annunci";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import type { OrdiniOrdineId } from "~/schemas/public/Ordini";
@ -753,7 +753,7 @@ export const updateServizioAnnuncio = async ({
mailType: "generic",
props: {
link: {
href: `${env.NEXT_PUBLIC_BASE_URL}/area-riservata/dashboard#${servizioId}-${annuncioId}`,
href: `${env.BASE_URL}/area-riservata/dashboard#${servizioId}-${annuncioId}`,
label: "Vai al servizio",
},
noreply: true,
@ -772,7 +772,7 @@ export const updateServizioAnnuncio = async ({
mailType: "generic",
props: {
link: {
href: `${env.NEXT_PUBLIC_BASE_URL}/area-riservata/admin/user-view/ricerca/${servizio.user_id}#${servizioId}-${annuncioId}`,
href: `${env.BASE_URL}/area-riservata/admin/user-view/ricerca/${servizio.user_id}#${servizioId}-${annuncioId}`,
label: "Vai al servizio",
},
noreply: true,
@ -930,7 +930,7 @@ export const SbloccaContatti = async ({
mailType: "generic",
props: {
link: {
href: `${env.NEXT_PUBLIC_BASE_URL}/area-riservata/dashboard#${servizioId}-${annuncioId}`,
href: `${env.BASE_URL}/area-riservata/dashboard#${servizioId}-${annuncioId}`,
label: "Vai al servizio",
},
noreply: true,
@ -1052,7 +1052,7 @@ export const interruzioneServizio = async (servizioId: ServizioServizioId) => {
mailType: "generic",
props: {
link: {
href: `${env.NEXT_PUBLIC_BASE_URL}/area-riservata/admin/user-view/ricerca/${servizio.user_id}#${servizioId}`,
href: `${env.BASE_URL}/area-riservata/admin/user-view/ricerca/${servizio.user_id}#${servizioId}`,
label: "Vai al servizio",
},
noreply: true,
@ -1155,6 +1155,12 @@ export const sendServizioEmail = async ({
.where("servizio_annunci.servizio_id", "=", servizioId)
.execute();
console.log("=== EMAIL DEBUG ===");
console.log("BASE_URL:", env.BASE_URL);
console.log("INTERNAL_BASE_URL:", env.INTERNAL_BASE_URL);
console.log("NEXT_PUBLIC_BASE_URL:", env.NEXT_PUBLIC_BASE_URL);
console.log("==================");
const { email, nome } = user;
await NewMail({
mailType: "onboardingServizio",
@ -1169,7 +1175,7 @@ export const sendServizioEmail = async ({
})),
nome,
token: servizioId,
baseUrl: env.NEXT_PUBLIC_BASE_URL,
baseUrl: env.BASE_URL,
},
subject: "Procedi ora su Infoalloggi.it",
to: email,
@ -1234,7 +1240,7 @@ export const userConfirmImmobile = async ({
mailType: "generic",
props: {
link: {
href: `${env.NEXT_PUBLIC_BASE_URL}/area-riservata/admin/user-view/ricerca/${servizio.user_id}#${servizioId}-${annuncioId}`,
href: `${env.BASE_URL}/area-riservata/admin/user-view/ricerca/${servizio.user_id}#${servizioId}-${annuncioId}`,
label: "Visualizza Annuncio",
},
noreply: true,
@ -1448,7 +1454,7 @@ export const SendContactEmail = async ({
messaggio,
nome,
telefono,
baseUrl: env.NEXT_PUBLIC_BASE_URL,
baseUrl: env.BASE_URL,
},
subject: "Contatto per annuncio",
to: "web@infoalloggi.it",

View file

@ -1,4 +1,4 @@
import { env } from "~/env.mjs";
import { env } from "~/env";
import { GetFlagValueHandler } from "~/server/controllers/flags.controller";
import { db } from "~/server/db";
import { NewMail } from "~/server/services/mailer";

View file

@ -1,6 +1,6 @@
import { TRPCError } from "@trpc/server";
import Stripe from "stripe";
import { env } from "~/env.mjs";
import { env } from "~/env";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum";
import type { Payments, PaymentsId } from "~/schemas/public/Payments";

View file

@ -8,7 +8,7 @@ import {
type Transaction,
} from "kysely";
import { Pool } from "pg";
import { env } from "~/env.mjs";
import { env } from "~/env";
import type Database from "~/schemas/Database";
import type PublicSchema from "~/schemas/public/PublicSchema";

View file

@ -1,7 +1,7 @@
import { randomBytes } from "node:crypto";
import { TRPCError } from "@trpc/server";
import { add } from "date-fns";
import { env } from "~/env.mjs";
import { env } from "~/env";
import type { UsersId } from "~/schemas/public/Users";
import { db } from "~/server/db";
import { NewMail } from "~/server/services/mailer";

View file

@ -1,4 +1,4 @@
import { env } from "~/env.mjs";
import { env } from "~/env";
export const createSrcset = (url_immagini: string[]) => {
const finalSrcset = [];

View file

@ -32,7 +32,7 @@ import { createTransport } from "nodemailer";
import type { Options } from "nodemailer/lib/mailer";
import { htmlToText } from "nodemailer-html-to-text";
import type { JSX } from "react";
import { env } from "~/env.mjs";
import { env } from "~/env";
import type { UsersId } from "~/schemas/public/Users";
import { GetFlagValueHandler } from "~/server/controllers/flags.controller";
import { db } from "~/server/db";

View file

@ -1,5 +1,5 @@
import { TRPCError } from "@trpc/server";
import { env } from "~/env.mjs";
import { env } from "~/env";
import type {
StorageindexId,
StorageindexUpdate,

View file

@ -1,4 +1,4 @@
import { env } from "~/env.mjs";
import { env } from "~/env";
export const revalidate = async (path: string) => {
try {

View file

@ -1,4 +1,4 @@
import { env } from "~/env.mjs";
import { env } from "~/env";
export const getMediaUrl = (path: string) => {
const baseURL = !env.NEXT_PUBLIC_BASE_URL.includes("localhost")

View file

@ -1,5 +1,5 @@
import Redis from "ioredis";
import { env } from "~/env.mjs";
import { env } from "~/env";
let keydb: Redis | null = null;

View file

@ -43,7 +43,7 @@
"include": [
"src",
"next-env.d.ts",
"next.config.mjs",
"next.config.ts",
"postcss.config.cjs",
"reset.d.ts",
"TypeHelpers.type.ts",

View file

@ -129,7 +129,7 @@ services:
BACKENDSERVER_URL: http://backend:1323
KEYDB_URL: keydb:6379
TILES_URL: tiles:6379
#BASE_URL: ${BASE_URL}
BASE_URL: ${BASE_URL}
SENDGRID_API_KEY: ${SENDGRID_API_KEY}
STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY}
NEXT_PUBLIC_STRIPE_PUBLIC_KEY: ${NEXT_PUBLIC_STRIPE_PUBLIC_KEY}