mirror of
https://github.com/documenso/documenso.git
synced 2025-11-17 18:21:32 +10:00
fix: wip
This commit is contained in:
@ -6,6 +6,7 @@ import {
|
||||
SUPPORTED_LANGUAGE_CODES,
|
||||
isValidLanguageCode,
|
||||
} from '../../constants/i18n';
|
||||
import { env } from '../../utils/env';
|
||||
import { remember } from '../../utils/remember';
|
||||
|
||||
type SupportedLanguages = (typeof SUPPORTED_LANGUAGE_CODES)[number];
|
||||
@ -13,7 +14,7 @@ type SupportedLanguages = (typeof SUPPORTED_LANGUAGE_CODES)[number];
|
||||
export async function loadCatalog(lang: SupportedLanguages): Promise<{
|
||||
[k: string]: Messages;
|
||||
}> {
|
||||
const extension = process.env.NODE_ENV === 'development' ? 'po' : 'js';
|
||||
const extension = env('NODE_ENV') === 'development' ? 'po' : 'js';
|
||||
|
||||
// const { messages } = await import(`../../translations/${lang}/web.${extension}`);
|
||||
const messages = {};
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
import { env } from 'next-runtime-env';
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
|
||||
export const APP_DOCUMENT_UPLOAD_SIZE_LIMIT =
|
||||
Number(process.env.NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT) || 50;
|
||||
Number(env('NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT')) || 50;
|
||||
|
||||
// Todo: env('NEXT_PUBLIC_WEBAPP_URL')
|
||||
export const NEXT_PUBLIC_WEBAPP_URL = () => 'http://localhost:3000';
|
||||
export const NEXT_PUBLIC_MARKETING_URL = () => env('NEXT_PUBLIC_MARKETING_URL');
|
||||
export const NEXT_PRIVATE_INTERNAL_WEBAPP_URL =
|
||||
process.env.NEXT_PRIVATE_INTERNAL_WEBAPP_URL ?? NEXT_PUBLIC_WEBAPP_URL();
|
||||
env('NEXT_PRIVATE_INTERNAL_WEBAPP_URL') ?? NEXT_PUBLIC_WEBAPP_URL();
|
||||
|
||||
export const IS_APP_MARKETING = process.env.NEXT_PUBLIC_PROJECT === 'marketing';
|
||||
export const IS_APP_WEB = process.env.NEXT_PUBLIC_PROJECT === 'web';
|
||||
export const IS_APP_MARKETING = env('NEXT_PUBLIC_PROJECT') === 'marketing';
|
||||
export const IS_APP_WEB = env('NEXT_PUBLIC_PROJECT') === 'web';
|
||||
export const IS_BILLING_ENABLED = () => env('NEXT_PUBLIC_FEATURE_BILLING_ENABLED') === 'true';
|
||||
export const IS_APP_WEB_I18N_ENABLED = true;
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Todo: Reimport
|
||||
import { env } from '../utils/env';
|
||||
|
||||
export const SALT_ROUNDS = 12;
|
||||
|
||||
@ -9,17 +9,16 @@ export const IDENTITY_PROVIDER_NAME: Record<string, string> = {
|
||||
};
|
||||
|
||||
export const IS_GOOGLE_SSO_ENABLED = Boolean(
|
||||
import.meta.env.NEXT_PRIVATE_GOOGLE_CLIENT_ID &&
|
||||
import.meta.env.NEXT_PRIVATE_GOOGLE_CLIENT_SECRET,
|
||||
env('NEXT_PRIVATE_GOOGLE_CLIENT_ID') && env('NEXT_PRIVATE_GOOGLE_CLIENT_SECRET'),
|
||||
);
|
||||
|
||||
export const IS_OIDC_SSO_ENABLED = Boolean(
|
||||
process.env.NEXT_PRIVATE_OIDC_WELL_KNOWN &&
|
||||
process.env.NEXT_PRIVATE_OIDC_CLIENT_ID &&
|
||||
process.env.NEXT_PRIVATE_OIDC_CLIENT_SECRET,
|
||||
env('NEXT_PRIVATE_OIDC_WELL_KNOWN') &&
|
||||
env('NEXT_PRIVATE_OIDC_CLIENT_ID') &&
|
||||
env('NEXT_PRIVATE_OIDC_CLIENT_SECRET'),
|
||||
);
|
||||
|
||||
export const OIDC_PROVIDER_LABEL = process.env.NEXT_PRIVATE_OIDC_PROVIDER_LABEL;
|
||||
export const OIDC_PROVIDER_LABEL = env('NEXT_PRIVATE_OIDC_PROVIDER_LABEL');
|
||||
|
||||
export const USER_SECURITY_AUDIT_LOG_MAP: Record<string, string> = {
|
||||
ACCOUNT_SSO_LINK: 'Linked account to SSO',
|
||||
@ -49,7 +48,7 @@ export const PASSKEY_TIMEOUT = 60000;
|
||||
export const MAXIMUM_PASSKEYS = 50;
|
||||
|
||||
export const useSecureCookies =
|
||||
process.env.NODE_ENV === 'production' && String(process.env.NEXTAUTH_URL).startsWith('https://');
|
||||
env('NODE_ENV') === 'production' && String(env('NEXTAUTH_URL')).startsWith('https://');
|
||||
|
||||
const secureCookiePrefix = useSecureCookies ? '__Secure-' : '';
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
export const FROM_ADDRESS = process.env.NEXT_PRIVATE_SMTP_FROM_ADDRESS || 'noreply@documenso.com';
|
||||
export const FROM_NAME = process.env.NEXT_PRIVATE_SMTP_FROM_NAME || 'Documenso';
|
||||
import { env } from '../utils/env';
|
||||
|
||||
export const FROM_ADDRESS = env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com';
|
||||
export const FROM_NAME = env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso';
|
||||
|
||||
export const SERVICE_USER_EMAIL = 'serviceaccount@documenso.com';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { env } from 'next-runtime-env';
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
|
||||
import { APP_BASE_URL, WEBAPP_BASE_URL } from './app';
|
||||
|
||||
|
||||
@ -17,8 +17,6 @@ export enum AppErrorCode {
|
||||
'RETRY_EXCEPTION' = 'RETRY_EXCEPTION',
|
||||
'SCHEMA_FAILED' = 'SCHEMA_FAILED',
|
||||
'TOO_MANY_REQUESTS' = 'TOO_MANY_REQUESTS',
|
||||
'PROFILE_URL_TAKEN' = 'PROFILE_URL_TAKEN',
|
||||
'PREMIUM_PROFILE_URL' = 'PREMIUM_PROFILE_URL',
|
||||
}
|
||||
|
||||
export const genericErrorCodeToTrpcErrorCodeMap: Record<string, { code: string; status: number }> =
|
||||
@ -34,8 +32,6 @@ export const genericErrorCodeToTrpcErrorCodeMap: Record<string, { code: string;
|
||||
[AppErrorCode.RETRY_EXCEPTION]: { code: 'INTERNAL_SERVER_ERROR', status: 500 },
|
||||
[AppErrorCode.SCHEMA_FAILED]: { code: 'INTERNAL_SERVER_ERROR', status: 500 },
|
||||
[AppErrorCode.TOO_MANY_REQUESTS]: { code: 'TOO_MANY_REQUESTS', status: 429 },
|
||||
[AppErrorCode.PROFILE_URL_TAKEN]: { code: 'BAD_REQUEST', status: 400 },
|
||||
[AppErrorCode.PREMIUM_PROFILE_URL]: { code: 'BAD_REQUEST', status: 400 },
|
||||
};
|
||||
|
||||
export const ZAppErrorJsonSchema = z.object({
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { match } from 'ts-pattern';
|
||||
|
||||
import { env } from '../../utils/env';
|
||||
import type { JobDefinition, TriggerJobOptions } from './_internal/job';
|
||||
import type { BaseJobProvider as JobClientProvider } from './base';
|
||||
import { InngestJobProvider } from './inngest';
|
||||
@ -10,7 +11,7 @@ export class JobClient<T extends ReadonlyArray<JobDefinition> = []> {
|
||||
private _provider: JobClientProvider;
|
||||
|
||||
public constructor(definitions: T) {
|
||||
this._provider = match(process.env.NEXT_PRIVATE_JOBS_PROVIDER)
|
||||
this._provider = match(env('NEXT_PRIVATE_JOBS_PROVIDER'))
|
||||
.with('inngest', () => InngestJobProvider.getInstance())
|
||||
.with('trigger', () => TriggerJobProvider.getInstance())
|
||||
.otherwise(() => LocalJobProvider.getInstance());
|
||||
|
||||
@ -9,6 +9,7 @@ import type { Logger } from 'inngest/middleware/logger';
|
||||
import { serve as createPagesRoute } from 'inngest/next';
|
||||
import { json } from 'micro';
|
||||
|
||||
import { env } from '../../utils/env';
|
||||
import type { JobDefinition, JobRunIO, SimpleTriggerJobOptions } from './_internal/job';
|
||||
import { BaseJobProvider } from './base';
|
||||
|
||||
@ -28,8 +29,8 @@ export class InngestJobProvider extends BaseJobProvider {
|
||||
static getInstance() {
|
||||
if (!this._instance) {
|
||||
const client = new InngestClient({
|
||||
id: process.env.NEXT_PRIVATE_INNGEST_APP_ID || 'documenso-app',
|
||||
eventKey: process.env.INNGEST_EVENT_KEY || process.env.NEXT_PRIVATE_INNGEST_EVENT_KEY,
|
||||
id: env('NEXT_PRIVATE_INNGEST_APP_ID') || 'documenso-app',
|
||||
eventKey: env('INNGEST_EVENT_KEY') || env('NEXT_PRIVATE_INNGEST_EVENT_KEY'),
|
||||
});
|
||||
|
||||
this._instance = new InngestJobProvider({ client });
|
||||
|
||||
@ -2,6 +2,7 @@ import { createPagesRoute } from '@trigger.dev/nextjs';
|
||||
import type { IO } from '@trigger.dev/sdk';
|
||||
import { TriggerClient, eventTrigger } from '@trigger.dev/sdk';
|
||||
|
||||
import { env } from '../../utils/env';
|
||||
import type { JobDefinition, JobRunIO, SimpleTriggerJobOptions } from './_internal/job';
|
||||
import { BaseJobProvider } from './base';
|
||||
|
||||
@ -20,8 +21,8 @@ export class TriggerJobProvider extends BaseJobProvider {
|
||||
if (!this._instance) {
|
||||
const client = new TriggerClient({
|
||||
id: 'documenso-app',
|
||||
apiKey: process.env.NEXT_PRIVATE_TRIGGER_API_KEY,
|
||||
apiUrl: process.env.NEXT_PRIVATE_TRIGGER_API_URL,
|
||||
apiKey: env('NEXT_PRIVATE_TRIGGER_API_KEY'),
|
||||
apiUrl: env('NEXT_PRIVATE_TRIGGER_API_URL'),
|
||||
});
|
||||
|
||||
this._instance = new TriggerJobProvider({ client });
|
||||
|
||||
@ -10,8 +10,8 @@ import type { JWT } from 'next-auth/jwt';
|
||||
import CredentialsProvider from 'next-auth/providers/credentials';
|
||||
import type { GoogleProfile } from 'next-auth/providers/google';
|
||||
import GoogleProvider from 'next-auth/providers/google';
|
||||
import { env } from 'next-runtime-env';
|
||||
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { formatSecureCookieName, useSecureCookies } from '../constants/auth';
|
||||
|
||||
@ -1,24 +1,28 @@
|
||||
export const isErrorCode = (code: unknown): code is ErrorCode => {
|
||||
return typeof code === 'string' && code in ErrorCode;
|
||||
};
|
||||
// export const isErrorCode = (code: unknown): code is ErrorCode => {
|
||||
// return typeof code === 'string' && code in ErrorCode;
|
||||
// };
|
||||
|
||||
export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
|
||||
// export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
|
||||
|
||||
export const ErrorCode = {
|
||||
INCORRECT_EMAIL_PASSWORD: 'INCORRECT_EMAIL_PASSWORD',
|
||||
USER_MISSING_PASSWORD: 'USER_MISSING_PASSWORD',
|
||||
CREDENTIALS_NOT_FOUND: 'CREDENTIALS_NOT_FOUND',
|
||||
INTERNAL_SEVER_ERROR: 'INTERNAL_SEVER_ERROR',
|
||||
TWO_FACTOR_ALREADY_ENABLED: 'TWO_FACTOR_ALREADY_ENABLED',
|
||||
TWO_FACTOR_SETUP_REQUIRED: 'TWO_FACTOR_SETUP_REQUIRED',
|
||||
TWO_FACTOR_MISSING_SECRET: 'TWO_FACTOR_MISSING_SECRET',
|
||||
TWO_FACTOR_MISSING_CREDENTIALS: 'TWO_FACTOR_MISSING_CREDENTIALS',
|
||||
INCORRECT_TWO_FACTOR_CODE: 'INCORRECT_TWO_FACTOR_CODE',
|
||||
INCORRECT_TWO_FACTOR_BACKUP_CODE: 'INCORRECT_TWO_FACTOR_BACKUP_CODE',
|
||||
INCORRECT_IDENTITY_PROVIDER: 'INCORRECT_IDENTITY_PROVIDER',
|
||||
INCORRECT_PASSWORD: 'INCORRECT_PASSWORD',
|
||||
MISSING_ENCRYPTION_KEY: 'MISSING_ENCRYPTION_KEY',
|
||||
MISSING_BACKUP_CODE: 'MISSING_BACKUP_CODE',
|
||||
UNVERIFIED_EMAIL: 'UNVERIFIED_EMAIL',
|
||||
ACCOUNT_DISABLED: 'ACCOUNT_DISABLED',
|
||||
} as const;
|
||||
// Todo: Delete file
|
||||
// Todo: Delete file
|
||||
// Todo: Delete file
|
||||
// Todo: Delete file
|
||||
// export const ErrorCode = {
|
||||
// INCORRECT_EMAIL_PASSWORD: 'INCORRECT_EMAIL_PASSWORD',
|
||||
// USER_MISSING_PASSWORD: 'USER_MISSING_PASSWORD',
|
||||
// CREDENTIALS_NOT_FOUND: 'CREDENTIALS_NOT_FOUND',
|
||||
// INTERNAL_SEVER_ERROR: 'INTERNAL_SEVER_ERROR',
|
||||
// TWO_FACTOR_ALREADY_ENABLED: 'TWO_FACTOR_ALREADY_ENABLED',
|
||||
// TWO_FACTOR_SETUP_REQUIRED: 'TWO_FACTOR_SETUP_REQUIRED',
|
||||
// TWO_FACTOR_MISSING_SECRET: 'TWO_FACTOR_MISSING_SECRET',
|
||||
// TWO_FACTOR_MISSING_CREDENTIALS: 'TWO_FACTOR_MISSING_CREDENTIALS',
|
||||
// INCORRECT_TWO_FACTOR_CODE: 'INCORRECT_TWO_FACTOR_CODE',
|
||||
// INCORRECT_TWO_FACTOR_BACKUP_CODE: 'INCORRECT_TWO_FACTOR_BACKUP_CODE',
|
||||
// INCORRECT_IDENTITY_PROVIDER: 'INCORRECT_IDENTITY_PROVIDER',
|
||||
// INCORRECT_PASSWORD: 'INCORRECT_PASSWORD',
|
||||
// MISSING_ENCRYPTION_KEY: 'MISSING_ENCRYPTION_KEY',
|
||||
// MISSING_BACKUP_CODE: 'MISSING_BACKUP_CODE',
|
||||
// UNVERIFIED_EMAIL: 'UNVERIFIED_EMAIL',
|
||||
// ACCOUNT_DISABLED: 'ACCOUNT_DISABLED',
|
||||
// } as const;
|
||||
|
||||
@ -3,7 +3,6 @@ import { base32 } from '@scure/base';
|
||||
import crypto from 'crypto';
|
||||
import { createTOTPKeyURI } from 'oslo/otp';
|
||||
|
||||
import { ErrorCode } from '@documenso/lib/next-auth/error-codes';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { DOCUMENSO_ENCRYPTION_KEY } from '../../constants/crypto';
|
||||
@ -21,7 +20,7 @@ export const setupTwoFactorAuthentication = async ({
|
||||
const key = DOCUMENSO_ENCRYPTION_KEY;
|
||||
|
||||
if (!key) {
|
||||
throw new Error(ErrorCode.MISSING_ENCRYPTION_KEY);
|
||||
throw new Error('MISSING_ENCRYPTION_KEY');
|
||||
}
|
||||
|
||||
const secret = crypto.randomBytes(10);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { User } from '@prisma/client';
|
||||
|
||||
import { ErrorCode } from '../../next-auth/error-codes';
|
||||
import { AppError } from '../../errors/app-error';
|
||||
import { verifyTwoFactorAuthenticationToken } from './verify-2fa-token';
|
||||
import { verifyBackupCode } from './verify-backup-code';
|
||||
|
||||
@ -16,11 +16,11 @@ export const validateTwoFactorAuthentication = async ({
|
||||
user,
|
||||
}: ValidateTwoFactorAuthenticationOptions) => {
|
||||
if (!user.twoFactorEnabled) {
|
||||
throw new Error(ErrorCode.TWO_FACTOR_SETUP_REQUIRED);
|
||||
throw new AppError('TWO_FACTOR_SETUP_REQUIRED');
|
||||
}
|
||||
|
||||
if (!user.twoFactorSecret) {
|
||||
throw new Error(ErrorCode.TWO_FACTOR_MISSING_SECRET);
|
||||
throw new AppError('TWO_FACTOR_MISSING_SECRET');
|
||||
}
|
||||
|
||||
if (totpCode) {
|
||||
@ -31,5 +31,5 @@ export const validateTwoFactorAuthentication = async ({
|
||||
return await verifyBackupCode({ user, backupCode });
|
||||
}
|
||||
|
||||
throw new Error(ErrorCode.TWO_FACTOR_MISSING_CREDENTIALS);
|
||||
throw new AppError('TWO_FACTOR_MISSING_CREDENTIALS');
|
||||
};
|
||||
|
||||
@ -8,6 +8,7 @@ import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { getI18nInstance } from '../../client-only/providers/i18n-server';
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app';
|
||||
import { env } from '../../utils/env';
|
||||
import { renderEmailWithI18N } from '../../utils/render-email-with-i18n';
|
||||
|
||||
export interface SendConfirmationEmailProps {
|
||||
@ -15,8 +16,8 @@ export interface SendConfirmationEmailProps {
|
||||
}
|
||||
|
||||
export const sendConfirmationEmail = async ({ userId }: SendConfirmationEmailProps) => {
|
||||
const NEXT_PRIVATE_SMTP_FROM_NAME = process.env.NEXT_PRIVATE_SMTP_FROM_NAME;
|
||||
const NEXT_PRIVATE_SMTP_FROM_ADDRESS = process.env.NEXT_PRIVATE_SMTP_FROM_ADDRESS;
|
||||
const NEXT_PRIVATE_SMTP_FROM_NAME = env('NEXT_PRIVATE_SMTP_FROM_NAME');
|
||||
const NEXT_PRIVATE_SMTP_FROM_ADDRESS = env('NEXT_PRIVATE_SMTP_FROM_ADDRESS');
|
||||
|
||||
const user = await prisma.user.findFirstOrThrow({
|
||||
where: {
|
||||
|
||||
@ -8,6 +8,7 @@ import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { getI18nInstance } from '../../client-only/providers/i18n-server';
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app';
|
||||
import { env } from '../../utils/env';
|
||||
import { renderEmailWithI18N } from '../../utils/render-email-with-i18n';
|
||||
|
||||
export interface SendForgotPasswordOptions {
|
||||
@ -55,8 +56,8 @@ export const sendForgotPassword = async ({ userId }: SendForgotPasswordOptions)
|
||||
name: user.name || '',
|
||||
},
|
||||
from: {
|
||||
name: process.env.NEXT_PRIVATE_SMTP_FROM_NAME || 'Documenso',
|
||||
address: process.env.NEXT_PRIVATE_SMTP_FROM_ADDRESS || 'noreply@documenso.com',
|
||||
name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso',
|
||||
address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com',
|
||||
},
|
||||
subject: i18n._(msg`Forgot Password?`),
|
||||
html,
|
||||
|
||||
@ -5,6 +5,7 @@ import { ResetPasswordTemplate } from '@documenso/email/templates/reset-password
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app';
|
||||
import { env } from '../../utils/env';
|
||||
import { renderEmailWithI18N } from '../../utils/render-email-with-i18n';
|
||||
|
||||
export interface SendResetPasswordOptions {
|
||||
@ -37,8 +38,8 @@ export const sendResetPassword = async ({ userId }: SendResetPasswordOptions) =>
|
||||
name: user.name || '',
|
||||
},
|
||||
from: {
|
||||
name: process.env.NEXT_PRIVATE_SMTP_FROM_NAME || 'Documenso',
|
||||
address: process.env.NEXT_PRIVATE_SMTP_FROM_ADDRESS || 'noreply@documenso.com',
|
||||
name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso',
|
||||
address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com',
|
||||
},
|
||||
subject: 'Password Reset Success!',
|
||||
html,
|
||||
|
||||
@ -14,6 +14,7 @@ import { extractDerivedDocumentEmailSettings } from '../../types/document-email'
|
||||
import type { RequestMetadata } from '../../universal/extract-request-metadata';
|
||||
import { getFile } from '../../universal/upload/get-file';
|
||||
import { createDocumentAuditLogData } from '../../utils/document-audit-logs';
|
||||
import { env } from '../../utils/env';
|
||||
import { renderCustomEmailTemplate } from '../../utils/render-custom-email-template';
|
||||
import { renderEmailWithI18N } from '../../utils/render-email-with-i18n';
|
||||
import { teamGlobalSettingsToBranding } from '../../utils/team-global-settings-to-branding';
|
||||
@ -113,8 +114,8 @@ export const sendCompletedEmail = async ({ documentId, requestMetadata }: SendDo
|
||||
},
|
||||
],
|
||||
from: {
|
||||
name: process.env.NEXT_PRIVATE_SMTP_FROM_NAME || 'Documenso',
|
||||
address: process.env.NEXT_PRIVATE_SMTP_FROM_ADDRESS || 'noreply@documenso.com',
|
||||
name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso',
|
||||
address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com',
|
||||
},
|
||||
subject: i18n._(msg`Signing Complete!`),
|
||||
html,
|
||||
@ -190,8 +191,8 @@ export const sendCompletedEmail = async ({ documentId, requestMetadata }: SendDo
|
||||
},
|
||||
],
|
||||
from: {
|
||||
name: process.env.NEXT_PRIVATE_SMTP_FROM_NAME || 'Documenso',
|
||||
address: process.env.NEXT_PRIVATE_SMTP_FROM_ADDRESS || 'noreply@documenso.com',
|
||||
name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso',
|
||||
address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com',
|
||||
},
|
||||
subject:
|
||||
isDirectTemplate && document.documentMeta?.subject
|
||||
|
||||
@ -10,6 +10,7 @@ import { getI18nInstance } from '../../client-only/providers/i18n-server';
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app';
|
||||
import { AppError, AppErrorCode } from '../../errors/app-error';
|
||||
import { extractDerivedDocumentEmailSettings } from '../../types/document-email';
|
||||
import { env } from '../../utils/env';
|
||||
import { renderEmailWithI18N } from '../../utils/render-email-with-i18n';
|
||||
import { teamGlobalSettingsToBranding } from '../../utils/team-global-settings-to-branding';
|
||||
|
||||
@ -79,8 +80,8 @@ export const sendDeleteEmail = async ({ documentId, reason }: SendDeleteEmailOpt
|
||||
name: name || '',
|
||||
},
|
||||
from: {
|
||||
name: process.env.NEXT_PRIVATE_SMTP_FROM_NAME || 'Documenso',
|
||||
address: process.env.NEXT_PRIVATE_SMTP_FROM_ADDRESS || 'noreply@documenso.com',
|
||||
name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso',
|
||||
address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com',
|
||||
},
|
||||
subject: i18n._(msg`Document Deleted!`),
|
||||
html,
|
||||
|
||||
@ -9,6 +9,7 @@ import { prisma } from '@documenso/prisma';
|
||||
import { getI18nInstance } from '../../client-only/providers/i18n-server';
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app';
|
||||
import { extractDerivedDocumentEmailSettings } from '../../types/document-email';
|
||||
import { env } from '../../utils/env';
|
||||
import { renderEmailWithI18N } from '../../utils/render-email-with-i18n';
|
||||
import { teamGlobalSettingsToBranding } from '../../utils/team-global-settings-to-branding';
|
||||
|
||||
@ -90,8 +91,8 @@ export const sendPendingEmail = async ({ documentId, recipientId }: SendPendingE
|
||||
name,
|
||||
},
|
||||
from: {
|
||||
name: process.env.NEXT_PRIVATE_SMTP_FROM_NAME || 'Documenso',
|
||||
address: process.env.NEXT_PRIVATE_SMTP_FROM_ADDRESS || 'noreply@documenso.com',
|
||||
name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso',
|
||||
address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com',
|
||||
},
|
||||
subject: i18n._(msg`Waiting for others to complete signing.`),
|
||||
html,
|
||||
|
||||
@ -3,6 +3,7 @@ import type { Browser } from 'playwright';
|
||||
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app';
|
||||
import { type SupportedLanguageCodes, isValidLanguageCode } from '../../constants/i18n';
|
||||
import { env } from '../../utils/env';
|
||||
import { encryptSecondaryData } from '../crypto/encrypt';
|
||||
|
||||
export type GetCertificatePdfOptions = {
|
||||
@ -21,10 +22,10 @@ export const getCertificatePdf = async ({ documentId, language }: GetCertificate
|
||||
|
||||
let browser: Browser;
|
||||
|
||||
if (process.env.NEXT_PRIVATE_BROWSERLESS_URL) {
|
||||
if (env('NEXT_PRIVATE_BROWSERLESS_URL')) {
|
||||
// !: Use CDP rather than the default `connect` method to avoid coupling to the playwright version.
|
||||
// !: Previously we would have to keep the playwright version in sync with the browserless version to avoid errors.
|
||||
browser = await chromium.connectOverCDP(process.env.NEXT_PRIVATE_BROWSERLESS_URL);
|
||||
browser = await chromium.connectOverCDP(env('NEXT_PRIVATE_BROWSERLESS_URL'));
|
||||
} else {
|
||||
browser = await chromium.launch();
|
||||
}
|
||||
|
||||
@ -25,15 +25,12 @@ import {
|
||||
ZRadioFieldMeta,
|
||||
ZTextFieldMeta,
|
||||
} from '../../types/field-meta';
|
||||
import { env } from '../../utils/env';
|
||||
|
||||
export const insertFieldInPDF = async (pdf: PDFDocument, field: FieldWithSignature) => {
|
||||
const fontCaveat = await fetch(process.env.FONT_CAVEAT_URI).then(async (res) =>
|
||||
res.arrayBuffer(),
|
||||
);
|
||||
const fontCaveat = await fetch(env('FONT_CAVEAT_URI')).then(async (res) => res.arrayBuffer());
|
||||
|
||||
const fontNoto = await fetch(process.env.FONT_NOTO_SANS_URI).then(async (res) =>
|
||||
res.arrayBuffer(),
|
||||
);
|
||||
const fontNoto = await fetch(env('FONT_NOTO_SANS_URI')).then(async (res) => res.arrayBuffer());
|
||||
|
||||
const isSignatureField = isSignatureFieldType(field.type);
|
||||
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
/* eslint-disable turbo/no-undeclared-env-vars */
|
||||
import { Redis } from '@upstash/redis';
|
||||
|
||||
import { env } from '../../utils/env';
|
||||
|
||||
// !: We're null coalescing here because we don't want local builds to fail.
|
||||
export const redis = new Redis({
|
||||
url: process.env.NEXT_PRIVATE_REDIS_URL ?? '',
|
||||
token: process.env.NEXT_PRIVATE_REDIS_TOKEN ?? '',
|
||||
url: env('NEXT_PRIVATE_REDIS_URL') ?? '',
|
||||
token: env('NEXT_PRIVATE_REDIS_TOKEN') ?? '',
|
||||
});
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
/// <reference types="./stripe.d.ts" />
|
||||
import Stripe from 'stripe';
|
||||
|
||||
export const stripe = new Stripe(process.env.NEXT_PRIVATE_STRIPE_API_KEY ?? '', {
|
||||
import { env } from '../../utils/env';
|
||||
|
||||
export const stripe = new Stripe(env('NEXT_PRIVATE_STRIPE_API_KEY') ?? '', {
|
||||
apiVersion: '2022-11-15',
|
||||
typescript: true,
|
||||
});
|
||||
|
||||
@ -15,6 +15,7 @@ import { createTokenVerification } from '@documenso/lib/utils/token-verification
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { getI18nInstance } from '../../client-only/providers/i18n-server';
|
||||
import { env } from '../../utils/env';
|
||||
import { renderEmailWithI18N } from '../../utils/render-email-with-i18n';
|
||||
import { teamGlobalSettingsToBranding } from '../../utils/team-global-settings-to-branding';
|
||||
|
||||
@ -122,7 +123,7 @@ export const sendTeamEmailVerificationEmail = async (
|
||||
teamGlobalSettings?: TeamGlobalSettings | null;
|
||||
},
|
||||
) => {
|
||||
const assetBaseUrl = process.env.NEXT_PUBLIC_WEBAPP_URL || 'http://localhost:3000';
|
||||
const assetBaseUrl = env('NEXT_PUBLIC_WEBAPP_URL') || 'http://localhost:3000';
|
||||
|
||||
const template = createElement(ConfirmTeamEmailTemplate, {
|
||||
assetBaseUrl,
|
||||
|
||||
@ -10,6 +10,7 @@ import { TEAM_MEMBER_ROLE_PERMISSIONS_MAP } from '@documenso/lib/constants/teams
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { getI18nInstance } from '../../client-only/providers/i18n-server';
|
||||
import { env } from '../../utils/env';
|
||||
import { renderEmailWithI18N } from '../../utils/render-email-with-i18n';
|
||||
import { teamGlobalSettingsToBranding } from '../../utils/team-global-settings-to-branding';
|
||||
|
||||
@ -69,7 +70,7 @@ export const deleteTeamEmail = async ({ userId, userEmail, teamId }: DeleteTeamE
|
||||
});
|
||||
|
||||
try {
|
||||
const assetBaseUrl = process.env.NEXT_PUBLIC_WEBAPP_URL || 'http://localhost:3000';
|
||||
const assetBaseUrl = env('NEXT_PUBLIC_WEBAPP_URL') || 'http://localhost:3000';
|
||||
|
||||
const template = createElement(TeamEmailRemovedTemplate, {
|
||||
assetBaseUrl,
|
||||
|
||||
@ -44,6 +44,7 @@ import {
|
||||
createRecipientAuthOptions,
|
||||
extractDocumentAuthMethods,
|
||||
} from '../../utils/document-auth';
|
||||
import { env } from '../../utils/env';
|
||||
import { renderEmailWithI18N } from '../../utils/render-email-with-i18n';
|
||||
import { teamGlobalSettingsToBranding } from '../../utils/team-global-settings-to-branding';
|
||||
import { formatDocumentsPath } from '../../utils/teams';
|
||||
@ -582,8 +583,8 @@ export const createDocumentFromDirectTemplate = async ({
|
||||
},
|
||||
],
|
||||
from: {
|
||||
name: process.env.NEXT_PRIVATE_SMTP_FROM_NAME || 'Documenso',
|
||||
address: process.env.NEXT_PRIVATE_SMTP_FROM_ADDRESS || 'noreply@documenso.com',
|
||||
name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso',
|
||||
address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com',
|
||||
},
|
||||
subject: i18n._(msg`Document created from direct template`),
|
||||
html,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { hash } from '@node-rs/bcrypt';
|
||||
import { IdentityProvider, TeamMemberInviteStatus } from '@prisma/client';
|
||||
import { TeamMemberInviteStatus } from '@prisma/client';
|
||||
|
||||
import { getStripeCustomerByUser } from '@documenso/ee/server-only/stripe/get-customer';
|
||||
import { updateSubscriptionItemQuantity } from '@documenso/ee/server-only/stripe/update-subscription-item-quantity';
|
||||
@ -39,22 +39,35 @@ export const createUser = async ({ name, email, password, signature, url }: Crea
|
||||
});
|
||||
|
||||
if (urlExists) {
|
||||
throw new AppError(AppErrorCode.PROFILE_URL_TAKEN, {
|
||||
throw new AppError('PROFILE_URL_TAKEN', {
|
||||
message: 'Profile username is taken',
|
||||
userMessage: 'The profile username is already taken',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
name,
|
||||
email: email.toLowerCase(),
|
||||
password: hashedPassword,
|
||||
signature,
|
||||
identityProvider: IdentityProvider.DOCUMENSO,
|
||||
url,
|
||||
},
|
||||
const user = await prisma.$transaction(async (tx) => {
|
||||
const user = await tx.user.create({
|
||||
data: {
|
||||
name,
|
||||
email: email.toLowerCase(),
|
||||
password: hashedPassword, // Todo: Drop password.
|
||||
signature,
|
||||
url,
|
||||
},
|
||||
});
|
||||
|
||||
await tx.account.create({
|
||||
data: {
|
||||
userId: user.id,
|
||||
type: 'emailPassword', // Todo
|
||||
provider: 'DOCUMENSO', // Todo: Enums
|
||||
providerAccountId: user.id.toString(),
|
||||
password: hashedPassword,
|
||||
},
|
||||
});
|
||||
|
||||
return user;
|
||||
});
|
||||
|
||||
const acceptedTeamInvites = await prisma.teamMemberInvite.findMany({
|
||||
|
||||
@ -26,7 +26,10 @@ export const verifyEmail = async ({ token }: VerifyEmailProps) => {
|
||||
});
|
||||
|
||||
if (!verificationToken) {
|
||||
return EMAIL_VERIFICATION_STATE.NOT_FOUND;
|
||||
return {
|
||||
state: EMAIL_VERIFICATION_STATE.NOT_FOUND,
|
||||
userId: null,
|
||||
};
|
||||
}
|
||||
|
||||
// check if the token is valid or expired
|
||||
@ -55,11 +58,17 @@ export const verifyEmail = async ({ token }: VerifyEmailProps) => {
|
||||
});
|
||||
}
|
||||
|
||||
return EMAIL_VERIFICATION_STATE.EXPIRED;
|
||||
return {
|
||||
state: EMAIL_VERIFICATION_STATE.EXPIRED,
|
||||
userId: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (verificationToken.completed) {
|
||||
return EMAIL_VERIFICATION_STATE.ALREADY_VERIFIED;
|
||||
return {
|
||||
state: EMAIL_VERIFICATION_STATE.ALREADY_VERIFIED,
|
||||
userId: null,
|
||||
};
|
||||
}
|
||||
|
||||
const [updatedUser] = await prisma.$transaction([
|
||||
@ -94,5 +103,8 @@ export const verifyEmail = async ({ token }: VerifyEmailProps) => {
|
||||
throw new Error('Something went wrong while verifying your email. Please try again.');
|
||||
}
|
||||
|
||||
return EMAIL_VERIFICATION_STATE.VERIFIED;
|
||||
return {
|
||||
state: EMAIL_VERIFICATION_STATE.VERIFIED,
|
||||
userId: updatedUser.id,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"extends": "@documenso/tsconfig/react-library.json",
|
||||
"compilerOptions": {
|
||||
"types": ["@documenso/tsconfig/process-env.d.ts"],
|
||||
"types": ["@documenso/tsconfig/process-env.d.ts", "vite/client"],
|
||||
"moduleResolution": "Bundler"
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.tsx", "**/*.d.ts"],
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
/* eslint-disable turbo/no-undeclared-env-vars */
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '../constants/app';
|
||||
import { env } from '../utils/env';
|
||||
|
||||
export const getBaseUrl = () => {
|
||||
if (typeof window !== 'undefined') {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (process.env.VERCEL_URL) {
|
||||
return `https://${process.env.VERCEL_URL}`;
|
||||
if (env('VERCEL_URL')) {
|
||||
return `https://${env('VERCEL_URL')}`;
|
||||
}
|
||||
|
||||
const webAppUrl = NEXT_PUBLIC_WEBAPP_URL();
|
||||
@ -16,5 +17,5 @@ export const getBaseUrl = () => {
|
||||
return webAppUrl;
|
||||
}
|
||||
|
||||
return `http://localhost:${process.env.PORT ?? 3000}`;
|
||||
return `http://localhost:${env('PORT') ?? 3000}`;
|
||||
};
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { DocumentDataType } from '@prisma/client';
|
||||
import { base64 } from '@scure/base';
|
||||
import { env } from 'next-runtime-env';
|
||||
import { PDFDocument } from 'pdf-lib';
|
||||
import { match } from 'ts-pattern';
|
||||
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
|
||||
import { AppError } from '../../errors/app-error';
|
||||
import { createDocumentData } from '../../server-only/document-data/create-document-data';
|
||||
|
||||
|
||||
@ -1,8 +1,3 @@
|
||||
'use server';
|
||||
|
||||
import { headers } from 'next/headers';
|
||||
import { NextRequest } from 'next/server';
|
||||
|
||||
import {
|
||||
DeleteObjectCommand,
|
||||
GetObjectCommand,
|
||||
@ -10,10 +5,11 @@ import {
|
||||
S3Client,
|
||||
} from '@aws-sdk/client-s3';
|
||||
import slugify from '@sindresorhus/slugify';
|
||||
import { type JWT, getToken } from 'next-auth/jwt';
|
||||
import { env } from 'next-runtime-env';
|
||||
import { type JWT } from 'next-auth/jwt';
|
||||
import path from 'node:path';
|
||||
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
|
||||
import { APP_BASE_URL } from '../../constants/app';
|
||||
import { ONE_HOUR, ONE_SECOND } from '../../constants/time';
|
||||
import { alphaid } from '../id';
|
||||
@ -23,16 +19,17 @@ export const getPresignPostUrl = async (fileName: string, contentType: string) =
|
||||
|
||||
const { getSignedUrl } = await import('@aws-sdk/s3-request-presigner');
|
||||
|
||||
let token: JWT | null = null;
|
||||
const token: JWT | null = null;
|
||||
|
||||
try {
|
||||
const baseUrl = APP_BASE_URL() ?? 'http://localhost:3000';
|
||||
|
||||
token = await getToken({
|
||||
req: new NextRequest(baseUrl, {
|
||||
headers: headers(),
|
||||
}),
|
||||
});
|
||||
// Todo
|
||||
// token = await getToken({
|
||||
// req: new NextRequest(baseUrl, {
|
||||
// headers: headers(),
|
||||
// }),
|
||||
// });
|
||||
} catch (err) {
|
||||
// Non server-component environment
|
||||
}
|
||||
@ -47,7 +44,7 @@ export const getPresignPostUrl = async (fileName: string, contentType: string) =
|
||||
}
|
||||
|
||||
const putObjectCommand = new PutObjectCommand({
|
||||
Bucket: process.env.NEXT_PRIVATE_UPLOAD_BUCKET,
|
||||
Bucket: env('NEXT_PRIVATE_UPLOAD_BUCKET'),
|
||||
Key: key,
|
||||
ContentType: contentType,
|
||||
});
|
||||
@ -65,7 +62,7 @@ export const getAbsolutePresignPostUrl = async (key: string) => {
|
||||
const { getSignedUrl: getS3SignedUrl } = await import('@aws-sdk/s3-request-presigner');
|
||||
|
||||
const putObjectCommand = new PutObjectCommand({
|
||||
Bucket: process.env.NEXT_PRIVATE_UPLOAD_BUCKET,
|
||||
Bucket: env('NEXT_PRIVATE_UPLOAD_BUCKET'),
|
||||
Key: key,
|
||||
});
|
||||
|
||||
@ -77,15 +74,15 @@ export const getAbsolutePresignPostUrl = async (key: string) => {
|
||||
};
|
||||
|
||||
export const getPresignGetUrl = async (key: string) => {
|
||||
if (process.env.NEXT_PRIVATE_UPLOAD_DISTRIBUTION_DOMAIN) {
|
||||
const distributionUrl = new URL(key, `${process.env.NEXT_PRIVATE_UPLOAD_DISTRIBUTION_DOMAIN}`);
|
||||
if (env('NEXT_PRIVATE_UPLOAD_DISTRIBUTION_DOMAIN')) {
|
||||
const distributionUrl = new URL(key, `${env('NEXT_PRIVATE_UPLOAD_DISTRIBUTION_DOMAIN')}`);
|
||||
|
||||
const { getSignedUrl: getCloudfrontSignedUrl } = await import('@aws-sdk/cloudfront-signer');
|
||||
|
||||
const url = getCloudfrontSignedUrl({
|
||||
url: distributionUrl.toString(),
|
||||
keyPairId: `${process.env.NEXT_PRIVATE_UPLOAD_DISTRIBUTION_KEY_ID}`,
|
||||
privateKey: `${process.env.NEXT_PRIVATE_UPLOAD_DISTRIBUTION_KEY_CONTENTS}`,
|
||||
keyPairId: `${env('NEXT_PRIVATE_UPLOAD_DISTRIBUTION_KEY_ID')}`,
|
||||
privateKey: `${env('NEXT_PRIVATE_UPLOAD_DISTRIBUTION_KEY_CONTENTS')}`,
|
||||
dateLessThan: new Date(Date.now() + ONE_HOUR).toISOString(),
|
||||
});
|
||||
|
||||
@ -97,7 +94,7 @@ export const getPresignGetUrl = async (key: string) => {
|
||||
const { getSignedUrl: getS3SignedUrl } = await import('@aws-sdk/s3-request-presigner');
|
||||
|
||||
const getObjectCommand = new GetObjectCommand({
|
||||
Bucket: process.env.NEXT_PRIVATE_UPLOAD_BUCKET,
|
||||
Bucket: env('NEXT_PRIVATE_UPLOAD_BUCKET'),
|
||||
Key: key,
|
||||
});
|
||||
|
||||
@ -113,7 +110,7 @@ export const deleteS3File = async (key: string) => {
|
||||
|
||||
await client.send(
|
||||
new DeleteObjectCommand({
|
||||
Bucket: process.env.NEXT_PRIVATE_UPLOAD_BUCKET,
|
||||
Bucket: env('NEXT_PRIVATE_UPLOAD_BUCKET'),
|
||||
Key: key,
|
||||
}),
|
||||
);
|
||||
@ -127,17 +124,16 @@ const getS3Client = () => {
|
||||
}
|
||||
|
||||
const hasCredentials =
|
||||
process.env.NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID &&
|
||||
process.env.NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY;
|
||||
env('NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID') && env('NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY');
|
||||
|
||||
return new S3Client({
|
||||
endpoint: process.env.NEXT_PRIVATE_UPLOAD_ENDPOINT || undefined,
|
||||
forcePathStyle: process.env.NEXT_PRIVATE_UPLOAD_FORCE_PATH_STYLE === 'true',
|
||||
region: process.env.NEXT_PRIVATE_UPLOAD_REGION || 'us-east-1',
|
||||
endpoint: env('NEXT_PRIVATE_UPLOAD_ENDPOINT') || undefined,
|
||||
forcePathStyle: env('NEXT_PRIVATE_UPLOAD_FORCE_PATH_STYLE') === 'true',
|
||||
region: env('NEXT_PRIVATE_UPLOAD_REGION') || 'us-east-1',
|
||||
credentials: hasCredentials
|
||||
? {
|
||||
accessKeyId: String(process.env.NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID),
|
||||
secretAccessKey: String(process.env.NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY),
|
||||
accessKeyId: String(env('NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID')),
|
||||
secretAccessKey: String(env('NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY')),
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
|
||||
18
packages/lib/utils/env.ts
Normal file
18
packages/lib/utils/env.ts
Normal file
@ -0,0 +1,18 @@
|
||||
/// <reference types="@documenso/tsconfig/process-env.d.ts" />
|
||||
|
||||
type EnvironmentVariable = keyof NodeJS.ProcessEnv;
|
||||
|
||||
export const env = (variable: EnvironmentVariable | (string & {})) => {
|
||||
// console.log({
|
||||
// ['typeof window']: typeof window,
|
||||
// ['process.env']: process.env,
|
||||
// ['window.__ENV__']: typeof window !== 'undefined' && window.__ENV__,
|
||||
// });
|
||||
|
||||
// This may need ot be import.meta.env.SSR depending on vite.
|
||||
if (typeof window !== 'undefined' && typeof window.__ENV__ === 'object') {
|
||||
return window.__ENV__[variable];
|
||||
}
|
||||
|
||||
return process.env[variable];
|
||||
};
|
||||
@ -5,9 +5,10 @@ import type { I18n, MessageDescriptor } from '@lingui/core';
|
||||
import { IS_APP_WEB, IS_APP_WEB_I18N_ENABLED } from '../constants/app';
|
||||
import type { I18nLocaleData, SupportedLanguageCodes } from '../constants/i18n';
|
||||
import { APP_I18N_OPTIONS } from '../constants/i18n';
|
||||
import { env } from './env';
|
||||
|
||||
export async function dynamicActivate(i18nInstance: I18n, locale: string) {
|
||||
const extension = process.env.NODE_ENV === 'development' ? 'po' : 'js';
|
||||
const extension = env('NODE_ENV') === 'development' ? 'po' : 'js';
|
||||
|
||||
// const { messages } = await import(`../translations/${locale}/web.${extension}`);
|
||||
// todo
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import Honeybadger from '@honeybadger-io/js';
|
||||
|
||||
import { env } from './env';
|
||||
|
||||
export const buildLogger = () => {
|
||||
if (process.env.NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY) {
|
||||
if (env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY')) {
|
||||
return new HoneybadgerLogger();
|
||||
}
|
||||
|
||||
@ -45,12 +47,12 @@ class DefaultLogger implements Logger {
|
||||
|
||||
class HoneybadgerLogger implements Logger {
|
||||
constructor() {
|
||||
if (!process.env.NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY) {
|
||||
if (!env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY')) {
|
||||
throw new Error('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY is not set');
|
||||
}
|
||||
|
||||
Honeybadger.configure({
|
||||
apiKey: process.env.NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY,
|
||||
apiKey: env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY'),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user