diff --git a/actions/add.action.ts b/actions/add.action.ts index f6dda09e8..55550bd69 100644 --- a/actions/add.action.ts +++ b/actions/add.action.ts @@ -69,7 +69,7 @@ export class AddAction extends AbstractAction { for (const property in configurationProjects) { if ( - configurationProjects[property].sourceRoot === + configurationProjects[property]!.sourceRoot === configuration.sourceRoot ) { defaultProjectName = property + defaultLabel; @@ -89,7 +89,7 @@ export class AddAction extends AbstractAction { ); const project = answers.appName.replace(defaultLabel, ''); if (project !== configuration.sourceRoot) { - sourceRoot = configurationProjects[project].sourceRoot; + sourceRoot = configurationProjects[project]!.sourceRoot; } } return { name: 'sourceRoot', value: sourceRoot }; diff --git a/actions/build.action.ts b/actions/build.action.ts index f813e3920..afacff9e6 100644 --- a/actions/build.action.ts +++ b/actions/build.action.ts @@ -11,15 +11,11 @@ import { TypeScriptBinaryLoader } from '../lib/compiler/typescript-loader'; import { WatchCompiler } from '../lib/compiler/watch-compiler'; import { WebpackCompiler } from '../lib/compiler/webpack-compiler'; import { WorkspaceUtils } from '../lib/compiler/workspace-utils'; -import { - ConfigurationLoader, - NestConfigurationLoader, -} from '../lib/configuration'; import { defaultOutDir } from '../lib/configuration/defaults'; -import { FileSystemReader } from '../lib/readers'; import { ERROR_PREFIX } from '../lib/ui'; import { AbstractAction } from './abstract.action'; import webpack = require('webpack'); +import { loadConfiguration } from '../lib/utils/load-configuration'; export class BuildAction extends AbstractAction { protected readonly pluginsLoader = new PluginsLoader(); @@ -36,10 +32,6 @@ export class BuildAction extends AbstractAction { this.tsConfigProvider, this.tsLoader, ); - protected readonly fileSystemReader = new FileSystemReader(process.cwd()); - protected readonly loader: ConfigurationLoader = new NestConfigurationLoader( - this.fileSystemReader, - ); protected readonly assetsManager = new AssetsManager(); protected readonly workspaceUtils = new WorkspaceUtils(); @@ -73,9 +65,9 @@ export class BuildAction extends AbstractAction { isDebugEnabled = false, onSuccess?: () => void, ) { - const configFileName = options.find((option) => option.name === 'config')! - .value as string; - const configuration = await this.loader.load(configFileName); + const configFileName = options.find((option) => option.name === 'config') + ?.value as string | undefined; + const configuration = await loadConfiguration(configFileName); const appName = inputs.find((input) => input.name === 'app')! .value as string; @@ -86,9 +78,8 @@ export class BuildAction extends AbstractAction { 'path', options, ); - const { options: tsOptions } = this.tsConfigProvider.getByConfigFilename( - pathToTsconfig, - ); + const { options: tsOptions } = + this.tsConfigProvider.getByConfigFilename(pathToTsconfig); const outDir = tsOptions.outDir || defaultOutDir; const isWebpackEnabled = getValueOrDefault( configuration, @@ -162,7 +153,7 @@ export class BuildAction extends AbstractAction { ): ( config: webpack.Configuration, webpackRef: typeof webpack, - ) => webpack.Configuration | webpack.Configuration { + ) => webpack.Configuration { const pathToWebpackFile = join(process.cwd(), webpackPath); try { return require(pathToWebpackFile); diff --git a/actions/generate.action.ts b/actions/generate.action.ts index 926d5eaab..833d2851a 100644 --- a/actions/generate.action.ts +++ b/actions/generate.action.ts @@ -66,7 +66,7 @@ const generateFiles = async (inputs: Input[]) => { for (const property in configurationProjects) { if ( - configurationProjects[property].sourceRoot === configuration.sourceRoot + configurationProjects[property]!.sourceRoot === configuration.sourceRoot ) { defaultProjectName = property + defaultLabel; break; @@ -86,7 +86,7 @@ const generateFiles = async (inputs: Input[]) => { const project: string = answers.appName.replace(defaultLabel, ''); if (project !== configuration.sourceRoot) { - sourceRoot = configurationProjects[project].sourceRoot; + sourceRoot = configurationProjects[project]!.sourceRoot; } if (answers.appName !== defaultProjectName) { diff --git a/actions/start.action.ts b/actions/start.action.ts index 9e649c833..bec18b838 100644 --- a/actions/start.action.ts +++ b/actions/start.action.ts @@ -10,13 +10,14 @@ import { Configuration } from '../lib/configuration'; import { defaultOutDir } from '../lib/configuration/defaults'; import { ERROR_PREFIX } from '../lib/ui'; import { BuildAction } from './build.action'; +import { loadConfiguration } from '../lib/utils/load-configuration'; export class StartAction extends BuildAction { public async handle(inputs: Input[], options: Input[]) { try { - const configFileName = options.find((option) => option.name === 'config')! - .value as string; - const configuration = await this.loader.load(configFileName); + const configFileName = options.find((option) => option.name === 'config') + ?.value as string | undefined; + const configuration = await loadConfiguration(configFileName); const appName = inputs.find((input) => input.name === 'app')! .value as string; diff --git a/lib/compiler/defaults/webpack-defaults.ts b/lib/compiler/defaults/webpack-defaults.ts index 96c02fa06..9ef635a22 100644 --- a/lib/compiler/defaults/webpack-defaults.ts +++ b/lib/compiler/defaults/webpack-defaults.ts @@ -1,7 +1,6 @@ import ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); import { join } from 'path'; import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin'; -import { defaultConfiguration } from '../../configuration/defaults'; import { appendTsExtension } from '../helpers/append-extension'; import { MultiNestCompilerPlugins } from '../plugins-loader'; import webpack = require('webpack'); @@ -12,7 +11,7 @@ export const webpackDefaultsFactory = ( relativeSourceRoot: string, entryFilename: string, isDebugEnabled = false, - tsConfigFile = defaultConfiguration.compilerOptions.tsConfigPath, + tsConfigFile: string, plugins: MultiNestCompilerPlugins, ): webpack.Configuration => ({ entry: appendTsExtension(join(sourceRoot, entryFilename)), diff --git a/lib/configuration/configuration.ts b/lib/configuration/configuration.ts index 175ec8ec8..4d55453a7 100644 --- a/lib/configuration/configuration.ts +++ b/lib/configuration/configuration.ts @@ -1,4 +1,9 @@ +import * as Joi from 'types-joi'; +import { InterfaceFrom } from 'types-joi'; +import { Schema } from 'joi'; + export type Asset = 'string' | AssetEntry; + export interface AssetEntry { glob: string; include?: string; @@ -16,42 +21,68 @@ export interface ActionOnFile { watchAssetsMode: boolean; } -interface CompilerOptions { - tsConfigPath?: string; - webpack?: boolean; - webpackConfigPath?: string; - plugins?: string[] | PluginOptions[]; - assets?: string[]; - deleteOutDir?: boolean; -} +const pluginOptionsSchema = Joi.object({ + name: Joi.string().required(), + options: Joi.object().pattern(Joi.string(), Joi.any()).required(), +}); -interface PluginOptions { - name: string; - options: Record[]; -} +const generateOptionsSchema = Joi.object({ + spec: Joi.alternatives([ + Joi.boolean(), + Joi.object().pattern(Joi.string(), Joi.boolean().required()), + ]).optional(), +}); -interface GenerateOptions { - spec?: boolean | Record; -} +const compilerOptionsSchema = Joi.object({ + tsConfigPath: Joi.string().default('tsconfig.build.json'), + webpack: Joi.boolean().default(false), + webpackConfigPath: Joi.string().default('webpack.config.js'), + plugins: Joi.array() + .items(Joi.alternatives([Joi.string(), pluginOptionsSchema])) + .default([]), + assets: Joi.array() + .items( + Joi.alternatives([ + Joi.string(), + Joi.object({ + include: Joi.string().optional(), + exclude: Joi.string().optional(), + outDir: Joi.string().optional(), + watchAssets: Joi.boolean().optional(), + }), + ]), + ) + .default([]), + watchAssets: Joi.boolean().default(false), + deleteOutDir: Joi.boolean().default(false), +}); -export interface ProjectConfiguration { - type?: string; - root?: string; - entryFile?: string; - sourceRoot?: string; - compilerOptions?: CompilerOptions; -} +const projectConfigurationSchema = Joi.object({ + type: Joi.string().optional(), + root: Joi.string().optional(), + entryFile: Joi.string().optional(), + sourceRoot: Joi.string().optional(), + compilerOptions: compilerOptionsSchema.optional(), +}); -export interface Configuration { - [key: string]: any; - language?: string; - collection?: string; - sourceRoot?: string; - entryFile?: string; - monorepo?: boolean; - compilerOptions?: CompilerOptions; - generateOptions?: GenerateOptions; - projects?: { - [key: string]: ProjectConfiguration; - }; -} +const configurationSchemaOfTypesJoi = Joi.object({ + language: Joi.string().default('ts'), + collection: Joi.string().default('@nestjs/schematics'), + sourceRoot: Joi.string().default('src'), + entryFile: Joi.string().default('main'), + monorepo: Joi.boolean().default(false), + compilerOptions: compilerOptionsSchema.default(undefined), + generateOptions: generateOptionsSchema.default(undefined), + projects: Joi.object() + .pattern(Joi.string(), projectConfigurationSchema.required()) + .default({}), +}).required(); + +export const configurationSchema = + configurationSchemaOfTypesJoi as unknown as Schema; + +export type Configuration = InterfaceFrom; + +export type ProjectConfiguration = InterfaceFrom< + typeof projectConfigurationSchema +>; diff --git a/lib/configuration/defaults.ts b/lib/configuration/defaults.ts index b36f002e3..2c8594f90 100644 --- a/lib/configuration/defaults.ts +++ b/lib/configuration/defaults.ts @@ -1,22 +1,3 @@ -import { Configuration } from './configuration'; - -export const defaultConfiguration: Required = { - language: 'ts', - sourceRoot: 'src', - collection: '@nestjs/schematics', - entryFile: 'main', - projects: {}, - monorepo: false, - compilerOptions: { - tsConfigPath: 'tsconfig.build.json', - webpack: false, - webpackConfigPath: 'webpack.config.js', - plugins: [], - assets: [], - }, - generateOptions: {}, -}; - export const defaultOutDir = 'dist'; export const defaultGitIgnore = `# compiled output /dist diff --git a/lib/configuration/nest-configuration.loader.ts b/lib/configuration/nest-configuration.loader.ts index 3f7f1f697..26359460a 100644 --- a/lib/configuration/nest-configuration.loader.ts +++ b/lib/configuration/nest-configuration.loader.ts @@ -1,38 +1,31 @@ import { Reader } from '../readers'; import { Configuration } from './configuration'; import { ConfigurationLoader } from './configuration.loader'; -import { defaultConfiguration } from './defaults'; +import { Schema } from 'joi'; export class NestConfigurationLoader implements ConfigurationLoader { - constructor(private readonly reader: Reader) {} + constructor( + private readonly reader: Reader, + private readonly configurationSchema: Schema, + ) {} - public async load(name?: string): Promise> { - const content: string | undefined = name - ? await this.reader.read(name) - : await this.reader.readAnyOf([ - '.nestcli.json', - '.nest-cli.json', - 'nest-cli.json', - 'nest.json', - ]); + private validateConfiguration(configuration: Configuration): Configuration { + const { error, value } = this.configurationSchema.validate(configuration); + if (error) throw error; + return value; + } - if (!content) { - return defaultConfiguration; - } + public async load(name?: string): Promise> { + const content = + (name + ? await this.reader.read(name) + : await this.reader.readAnyOf([ + '.nestcli.json', + '.nest-cli.json', + 'nest-cli.json', + 'nest.json', + ])) || '{}'; const fileConfig = JSON.parse(content); - if (fileConfig.compilerOptions) { - return { - ...defaultConfiguration, - ...fileConfig, - compilerOptions: { - ...defaultConfiguration.compilerOptions, - ...fileConfig.compilerOptions, - }, - }; - } - return { - ...defaultConfiguration, - ...fileConfig, - }; + return this.validateConfiguration(fileConfig); } } diff --git a/lib/utils/load-configuration.ts b/lib/utils/load-configuration.ts index 6b4251f17..8298e2d2d 100644 --- a/lib/utils/load-configuration.ts +++ b/lib/utils/load-configuration.ts @@ -1,10 +1,17 @@ -import { Configuration, ConfigurationLoader } from '../configuration'; -import { NestConfigurationLoader } from '../configuration/nest-configuration.loader'; +import { + Configuration, + ConfigurationLoader, + configurationSchema, + NestConfigurationLoader, +} from '../configuration'; import { FileSystemReader } from '../readers'; -export async function loadConfiguration(): Promise> { +export async function loadConfiguration( + name?: string, +): Promise> { const loader: ConfigurationLoader = new NestConfigurationLoader( new FileSystemReader(process.cwd()), + configurationSchema, ); - return loader.load(); + return loader.load(name); } diff --git a/package-lock.json b/package-lock.json index 2bd9c28b2..e87a6f191 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "commander": "4.1.1", "fork-ts-checker-webpack-plugin": "6.4.0", "inquirer": "7.3.3", + "joi": "^17.4.2", "node-emoji": "1.11.0", "ora": "5.4.1", "os-name": "4.0.1", @@ -28,6 +29,7 @@ "tree-kill": "1.2.2", "tsconfig-paths": "3.11.0", "tsconfig-paths-webpack-plugin": "3.5.2", + "types-joi": "^2.1.0", "typescript": "4.3.5", "webpack": "5.64.1", "webpack-node-externals": "3.0.0" @@ -1568,6 +1570,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@hapi/hoek": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", + "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", @@ -2681,6 +2696,24 @@ "@octokit/openapi-types": "^11.2.0" } }, + "node_modules/@sideway/address": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.2.tgz", + "integrity": "sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "node_modules/@sindresorhus/is": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", @@ -7715,16 +7748,16 @@ }, "node_modules/fsevents/node_modules/abbrev": { "version": "1.1.1", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/fsevents/node_modules/ansi-regex": { "version": "2.1.1", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.10.0" @@ -7732,16 +7765,16 @@ }, "node_modules/fsevents/node_modules/aproba": { "version": "1.2.0", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/fsevents/node_modules/are-we-there-yet": { "version": "1.1.5", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "delegates": "^1.0.0", @@ -7750,16 +7783,16 @@ }, "node_modules/fsevents/node_modules/balanced-match": { "version": "1.0.0", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/brace-expansion": { "version": "1.1.11", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "dependencies": { "balanced-match": "^1.0.0", @@ -7768,16 +7801,16 @@ }, "node_modules/fsevents/node_modules/chownr": { "version": "1.1.1", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/fsevents/node_modules/code-point-at": { "version": "1.1.0", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.10.0" @@ -7785,30 +7818,30 @@ }, "node_modules/fsevents/node_modules/concat-map": { "version": "0.0.1", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/console-control-strings": { "version": "1.1.0", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/fsevents/node_modules/core-util-is": { "version": "1.0.2", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/debug": { "version": "2.6.9", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "dependencies": { "ms": "2.0.0" @@ -7816,9 +7849,9 @@ }, "node_modules/fsevents/node_modules/deep-extend": { "version": "0.6.0", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "engines": { "node": ">=4.0.0" @@ -7826,16 +7859,16 @@ }, "node_modules/fsevents/node_modules/delegates": { "version": "1.0.0", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/detect-libc": { "version": "1.0.3", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "inBundle": true, + "license": "Apache-2.0", "optional": true, "bin": { "detect-libc": "bin/detect-libc.js" @@ -7846,9 +7879,9 @@ }, "node_modules/fsevents/node_modules/fs-minipass": { "version": "1.2.5", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "minipass": "^2.2.1" @@ -7856,16 +7889,16 @@ }, "node_modules/fsevents/node_modules/fs.realpath": { "version": "1.0.0", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/fsevents/node_modules/gauge": { "version": "2.7.4", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "aproba": "^1.0.3", @@ -7880,9 +7913,9 @@ }, "node_modules/fsevents/node_modules/glob": { "version": "7.1.3", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -7898,16 +7931,16 @@ }, "node_modules/fsevents/node_modules/has-unicode": { "version": "2.0.1", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/fsevents/node_modules/iconv-lite": { "version": "0.4.24", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -7918,9 +7951,9 @@ }, "node_modules/fsevents/node_modules/ignore-walk": { "version": "3.0.1", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "minimatch": "^3.0.4" @@ -7928,9 +7961,9 @@ }, "node_modules/fsevents/node_modules/inflight": { "version": "1.0.6", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "once": "^1.3.0", @@ -7939,16 +7972,26 @@ }, "node_modules/fsevents/node_modules/inherits": { "version": "2.0.3", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, + "node_modules/fsevents/node_modules/ini": { + "version": "1.3.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "optional": true, + "engines": { + "node": "*" + } + }, "node_modules/fsevents/node_modules/is-fullwidth-code-point": { "version": "1.0.0", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "dependencies": { "number-is-nan": "^1.0.0" @@ -7959,16 +8002,16 @@ }, "node_modules/fsevents/node_modules/isarray": { "version": "1.0.0", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/minimatch": { "version": "3.0.4", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -7979,16 +8022,16 @@ }, "node_modules/fsevents/node_modules/minimist": { "version": "0.0.8", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/minipass": { "version": "2.3.5", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "safe-buffer": "^5.1.2", @@ -7997,9 +8040,9 @@ }, "node_modules/fsevents/node_modules/minizlib": { "version": "1.2.1", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "dependencies": { "minipass": "^2.2.1" @@ -8007,10 +8050,9 @@ }, "node_modules/fsevents/node_modules/mkdirp": { "version": "0.5.1", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "dependencies": { "minimist": "0.0.8" @@ -8021,16 +8063,16 @@ }, "node_modules/fsevents/node_modules/ms": { "version": "2.0.0", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/needle": { "version": "2.2.4", - "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "dependencies": { "debug": "^2.1.2", @@ -8046,10 +8088,9 @@ }, "node_modules/fsevents/node_modules/node-pre-gyp": { "version": "0.10.3", - "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", - "deprecated": "Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future", "dev": true, "inBundle": true, + "license": "BSD-3-Clause", "optional": true, "dependencies": { "detect-libc": "^1.0.2", @@ -8069,9 +8110,9 @@ }, "node_modules/fsevents/node_modules/nopt": { "version": "4.0.1", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "abbrev": "1", @@ -8083,16 +8124,16 @@ }, "node_modules/fsevents/node_modules/npm-bundled": { "version": "1.0.5", - "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/fsevents/node_modules/npm-packlist": { "version": "1.2.0", - "integrity": "sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "ignore-walk": "^3.0.1", @@ -8101,9 +8142,9 @@ }, "node_modules/fsevents/node_modules/npmlog": { "version": "4.1.2", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "are-we-there-yet": "~1.1.2", @@ -8114,9 +8155,9 @@ }, "node_modules/fsevents/node_modules/number-is-nan": { "version": "1.0.1", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.10.0" @@ -8124,9 +8165,9 @@ }, "node_modules/fsevents/node_modules/object-assign": { "version": "4.1.1", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.10.0" @@ -8134,9 +8175,9 @@ }, "node_modules/fsevents/node_modules/once": { "version": "1.4.0", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "wrappy": "1" @@ -8144,9 +8185,9 @@ }, "node_modules/fsevents/node_modules/os-homedir": { "version": "1.0.2", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.10.0" @@ -8154,9 +8195,9 @@ }, "node_modules/fsevents/node_modules/os-tmpdir": { "version": "1.0.2", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.10.0" @@ -8164,9 +8205,9 @@ }, "node_modules/fsevents/node_modules/osenv": { "version": "0.1.5", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "os-homedir": "^1.0.0", @@ -8175,9 +8216,9 @@ }, "node_modules/fsevents/node_modules/path-is-absolute": { "version": "1.0.1", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.10.0" @@ -8185,16 +8226,16 @@ }, "node_modules/fsevents/node_modules/process-nextick-args": { "version": "2.0.0", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/rc": { "version": "1.2.8", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "inBundle": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "optional": true, "dependencies": { "deep-extend": "^0.6.0", @@ -8208,16 +8249,16 @@ }, "node_modules/fsevents/node_modules/rc/node_modules/minimist": { "version": "1.2.0", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/readable-stream": { "version": "2.3.6", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "dependencies": { "core-util-is": "~1.0.0", @@ -8231,9 +8272,9 @@ }, "node_modules/fsevents/node_modules/rimraf": { "version": "2.6.3", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "glob": "^7.1.3" @@ -8244,30 +8285,30 @@ }, "node_modules/fsevents/node_modules/safe-buffer": { "version": "5.1.2", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/safer-buffer": { "version": "2.1.2", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/sax": { "version": "1.2.4", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/fsevents/node_modules/semver": { "version": "5.6.0", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "bin": { "semver": "bin/semver" @@ -8275,23 +8316,23 @@ }, "node_modules/fsevents/node_modules/set-blocking": { "version": "2.0.0", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/fsevents/node_modules/signal-exit": { "version": "3.0.2", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/fsevents/node_modules/string_decoder": { "version": "1.1.1", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "dependencies": { "safe-buffer": "~5.1.0" @@ -8299,9 +8340,9 @@ }, "node_modules/fsevents/node_modules/string-width": { "version": "1.0.2", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "dependencies": { "code-point-at": "^1.0.0", @@ -8314,9 +8355,9 @@ }, "node_modules/fsevents/node_modules/strip-ansi": { "version": "3.0.1", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "dependencies": { "ansi-regex": "^2.0.0" @@ -8327,9 +8368,9 @@ }, "node_modules/fsevents/node_modules/strip-json-comments": { "version": "2.0.1", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.10.0" @@ -8337,9 +8378,9 @@ }, "node_modules/fsevents/node_modules/tar": { "version": "4.4.8", - "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "chownr": "^1.1.1", @@ -8356,16 +8397,16 @@ }, "node_modules/fsevents/node_modules/util-deprecate": { "version": "1.0.2", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "inBundle": true, + "license": "MIT", "optional": true }, "node_modules/fsevents/node_modules/wide-align": { "version": "1.1.3", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true, "dependencies": { "string-width": "^1.0.2 || 2" @@ -8373,16 +8414,16 @@ }, "node_modules/fsevents/node_modules/wrappy": { "version": "1.0.2", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/fsevents/node_modules/yallist": { "version": "3.0.3", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true, "inBundle": true, + "license": "ISC", "optional": true }, "node_modules/function-bind": { @@ -12126,6 +12167,18 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/joi": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.2.tgz", + "integrity": "sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw==", + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.0", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -16557,6 +16610,11 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/types-joi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/types-joi/-/types-joi-2.1.0.tgz", + "integrity": "sha512-wdvZWNhDx9syXdes3V+YH0KLRNiwGsg7itbjL27truN1Av3YvnJDc3HGs9kbTpfzi3vV2q0scM2y6iSkm9nriQ==" + }, "node_modules/typescript": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", @@ -18585,6 +18643,19 @@ } } }, + "@hapi/hoek": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz", + "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==" + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, "@humanwhocodes/config-array": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", @@ -19450,6 +19521,24 @@ "@octokit/openapi-types": "^11.2.0" } }, + "@sideway/address": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.2.tgz", + "integrity": "sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "@sindresorhus/is": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", @@ -23356,28 +23445,24 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "bundled": true, "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "bundled": true, "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "bundled": true, "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "bundled": true, "dev": true, "optional": true, @@ -23388,14 +23473,12 @@ }, "balanced-match": { "version": "1.0.0", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "bundled": true, "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "bundled": true, "dev": true, "optional": true, @@ -23406,42 +23489,36 @@ }, "chownr": { "version": "1.1.1", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "bundled": true, "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "bundled": true, "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "bundled": true, "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "bundled": true, "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "bundled": true, "dev": true, "optional": true }, "debug": { "version": "2.6.9", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "bundled": true, "dev": true, "optional": true, @@ -23451,28 +23528,24 @@ }, "deep-extend": { "version": "0.6.0", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "bundled": true, "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "bundled": true, "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "bundled": true, "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "bundled": true, "dev": true, "optional": true, @@ -23482,14 +23555,12 @@ }, "fs.realpath": { "version": "1.0.0", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "bundled": true, "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "bundled": true, "dev": true, "optional": true, @@ -23506,7 +23577,6 @@ }, "glob": { "version": "7.1.3", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "bundled": true, "dev": true, "optional": true, @@ -23521,14 +23591,12 @@ }, "has-unicode": { "version": "2.0.1", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "bundled": true, "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "bundled": true, "dev": true, "optional": true, @@ -23538,7 +23606,6 @@ }, "ignore-walk": { "version": "3.0.1", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "bundled": true, "dev": true, "optional": true, @@ -23548,7 +23615,6 @@ }, "inflight": { "version": "1.0.6", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "bundled": true, "dev": true, "optional": true, @@ -23559,14 +23625,18 @@ }, "inherits": { "version": "2.0.3", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", "bundled": true, "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "bundled": true, "dev": true, "optional": true, @@ -23576,14 +23646,12 @@ }, "isarray": { "version": "1.0.0", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "bundled": true, "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "bundled": true, "dev": true, "optional": true, @@ -23593,14 +23661,12 @@ }, "minimist": { "version": "0.0.8", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "bundled": true, "dev": true, "optional": true }, "minipass": { "version": "2.3.5", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "bundled": true, "dev": true, "optional": true, @@ -23611,7 +23677,6 @@ }, "minizlib": { "version": "1.2.1", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "bundled": true, "dev": true, "optional": true, @@ -23621,7 +23686,6 @@ }, "mkdirp": { "version": "0.5.1", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "bundled": true, "dev": true, "optional": true, @@ -23631,14 +23695,12 @@ }, "ms": { "version": "2.0.0", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "bundled": true, "dev": true, "optional": true }, "needle": { "version": "2.2.4", - "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", "bundled": true, "dev": true, "optional": true, @@ -23650,7 +23712,6 @@ }, "node-pre-gyp": { "version": "0.10.3", - "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", "bundled": true, "dev": true, "optional": true, @@ -23669,7 +23730,6 @@ }, "nopt": { "version": "4.0.1", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "bundled": true, "dev": true, "optional": true, @@ -23680,14 +23740,12 @@ }, "npm-bundled": { "version": "1.0.5", - "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==", "bundled": true, "dev": true, "optional": true }, "npm-packlist": { "version": "1.2.0", - "integrity": "sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ==", "bundled": true, "dev": true, "optional": true, @@ -23698,7 +23756,6 @@ }, "npmlog": { "version": "4.1.2", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "bundled": true, "dev": true, "optional": true, @@ -23711,21 +23768,18 @@ }, "number-is-nan": { "version": "1.0.1", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "bundled": true, "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "bundled": true, "dev": true, "optional": true }, "once": { "version": "1.4.0", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "bundled": true, "dev": true, "optional": true, @@ -23735,21 +23789,18 @@ }, "os-homedir": { "version": "1.0.2", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "bundled": true, "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "bundled": true, "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "bundled": true, "dev": true, "optional": true, @@ -23760,21 +23811,18 @@ }, "path-is-absolute": { "version": "1.0.1", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "bundled": true, "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "bundled": true, "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "bundled": true, "dev": true, "optional": true, @@ -23787,7 +23835,6 @@ "dependencies": { "minimist": { "version": "1.2.0", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "bundled": true, "dev": true, "optional": true @@ -23796,7 +23843,6 @@ }, "readable-stream": { "version": "2.3.6", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "bundled": true, "dev": true, "optional": true, @@ -23812,7 +23858,6 @@ }, "rimraf": { "version": "2.6.3", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "bundled": true, "dev": true, "optional": true, @@ -23822,49 +23867,42 @@ }, "safe-buffer": { "version": "5.1.2", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "bundled": true, "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "bundled": true, "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "bundled": true, "dev": true, "optional": true }, "semver": { "version": "5.6.0", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "bundled": true, "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "bundled": true, "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "bundled": true, "dev": true, "optional": true }, "string_decoder": { "version": "1.1.1", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "bundled": true, "dev": true, "optional": true, @@ -23874,7 +23912,6 @@ }, "string-width": { "version": "1.0.2", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "bundled": true, "dev": true, "optional": true, @@ -23886,7 +23923,6 @@ }, "strip-ansi": { "version": "3.0.1", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "bundled": true, "dev": true, "optional": true, @@ -23896,14 +23932,12 @@ }, "strip-json-comments": { "version": "2.0.1", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "bundled": true, "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "bundled": true, "dev": true, "optional": true, @@ -23919,14 +23953,12 @@ }, "util-deprecate": { "version": "1.0.2", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "bundled": true, "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "bundled": true, "dev": true, "optional": true, @@ -23936,14 +23968,12 @@ }, "wrappy": { "version": "1.0.2", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "bundled": true, "dev": true, "optional": true }, "yallist": { "version": "3.0.3", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "bundled": true, "dev": true, "optional": true @@ -26745,6 +26775,18 @@ } } }, + "joi": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.2.tgz", + "integrity": "sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw==", + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.0", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -30128,6 +30170,11 @@ "is-typedarray": "^1.0.0" } }, + "types-joi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/types-joi/-/types-joi-2.1.0.tgz", + "integrity": "sha512-wdvZWNhDx9syXdes3V+YH0KLRNiwGsg7itbjL27truN1Av3YvnJDc3HGs9kbTpfzi3vV2q0scM2y6iSkm9nriQ==" + }, "typescript": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", diff --git a/package.json b/package.json index 61020124f..d8ca3f065 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "commander": "4.1.1", "fork-ts-checker-webpack-plugin": "6.4.0", "inquirer": "7.3.3", + "joi": "17.4.2", "node-emoji": "1.11.0", "ora": "5.4.1", "os-name": "4.0.1", @@ -62,6 +63,7 @@ "tree-kill": "1.2.2", "tsconfig-paths": "3.11.0", "tsconfig-paths-webpack-plugin": "3.5.2", + "types-joi": "2.1.0", "typescript": "4.3.5", "webpack": "5.64.1", "webpack-node-externals": "3.0.0" diff --git a/test/lib/compiler/helpers/get-value-or-default.spec.ts b/test/lib/compiler/helpers/get-value-or-default.spec.ts index 9bd648f3a..2822757f1 100644 --- a/test/lib/compiler/helpers/get-value-or-default.spec.ts +++ b/test/lib/compiler/helpers/get-value-or-default.spec.ts @@ -1,9 +1,8 @@ import { getValueOrDefault } from '../../../../lib/compiler/helpers/get-value-or-default'; -import { Configuration } from '../../../../lib/configuration'; describe('Get Value or Default', () => { it('should return assigned configuration value', async () => { - let configuration: Required = { + let configuration: any = { monorepo: true, sourceRoot: '', entryFile: '', @@ -34,7 +33,7 @@ describe('Get Value or Default', () => { }); it('should return assigned project configuration value', async () => { - let configuration: Required = { + let configuration: any = { monorepo: true, sourceRoot: '', entryFile: '', @@ -103,7 +102,7 @@ describe('Get Value or Default', () => { }); it('should return default configuration value when project value not found', async () => { - let configuration: Required = { + let configuration: any = { monorepo: true, sourceRoot: '', entryFile: '', @@ -172,7 +171,7 @@ describe('Get Value or Default', () => { }); it('should concatenate property path when app name contains dots', async () => { - let configuration: Required = { + let configuration: any = { monorepo: true, sourceRoot: '', entryFile: '', diff --git a/test/lib/configuration/nest-configuration.loader.spec.ts b/test/lib/configuration/nest-configuration.loader.spec.ts index 8ff7ba071..e4eae6026 100644 --- a/test/lib/configuration/nest-configuration.loader.spec.ts +++ b/test/lib/configuration/nest-configuration.loader.spec.ts @@ -1,5 +1,9 @@ -import { Configuration, ConfigurationLoader } from '../../../lib/configuration'; -import { NestConfigurationLoader } from '../../../lib/configuration/nest-configuration.loader'; +import { + Configuration, + ConfigurationLoader, + configurationSchema, + NestConfigurationLoader, +} from '../../../lib/configuration'; import { Reader } from '../../../lib/readers'; describe('Nest Configuration Loader', () => { @@ -30,7 +34,10 @@ describe('Nest Configuration Loader', () => { reader = mock(); }); it('should call reader.readAnyOf when load', async () => { - const loader: ConfigurationLoader = new NestConfigurationLoader(reader); + const loader: ConfigurationLoader = new NestConfigurationLoader( + reader, + configurationSchema, + ); const configuration: Configuration = await loader.load(); expect(reader.readAnyOf).toHaveBeenCalledWith([ '.nestcli.json', @@ -51,12 +58,17 @@ describe('Nest Configuration Loader', () => { tsConfigPath: 'tsconfig.build.json', webpack: false, webpackConfigPath: 'webpack.config.js', + watchAssets: false, + deleteOutDir: false, }, generateOptions: {}, }); }); it('should call reader.read when load with filename', async () => { - const loader: ConfigurationLoader = new NestConfigurationLoader(reader); + const loader: ConfigurationLoader = new NestConfigurationLoader( + reader, + configurationSchema, + ); const configuration: Configuration = await loader.load( 'nest-cli.secondary.config.json', ); @@ -74,8 +86,36 @@ describe('Nest Configuration Loader', () => { tsConfigPath: 'tsconfig.build.json', webpack: false, webpackConfigPath: 'webpack.config.js', + watchAssets: false, + deleteOutDir: false, }, generateOptions: {}, }); }); + + it('should throw error when appear unexpected attributes', async function () { + const loader: ConfigurationLoader = new NestConfigurationLoader( + { + read(_name: string): string { + return JSON.stringify({ + unexpected: 'xxx', + compilerOptions: { + anotherUnexpected: 'yyy', + }, + }); + }, + readAnyOf(_filenames: string[]): string { + return JSON.stringify({ + unexpected: 'xxx', + compilerOptions: { + anotherUnexpected: 'yyy', + }, + }); + }, + } as Reader, + configurationSchema, + ); + const configuration = loader.load(); + await expect(configuration).rejects.toThrow(); + }); });