【问题标题】:plainToClass from class-transform converts incorrecly类转换中的 plainToClass 转换不正确
【发布时间】:2022-02-02 23:03:55
【问题描述】:

我正在使用 class-transformerclass-validator 包中的 plainToClassvalidateSync 方法,验证总是失败,因为使用 plainToClass 后所有值都未定义

带有控制台日志的代码示例

import { plainToClass } from 'class-transformer';
import { IsEnum, IsNumber, IsString, validateSync } from 'class-validator';

enum Env {
  Development = 'development',
  Production = 'production',
  Test = 'test',
  Provision = 'provision',
}

class EnvVars {
  @IsEnum(Env) NODE_ENV: Env;
  @IsNumber() PORT: number;

  @IsString() APP_NAME: string;
  @IsString() APP_KEY: string;
  @IsString() APP_SECRET: string;
}

export const validateEnv = (config: Record<string, unknown>) => {
  const validatedConfig = plainToClass(EnvVars, config, {
    enableImplicitConversion: true,
  });

  const {
    NODE_ENV: cNODE_ENV,
    PORT: cPORT,
    APP_NAME: cAPP_NAME,
    APP_KEY: cAPP_KEY,
    APP_SECRET: cAPP_SECRET,
  } = config;

  console.log('config', {
    cNODE_ENV,
    cPORT,
    cAPP_NAME,
    cAPP_KEY,
    cAPP_SECRET,
  });

  const {
    NODE_ENV: vNODE_ENV,
    PORT: vPORT,
    APP_NAME: vAPP_NAME,
    APP_KEY: vAPP_KEY,
    APP_SECRET: vAPP_SECRET,
  } = validatedConfig;

  console.log('validated', {
    vNODE_ENV,
    vPORT,
    vAPP_NAME,
    vAPP_KEY,
    vAPP_SECRET,
  });

  const errors = validateSync(validatedConfig, {
    skipMissingProperties: false,
  });

  if (errors.length > 0) {
    const missingFields: string[] = [];
    const invalidFields: string[] = [];

    errors.forEach((error) => {
      (typeof error.value === 'undefined' ? missingFields : invalidFields).push(
        error.property,
      );
    });

    let errorMessage =
      'Your .env file was configured incorrectly. ' +
      'Please, check .env.example and fix all invalid or missing fields!';

    if (missingFields.length > 0) {
      errorMessage += '\nMissing fields:';
      missingFields.forEach((field) => {
        errorMessage += `\n\t- ${field}`;
      });
    }

    if (invalidFields.length > 0) {
      errorMessage += '\nInvalid fields:';
      invalidFields.forEach((field) => {
        errorMessage += `\n\t- ${field}`;
      });
    }

    throw new Error(errorMessage);
  }

  return validatedConfig;
};

日志:

config {
  cNODE_ENV: 'development',
  cPORT: '3000',
  cAPP_NAME: 'next-nest-mono',
  cAPP_KEY: 'APP_KEY',
  cAPP_SECRET: 'APP_SECRET'
}
validated {
  vNODE_ENV: undefined,
  vPORT: undefined,
  vAPP_NAME: undefined,
  vAPP_KEY: undefined,
  vAPP_SECRET: undefined
}
[Nest] 36628  - 02/02/2022, 6:10:38 PM   ERROR [Bootstrap] Error: Your .env file was configured incorrectly. Please, check .env.example and fix all invalid or missing fields!
Missing fields:
       - NODE_ENV
       - PORT
       - APP_NAME
       - APP_KEY
       - APP_SECRET

我正在使用带有自定义 webpack 配置的 nestjs。要传递 env 变量,我使用的是 dotenv-cli(例如 dotenv -e .env command)。

webpack.config.js

const webpack = require('webpack');
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const { RunScriptWebpackPlugin } = require('run-script-webpack-plugin');

module.exports = {
  entry: ['webpack/hot/poll?100', './src/main.ts'],
  target: 'node',
  externals: [
    nodeExternals({
      allowlist: ['webpack/hot/poll?100'],
    }),
  ],
  module: {
    rules: [
      {
        test: /.tsx?$/,
        use: 'swc-loader',
        exclude: /node_modules/,
      },
    ],
  },
  mode: 'development',
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new RunScriptWebpackPlugin(),
  ],
  output: {
    path: path.join(__dirname, 'dist'),
  },
};

附:奇怪的是,如果我使用 nest-cli 构建项目并运行它,则仅在开发环境中发生(当我使用自定义 webpack 配置时)不会发生错误。可能是什么问题?我找不到任何解决方案。

附言我检查了process.env,它包含所有必需的变量。

【问题讨论】:

标签: typescript webpack nestjs class-validator class-transformer


【解决方案1】:

.env这样的变量不用自己提供验证逻辑,nest自己做,可以看这里:https://docs.nestjs.com/techniques/configuration

只需使用 Joi 来验证您的架构配置,例如 app.module.ts


import * as Joi from 'joi';

@Module({
  imports: [
    ConfigModule.forRoot({
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid('development', 'production', 'test')
          .default('development'),
        PORT: Joi.number().default(3000),
        APP_NAME: Joi.string().required(),
        APP_KEY: Joi.string().required(),
        APP_SECRET: Joi.string().required()
      }),
      validationOptions: {
        allowUnknown: false,
        abortEarly: true,
      },
    }),
  ],
})
export class AppModule {}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-20
相关资源
最近更新 更多