From ce51a0ab9d15216080fe28a4634a437b0352ebd2 Mon Sep 17 00:00:00 2001 From: rishabh3112 Date: Wed, 20 Mar 2019 15:32:37 +0530 Subject: [PATCH 01/34] fix(add): add handling of merge option --- packages/generators/add-generator.ts | 50 ++++++++++++++++++++++------ packages/utils/scaffold.ts | 2 +- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 57548e98c92..43be46b4aaf 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -1,9 +1,3 @@ -import Generator = require("yeoman-generator"); - -import * as glob from "glob-all"; -import * as autoComplete from "inquirer-autocomplete-prompt"; -import * as path from "path"; - import npmExists from "@webpack-cli/utils/npm-exists"; import { getPackageManager } from "@webpack-cli/utils/package-manager"; import PROP_TYPES from "@webpack-cli/utils/prop-types"; @@ -11,13 +5,18 @@ import { AutoComplete, Confirm, IInquirerInput, - IInquirerList, Input, + InputValidate, List, } from "@webpack-cli/webpack-scaffold"; - +import { existsSync } from "fs"; +import * as glob from "glob-all"; +import * as autoComplete from "inquirer-autocomplete-prompt"; +import { resolve } from "path"; +import Generator = require("yeoman-generator"); import { ISchemaProperties, IWebpackOptions } from "./types"; import entryQuestions from "./utils/entry"; +import validate from "./utils/validate"; // tslint:disable:no-var-requires const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); @@ -94,7 +93,8 @@ export default class AddGenerator extends Generator { config: { configName?: string, topScope?: string[], - item?: string; + item?: string, + merge?: object, webpackOptions?: IWebpackOptions, }, }; @@ -173,6 +173,36 @@ export default class AddGenerator extends Generator { done(); }); } + if (action === "merge") { + const validatePath = (path: string) => { + const resolvedPath = resolve(process.env.PWD, path); + if (existsSync(resolvedPath)) { + if (/\.js$/.test(path)) { + if (typeof require(resolvedPath) !== "object") { + return "Given file doesn't export an Object"; + } + return true; + } else { + return "Path doesn't corresponds to a javascript file"; + } + } + return "Invalid path provided"; + }; + return this.prompt([ + InputValidate( + "mergeFile", + "What is the location of webpack configuration file with which you want to merge current configuration?", + validatePath, + ), + ]) + .then((mergeFileAnswer: { + mergeFile: string; + }) => { + const resolvedPath = resolve(process.env.PWD, mergeFileAnswer.mergeFile); + const mergeConfig = require(resolvedPath); + this.configuration.config.merge = mergeConfig; + }); + } } const temp: string = action; if (action === "resolveLoader") { @@ -367,7 +397,7 @@ export default class AddGenerator extends Generator { pluginsSchemaPath.indexOf("optimize") >= 0 ? "webpack.optimize" : "webpack"; - const resolvePluginsPath: string = path.resolve(pluginsSchemaPath); + const resolvePluginsPath: string = resolve(pluginsSchemaPath); const pluginSchema: object = resolvePluginsPath ? require(resolvePluginsPath) : null; diff --git a/packages/utils/scaffold.ts b/packages/utils/scaffold.ts index 3edfa815991..f3b897bcb86 100644 --- a/packages/utils/scaffold.ts +++ b/packages/utils/scaffold.ts @@ -48,7 +48,7 @@ export default function runTransform(transformConfig: ITransformConfig, action: transformations.push("topScope"); } - if (config.merge) { + if (config.merge && transformations.indexOf("merge") === -1) { transformations.push("merge"); } From d901d49cc29a715c03384c523170628dc1b53e01 Mon Sep 17 00:00:00 2001 From: rishabh3112 Date: Wed, 20 Mar 2019 17:46:51 +0530 Subject: [PATCH 02/34] chore(refactor): add generator --- packages/generators/add-generator.ts | 122 +++--------------- packages/utils/generators/add/index.ts | 62 +++++++++ .../utils/generators/add/questions/index.ts | 63 +++++++++ 3 files changed, 145 insertions(+), 102 deletions(-) create mode 100644 packages/utils/generators/add/index.ts create mode 100644 packages/utils/generators/add/questions/index.ts diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 43be46b4aaf..6fbdccb149b 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -1,6 +1,20 @@ +import { + replaceAt, + traverseAndGetProperties, + webpackDevServerSchema, + webpackSchema, +} from "@webpack-cli/utils/generators/add"; + +import { + actionTypeQuestion, + entryTypeQuestion, + manualOrListInput, + mergeFileQuestion, + topScopeQuestion, +} from "@webpack-cli/utils/generators/add/questions"; + import npmExists from "@webpack-cli/utils/npm-exists"; import { getPackageManager } from "@webpack-cli/utils/package-manager"; -import PROP_TYPES from "@webpack-cli/utils/prop-types"; import { AutoComplete, Confirm, @@ -18,66 +32,6 @@ import { ISchemaProperties, IWebpackOptions } from "./types"; import entryQuestions from "./utils/entry"; import validate from "./utils/validate"; -// tslint:disable:no-var-requires -const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); -const webpackSchema = require("./utils/optionsSchema.json"); -const PROPS: string[] = Array.from(PROP_TYPES.keys()); - -/** - * - * Replaces the string with a substring at the given index - * https://gist.github.com/efenacigiray/9367920 - * - * @param {String} string - string to be modified - * @param {Number} index - index to replace from - * @param {String} replace - string to replace starting from index - * - * @returns {String} string - The newly mutated string - * - */ -function replaceAt(str: string, index: number, replace: string): string { - return str.substring(0, index) + replace + str.substring(index + 1); -} - -/** - * - * Checks if the given array has a given property - * - * @param {Array} arr - array to check - * @param {String} prop - property to check existence of - * - * @returns {Boolean} hasProp - Boolean indicating if the property - * is present - */ -const traverseAndGetProperties = (arr: object[], prop: string): boolean => { - let hasProp: boolean = false; - arr.forEach((p: object): void => { - if (p[prop]) { - hasProp = true; - } - }); - return hasProp; -}; - -/** - * - * Search config properties - * - * @param {Object} answers Prompt answers object - * @param {String} input Input search string - * - * @returns {Promise} Returns promise which resolves to filtered props - * - */ -const searchProps = (answers: object, input: string): Promise => { - input = input || ""; - return Promise.resolve( - PROPS.filter((prop: string): boolean => - prop.toLowerCase().includes(input.toLowerCase()), - ), - ); -}; - /** * * Generator for adding properties @@ -94,7 +48,7 @@ export default class AddGenerator extends Generator { configName?: string, topScope?: string[], item?: string, - merge?: object, + merge?: IWebpackOptions, webpackOptions?: IWebpackOptions, }, }; @@ -116,24 +70,12 @@ export default class AddGenerator extends Generator { const done: (_?: void) => void | boolean = this.async(); let action: string; const self: this = this; - const manualOrListInput: (promptAction: string) => IInquirerInput = (promptAction: string) => - Input("actionAnswer", `What do you want to add to ${promptAction}?`); let inputPrompt: IInquirerInput; // first index indicates if it has a deep prop, 2nd indicates what kind of const isDeepProp: any[] = [false, false]; - return this.prompt([ - AutoComplete( - "actionType", - "What property do you want to add to?", - { - pageSize: 7, - source: searchProps, - suggestOnly: false, - }, - ), - ]) + return this.prompt([actionTypeQuestion]) .then((actionTypeAnswer: { actionType: string, }) => { @@ -146,9 +88,7 @@ export default class AddGenerator extends Generator { }) .then((_: void) => { if (action === "entry") { - return this.prompt([ - Confirm("entryType", "Will your application have multiple bundles?", false), - ]) + return this.prompt([entryTypeQuestion]) .then((entryTypeAnswer: { entryType: boolean, }) => { @@ -163,9 +103,7 @@ export default class AddGenerator extends Generator { }); } else { if (action === "topScope") { - return this.prompt([ - Input("topScope", "What do you want to add to topScope?"), - ]) + return this.prompt([topScopeQuestion]) .then((topScopeAnswer: { topScope: string; }) => { @@ -174,27 +112,7 @@ export default class AddGenerator extends Generator { }); } if (action === "merge") { - const validatePath = (path: string) => { - const resolvedPath = resolve(process.env.PWD, path); - if (existsSync(resolvedPath)) { - if (/\.js$/.test(path)) { - if (typeof require(resolvedPath) !== "object") { - return "Given file doesn't export an Object"; - } - return true; - } else { - return "Path doesn't corresponds to a javascript file"; - } - } - return "Invalid path provided"; - }; - return this.prompt([ - InputValidate( - "mergeFile", - "What is the location of webpack configuration file with which you want to merge current configuration?", - validatePath, - ), - ]) + return this.prompt([mergeFileQuestion]) .then((mergeFileAnswer: { mergeFile: string; }) => { diff --git a/packages/utils/generators/add/index.ts b/packages/utils/generators/add/index.ts new file mode 100644 index 00000000000..83ccd5fd1b5 --- /dev/null +++ b/packages/utils/generators/add/index.ts @@ -0,0 +1,62 @@ +import PROP_TYPES from "@webpack-cli/utils/prop-types"; + +const PROPS: string[] = Array.from(PROP_TYPES.keys()); + +// tslint:disable:no-var-requires +export const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); +export const webpackSchema = require("./utils/optionsSchema.json"); + +/** + * + * Replaces the string with a substring at the given index + * https://gist.github.com/efenacigiray/9367920 + * + * @param {String} string - string to be modified + * @param {Number} index - index to replace from + * @param {String} replace - string to replace starting from index + * + * @returns {String} string - The newly mutated string + * + */ +export function replaceAt(str: string, index: number, replace: string): string { + return str.substring(0, index) + replace + str.substring(index + 1); +} + +/** + * + * Checks if the given array has a given property + * + * @param {Array} arr - array to check + * @param {String} prop - property to check existence of + * + * @returns {Boolean} hasProp - Boolean indicating if the property + * is present + */ +export const traverseAndGetProperties = (arr: object[], prop: string): boolean => { + let hasProp: boolean = false; + arr.forEach((p: object): void => { + if (p[prop]) { + hasProp = true; + } + }); + return hasProp; +}; + +/** + * + * Search config properties + * + * @param {Object} answers Prompt answers object + * @param {String} input Input search string + * + * @returns {Promise} Returns promise which resolves to filtered props + * + */ +export const searchProps = (answers: object, input: string): Promise => { + input = input || ""; + return Promise.resolve( + PROPS.filter((prop: string): boolean => + prop.toLowerCase().includes(input.toLowerCase()), + ), + ); +}; diff --git a/packages/utils/generators/add/questions/index.ts b/packages/utils/generators/add/questions/index.ts new file mode 100644 index 00000000000..9ee042fdc13 --- /dev/null +++ b/packages/utils/generators/add/questions/index.ts @@ -0,0 +1,63 @@ +import { + AutoComplete, + Confirm, + IInquirerInput, + Input, + InputValidate, + List, +} from "@webpack-cli/webpack-scaffold"; +import { existsSync } from "fs"; +import { resolve } from "path"; +import { + searchProps, +} from "../index"; + +/** + * Returns Inquirer question for given action + * @param action string + */ +export const manualOrListInput: (action: string) => IInquirerInput = (action: string) => { + const actionQuestion = `What do you want to add to ${action}?`; + return Input("actionAnswer", actionQuestion); +}; + +export const actionTypeQuestion = AutoComplete( + "actionType", + "What property do you want to add to?", + { + pageSize: 7, + source: searchProps, + suggestOnly: false, + }, +); + +export const entryTypeQuestion = Confirm( + "entryType", + "Will your application have multiple bundles?", + false, +); + +export const topScopeQuestion = Input( + "topScope", + "What do you want to add to topScope?", +); + +const mergeFileQuestionFunction = () => { + const question = "What is the location of webpack configuration with which you want to merge current configuration?"; + const validator = (path: string) => { + const resolvedPath = resolve(process.env.PWD, path); + if (existsSync(resolvedPath)) { + if (/\.js$/.test(path)) { + if (typeof require(resolvedPath) !== "object") { + return "Given file doesn't export an Object"; + } + return true; + } else { + return "Path doesn't corresponds to a javascript file"; + } + } + return "Invalid path provided"; + }; + return InputValidate("mergeFile", question, validator); +}; +export const mergeFileQuestion = mergeFileQuestionFunction(); From eb43443232ffcd8489ed3f2476a7b59aa1d7a516 Mon Sep 17 00:00:00 2001 From: rishabh3112 Date: Wed, 20 Mar 2019 15:32:37 +0530 Subject: [PATCH 03/34] fix(add): add handling of merge option --- packages/generators/add-generator.ts | 49 +++++++++++++++++++++++----- packages/utils/scaffold.ts | 2 +- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 134c10be8b4..01b03363c14 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -1,9 +1,3 @@ -import Generator = require("yeoman-generator"); - -import * as glob from "glob-all"; -import * as autoComplete from "inquirer-autocomplete-prompt"; -import * as path from "path"; - import npmExists from "@webpack-cli/utils/npm-exists"; import { getPackageManager } from "@webpack-cli/utils/package-manager"; import PROP_TYPES from "@webpack-cli/utils/prop-types"; @@ -12,11 +6,17 @@ import { Confirm, IInquirerInput, Input, + InputValidate, List, } from "@webpack-cli/webpack-scaffold"; - +import { existsSync } from "fs"; +import * as glob from "glob-all"; +import * as autoComplete from "inquirer-autocomplete-prompt"; +import { resolve } from "path"; +import Generator = require("yeoman-generator"); import { ISchemaProperties, IWebpackOptions } from "./types"; import entryQuestions from "./utils/entry"; +import validate from "./utils/validate"; // tslint:disable:no-var-requires const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); @@ -93,7 +93,8 @@ export default class AddGenerator extends Generator { config: { configName?: string, topScope?: string[], - item?: string; + item?: string, + merge?: object, webpackOptions?: IWebpackOptions, }, }; @@ -172,6 +173,36 @@ export default class AddGenerator extends Generator { done(); }); } + if (action === "merge") { + const validatePath = (path: string) => { + const resolvedPath = resolve(process.env.PWD, path); + if (existsSync(resolvedPath)) { + if (/\.js$/.test(path)) { + if (typeof require(resolvedPath) !== "object") { + return "Given file doesn't export an Object"; + } + return true; + } else { + return "Path doesn't corresponds to a javascript file"; + } + } + return "Invalid path provided"; + }; + return this.prompt([ + InputValidate( + "mergeFile", + "What is the location of webpack configuration file with which you want to merge current configuration?", + validatePath, + ), + ]) + .then((mergeFileAnswer: { + mergeFile: string; + }) => { + const resolvedPath = resolve(process.env.PWD, mergeFileAnswer.mergeFile); + const mergeConfig = require(resolvedPath); + this.configuration.config.merge = mergeConfig; + }); + } } const temp = action; if (action === "resolveLoader") { @@ -366,7 +397,7 @@ export default class AddGenerator extends Generator { pluginsSchemaPath.indexOf("optimize") >= 0 ? "webpack.optimize" : "webpack"; - const resolvePluginsPath: string = path.resolve(pluginsSchemaPath); + const resolvePluginsPath: string = resolve(pluginsSchemaPath); const pluginSchema: object = resolvePluginsPath ? require(resolvePluginsPath) : null; diff --git a/packages/utils/scaffold.ts b/packages/utils/scaffold.ts index c1bd9ecbeca..be1f9982f4d 100644 --- a/packages/utils/scaffold.ts +++ b/packages/utils/scaffold.ts @@ -48,7 +48,7 @@ export default function runTransform(transformConfig: ITransformConfig, action: transformations.push("topScope"); } - if (config.merge) { + if (config.merge && transformations.indexOf("merge") === -1) { transformations.push("merge"); } From 66bde9f09f1973455b6fa16b1596129073b24858 Mon Sep 17 00:00:00 2001 From: rishabh3112 Date: Wed, 20 Mar 2019 17:46:51 +0530 Subject: [PATCH 04/34] chore(refactor): add generator --- packages/generators/add-generator.ts | 122 +++--------------- packages/utils/generators/add/index.ts | 62 +++++++++ .../utils/generators/add/questions/index.ts | 63 +++++++++ 3 files changed, 145 insertions(+), 102 deletions(-) create mode 100644 packages/utils/generators/add/index.ts create mode 100644 packages/utils/generators/add/questions/index.ts diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 01b03363c14..ee775757668 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -1,6 +1,20 @@ +import { + replaceAt, + traverseAndGetProperties, + webpackDevServerSchema, + webpackSchema, +} from "@webpack-cli/utils/generators/add"; + +import { + actionTypeQuestion, + entryTypeQuestion, + manualOrListInput, + mergeFileQuestion, + topScopeQuestion, +} from "@webpack-cli/utils/generators/add/questions"; + import npmExists from "@webpack-cli/utils/npm-exists"; import { getPackageManager } from "@webpack-cli/utils/package-manager"; -import PROP_TYPES from "@webpack-cli/utils/prop-types"; import { AutoComplete, Confirm, @@ -18,66 +32,6 @@ import { ISchemaProperties, IWebpackOptions } from "./types"; import entryQuestions from "./utils/entry"; import validate from "./utils/validate"; -// tslint:disable:no-var-requires -const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); -const webpackSchema = require("./utils/optionsSchema.json"); -const PROPS: string[] = Array.from(PROP_TYPES.keys()); - -/** - * - * Replaces the string with a substring at the given index - * https://gist.github.com/efenacigiray/9367920 - * - * @param {String} string - string to be modified - * @param {Number} index - index to replace from - * @param {String} replace - string to replace starting from index - * - * @returns {String} string - The newly mutated string - * - */ -function replaceAt(str: string, index: number, replace: string): string { - return str.substring(0, index) + replace + str.substring(index + 1); -} - -/** - * - * Checks if the given array has a given property - * - * @param {Array} arr - array to check - * @param {String} prop - property to check existence of - * - * @returns {Boolean} hasProp - Boolean indicating if the property - * is present - */ -const traverseAndGetProperties = (arr: object[], prop: string): boolean => { - let hasProp = false; - arr.forEach((p: object): void => { - if (p[prop]) { - hasProp = true; - } - }); - return hasProp; -}; - -/** - * - * Search config properties - * - * @param {Object} answers Prompt answers object - * @param {String} input Input search string - * - * @returns {Promise} Returns promise which resolves to filtered props - * - */ -const searchProps = (answers: object, input: string): Promise => { - input = input || ""; - return Promise.resolve( - PROPS.filter((prop: string): boolean => - prop.toLowerCase().includes(input.toLowerCase()), - ), - ); -}; - /** * * Generator for adding properties @@ -94,7 +48,7 @@ export default class AddGenerator extends Generator { configName?: string, topScope?: string[], item?: string, - merge?: object, + merge?: IWebpackOptions, webpackOptions?: IWebpackOptions, }, }; @@ -116,24 +70,12 @@ export default class AddGenerator extends Generator { const done: (_?: void) => void | boolean = this.async(); let action: string; const self: this = this; - const manualOrListInput: (promptAction: string) => IInquirerInput = (promptAction: string) => - Input("actionAnswer", `What do you want to add to ${promptAction}?`); let inputPrompt: IInquirerInput; // first index indicates if it has a deep prop, 2nd indicates what kind of const isDeepProp: any[] = [false, false]; - return this.prompt([ - AutoComplete( - "actionType", - "What property do you want to add to?", - { - pageSize: 7, - source: searchProps, - suggestOnly: false, - }, - ), - ]) + return this.prompt([actionTypeQuestion]) .then((actionTypeAnswer: { actionType: string, }) => { @@ -146,9 +88,7 @@ export default class AddGenerator extends Generator { }) .then((_: void) => { if (action === "entry") { - return this.prompt([ - Confirm("entryType", "Will your application have multiple bundles?", false), - ]) + return this.prompt([entryTypeQuestion]) .then((entryTypeAnswer: { entryType: boolean, }) => { @@ -163,9 +103,7 @@ export default class AddGenerator extends Generator { }); } else { if (action === "topScope") { - return this.prompt([ - Input("topScope", "What do you want to add to topScope?"), - ]) + return this.prompt([topScopeQuestion]) .then((topScopeAnswer: { topScope: string; }) => { @@ -174,27 +112,7 @@ export default class AddGenerator extends Generator { }); } if (action === "merge") { - const validatePath = (path: string) => { - const resolvedPath = resolve(process.env.PWD, path); - if (existsSync(resolvedPath)) { - if (/\.js$/.test(path)) { - if (typeof require(resolvedPath) !== "object") { - return "Given file doesn't export an Object"; - } - return true; - } else { - return "Path doesn't corresponds to a javascript file"; - } - } - return "Invalid path provided"; - }; - return this.prompt([ - InputValidate( - "mergeFile", - "What is the location of webpack configuration file with which you want to merge current configuration?", - validatePath, - ), - ]) + return this.prompt([mergeFileQuestion]) .then((mergeFileAnswer: { mergeFile: string; }) => { diff --git a/packages/utils/generators/add/index.ts b/packages/utils/generators/add/index.ts new file mode 100644 index 00000000000..83ccd5fd1b5 --- /dev/null +++ b/packages/utils/generators/add/index.ts @@ -0,0 +1,62 @@ +import PROP_TYPES from "@webpack-cli/utils/prop-types"; + +const PROPS: string[] = Array.from(PROP_TYPES.keys()); + +// tslint:disable:no-var-requires +export const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); +export const webpackSchema = require("./utils/optionsSchema.json"); + +/** + * + * Replaces the string with a substring at the given index + * https://gist.github.com/efenacigiray/9367920 + * + * @param {String} string - string to be modified + * @param {Number} index - index to replace from + * @param {String} replace - string to replace starting from index + * + * @returns {String} string - The newly mutated string + * + */ +export function replaceAt(str: string, index: number, replace: string): string { + return str.substring(0, index) + replace + str.substring(index + 1); +} + +/** + * + * Checks if the given array has a given property + * + * @param {Array} arr - array to check + * @param {String} prop - property to check existence of + * + * @returns {Boolean} hasProp - Boolean indicating if the property + * is present + */ +export const traverseAndGetProperties = (arr: object[], prop: string): boolean => { + let hasProp: boolean = false; + arr.forEach((p: object): void => { + if (p[prop]) { + hasProp = true; + } + }); + return hasProp; +}; + +/** + * + * Search config properties + * + * @param {Object} answers Prompt answers object + * @param {String} input Input search string + * + * @returns {Promise} Returns promise which resolves to filtered props + * + */ +export const searchProps = (answers: object, input: string): Promise => { + input = input || ""; + return Promise.resolve( + PROPS.filter((prop: string): boolean => + prop.toLowerCase().includes(input.toLowerCase()), + ), + ); +}; diff --git a/packages/utils/generators/add/questions/index.ts b/packages/utils/generators/add/questions/index.ts new file mode 100644 index 00000000000..9ee042fdc13 --- /dev/null +++ b/packages/utils/generators/add/questions/index.ts @@ -0,0 +1,63 @@ +import { + AutoComplete, + Confirm, + IInquirerInput, + Input, + InputValidate, + List, +} from "@webpack-cli/webpack-scaffold"; +import { existsSync } from "fs"; +import { resolve } from "path"; +import { + searchProps, +} from "../index"; + +/** + * Returns Inquirer question for given action + * @param action string + */ +export const manualOrListInput: (action: string) => IInquirerInput = (action: string) => { + const actionQuestion = `What do you want to add to ${action}?`; + return Input("actionAnswer", actionQuestion); +}; + +export const actionTypeQuestion = AutoComplete( + "actionType", + "What property do you want to add to?", + { + pageSize: 7, + source: searchProps, + suggestOnly: false, + }, +); + +export const entryTypeQuestion = Confirm( + "entryType", + "Will your application have multiple bundles?", + false, +); + +export const topScopeQuestion = Input( + "topScope", + "What do you want to add to topScope?", +); + +const mergeFileQuestionFunction = () => { + const question = "What is the location of webpack configuration with which you want to merge current configuration?"; + const validator = (path: string) => { + const resolvedPath = resolve(process.env.PWD, path); + if (existsSync(resolvedPath)) { + if (/\.js$/.test(path)) { + if (typeof require(resolvedPath) !== "object") { + return "Given file doesn't export an Object"; + } + return true; + } else { + return "Path doesn't corresponds to a javascript file"; + } + } + return "Invalid path provided"; + }; + return InputValidate("mergeFile", question, validator); +}; +export const mergeFileQuestion = mergeFileQuestionFunction(); From e5c7f6763a73803967881b8e7880d1ed64f48eef Mon Sep 17 00:00:00 2001 From: rishabh3112 Date: Thu, 21 Mar 2019 15:32:42 +0530 Subject: [PATCH 05/34] chore(refactor): update package list --- packages/utils/generators/add/index.ts | 2 +- packages/utils/package-lock.json | 108 +++++++++++-------------- packages/utils/package.json | 1 + 3 files changed, 51 insertions(+), 60 deletions(-) diff --git a/packages/utils/generators/add/index.ts b/packages/utils/generators/add/index.ts index 83ccd5fd1b5..50571e41447 100644 --- a/packages/utils/generators/add/index.ts +++ b/packages/utils/generators/add/index.ts @@ -1,4 +1,4 @@ -import PROP_TYPES from "@webpack-cli/utils/prop-types"; +import PROP_TYPES from "../../prop-types"; const PROPS: string[] = Array.from(PROP_TYPES.keys()); diff --git a/packages/utils/package-lock.json b/packages/utils/package-lock.json index d0ff77c38cb..2e4e60caa73 100644 --- a/packages/utils/package-lock.json +++ b/packages/utils/package-lock.json @@ -1,6 +1,6 @@ { "name": "@webpack-cli/utils", - "version": "0.1.3", + "version": "0.1.5", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -105,6 +105,15 @@ "integrity": "sha512-XIB0ZCaFZmWUHAa9dBqP5UKXXHwuukmVlP+XcyU94dui2k+l2lG+CHAbt2ffenHPUqoIs5Beh8Pdf2YEq/CZ7A==", "dev": true }, + "@webpack-cli/webpack-scaffold": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/webpack-scaffold/-/webpack-scaffold-0.1.5.tgz", + "integrity": "sha512-LHVL+aZjCW+K6EP3zR8jabIgxoHqW01KNMAXOxpTTNNSmNsjB0C59EXImleWzocDTPB7E2ZJbIXaHksRUT3F0Q==", + "dev": true, + "requires": { + "jscodeshift": "^0.5.1" + } + }, "abab": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", @@ -149,7 +158,7 @@ }, "ansi-escapes": { "version": "3.1.0", - "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" }, "ansi-regex": { @@ -465,7 +474,7 @@ }, "array-equal": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" }, "array-union": { @@ -824,47 +833,47 @@ }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" }, "babel-plugin-syntax-async-generators": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=" }, "babel-plugin-syntax-class-constructor-call": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=" }, "babel-plugin-syntax-class-properties": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" }, "babel-plugin-syntax-decorators": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=" }, "babel-plugin-syntax-dynamic-import": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" }, "babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" }, "babel-plugin-syntax-export-extensions": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=" }, "babel-plugin-syntax-flow": { "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "resolved": "http://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=" }, "babel-plugin-syntax-object-rest-spread": { @@ -1619,7 +1628,7 @@ "dependencies": { "colors": { "version": "1.0.3", - "resolved": "http://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" } } @@ -2310,7 +2319,7 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "requires": { "kind-of": "^3.0.2" @@ -2328,7 +2337,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "requires": { "kind-of": "^3.0.2" @@ -2663,8 +2672,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -2682,13 +2690,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2701,18 +2707,15 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -2815,8 +2818,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -2826,7 +2828,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2839,20 +2840,17 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "optional": true + "bundled": true }, "minipass": { "version": "2.2.4", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -2869,7 +2867,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -2942,8 +2939,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -2953,7 +2949,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3029,8 +3024,7 @@ }, "safe-buffer": { "version": "5.1.1", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -3060,7 +3054,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3078,7 +3071,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3117,13 +3109,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.0.2", - "bundled": true, - "optional": true + "bundled": true } } }, @@ -3285,7 +3275,7 @@ }, "globby": { "version": "8.0.1", - "resolved": "http://registry.npmjs.org/globby/-/globby-8.0.1.tgz", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", "requires": { "array-union": "^1.0.1", @@ -4458,7 +4448,7 @@ }, "jsesc": { "version": "1.3.0", - "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" }, "json-buffer": { @@ -4933,7 +4923,7 @@ }, "chalk": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", "requires": { "ansi-styles": "~1.0.0", @@ -5125,7 +5115,7 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-locale": { @@ -5140,7 +5130,7 @@ }, "os-tmpdir": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "p-cancelable": { @@ -5246,7 +5236,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { @@ -5570,7 +5560,7 @@ }, "regexpu-core": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", "requires": { "regenerate": "^1.2.1", @@ -5580,12 +5570,12 @@ }, "regjsgen": { "version": "0.2.0", - "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" }, "regjsparser": { "version": "0.1.5", - "resolved": "http://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "requires": { "jsesc": "~0.5.0" @@ -5593,7 +5583,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" } } @@ -5787,7 +5777,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "requires": { "ret": "~0.1.10" @@ -6449,7 +6439,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "supports-color": { @@ -6467,7 +6457,7 @@ }, "temp": { "version": "0.8.3", - "resolved": "http://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", "requires": { "os-tmpdir": "^1.0.0", @@ -6657,7 +6647,7 @@ }, "underscore": { "version": "1.6.0", - "resolved": "http://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" }, "union-value": { diff --git a/packages/utils/package.json b/packages/utils/package.json index 620aeaf5a2b..eb4395db0cd 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -31,6 +31,7 @@ "@types/node": "^10.12.9", "@types/p-each-series": "^1.0.0", "@types/prettier": "^1.15.0", + "@webpack-cli/webpack-scaffold": "^0.1.5", "typescript": "^3.1.6" }, "scripts": { From 2299848918615585646241d8db66324a1bc57229 Mon Sep 17 00:00:00 2001 From: rishabh3112 Date: Fri, 22 Mar 2019 14:04:28 +0530 Subject: [PATCH 06/34] chore(refactor): move schema to utils --- packages/utils/generators/add/index.ts | 2 +- packages/utils/generators/optionsSchema.json | 1989 ++++++++++++++++++ 2 files changed, 1990 insertions(+), 1 deletion(-) create mode 100644 packages/utils/generators/optionsSchema.json diff --git a/packages/utils/generators/add/index.ts b/packages/utils/generators/add/index.ts index 50571e41447..ead88bc2816 100644 --- a/packages/utils/generators/add/index.ts +++ b/packages/utils/generators/add/index.ts @@ -4,7 +4,7 @@ const PROPS: string[] = Array.from(PROP_TYPES.keys()); // tslint:disable:no-var-requires export const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); -export const webpackSchema = require("./utils/optionsSchema.json"); +export const webpackSchema = require("../optionsSchema.json"); /** * diff --git a/packages/utils/generators/optionsSchema.json b/packages/utils/generators/optionsSchema.json new file mode 100644 index 00000000000..aa272397d03 --- /dev/null +++ b/packages/utils/generators/optionsSchema.json @@ -0,0 +1,1989 @@ +{ + "additionalProperties": false, + "definitions": { + "common.pluginFunction": { + "description": "Function acting as plugin", + "instanceof": "Function", + "properties": { + "apply": { + "description": "The run point of the plugin, required method.", + "instanceof": "Function" + } + }, + "additionalProperties": true, + "required": [ + "apply" + ] + }, + "common.pluginObject": { + "description": "Plugin instance", + "type": "object", + "properties": { + "apply": { + "description": "The run point of the plugin, required method.", + "instanceof": "Function" + } + }, + "additionalProperties": true, + "required": [ + "apply" + ] + }, + "common.arrayOfStringOrStringArrayValues": { + "items": { + "description": "string or array of strings", + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "description": "A non-empty string", + "minLength": 1, + "type": "string" + }, + "type": "array" + } + ] + }, + "type": "array" + }, + "common.arrayOfStringValues": { + "items": { + "description": "A non-empty string", + "minLength": 1, + "type": "string" + }, + "type": "array" + }, + "common.nonEmptyArrayOfUniqueStringValues": { + "items": { + "description": "A non-empty string", + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array", + "uniqueItems": true + }, + "entry": { + "oneOf": [ + { + "minProperties": 1, + "additionalProperties": { + "description": "An entry point with name", + "oneOf": [ + { + "description": "The string is resolved to a module which is loaded upon startup.", + "minLength": 1, + "type": "string" + }, + { + "description": "All modules are loaded upon startup. The last one is exported.", + "anyOf": [ + { + "$ref": "#/definitions/common.nonEmptyArrayOfUniqueStringValues" + } + ] + } + ] + }, + "description": "Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.", + "type": "object" + }, + { + "description": "An entry point without name. The string is resolved to a module which is loaded upon startup.", + "minLength": 1, + "type": "string" + }, + { + "description": "An entry point without name. All modules are loaded upon startup. The last one is exported.", + "anyOf": [ + { + "$ref": "#/definitions/common.nonEmptyArrayOfUniqueStringValues" + } + ] + }, + { + "description": "A Function returning an entry object, an entry string, an entry array or a promise to these things.", + "instanceof": "Function" + } + ] + }, + "externals": { + "anyOf": [ + { + "description": "An exact matched dependency becomes external. The same string is used as external dependency.", + "type": "string" + }, + { + "additionalProperties": { + "description": "The dependency used for the external", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object" + }, + { + "type": "boolean" + } + ] + }, + "description": "If an dependency matches exactly a property of the object, the property value is used as dependency.", + "type": "object" + }, + { + "description": "`function(context, request, callback(err, result))` The function is called on each dependency.", + "instanceof": "Function" + }, + { + "description": "Every matched dependency becomes external.", + "instanceof": "RegExp" + }, + { + "items": { + "description": "External configuration", + "anyOf": [ + { + "$ref": "#/definitions/externals" + } + ] + }, + "type": "array" + } + ] + }, + "module": { + "additionalProperties": false, + "properties": { + "exprContextCritical": { + "description": "Enable warnings for full dynamic dependencies", + "type": "boolean" + }, + "exprContextRecursive": { + "description": "Enable recursive directory lookup for full dynamic dependencies", + "type": "boolean" + }, + "exprContextRegExp": { + "description": "Sets the default regular expression for full dynamic dependencies", + "anyOf": [ + { + "type": "boolean" + }, + { + "instanceof": "RegExp" + } + ] + }, + "exprContextRequest": { + "description": "Set the default request for full dynamic dependencies", + "type": "string" + }, + "noParse": { + "description": "Don't parse files matching. It's matched against the full resolved request.", + "anyOf": [ + { + "items": { + "description": "A regular expression, when matched the module is not parsed", + "instanceof": "RegExp" + }, + "minItems": 1, + "type": "array" + }, + { + "instanceof": "RegExp" + }, + { + "instanceof": "Function" + }, + { + "items": { + "description": "An absolute path, when the module starts with this path it is not parsed", + "type": "string", + "absolutePath": true + }, + "minItems": 1, + "type": "array" + }, + { + "type": "string", + "absolutePath": true + } + ] + }, + "rules": { + "allOf": [ + { + "$ref": "#/definitions/ruleSet-rules" + } + ], + "description": "An array of rules applied for modules." + }, + "defaultRules": { + "description": "An array of rules applied by default for modules.", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-rules" + } + ] + }, + "unknownContextCritical": { + "description": "Enable warnings when using the require function in a not statically analyse-able way", + "type": "boolean" + }, + "unknownContextRecursive": { + "description": "Enable recursive directory lookup when using the require function in a not statically analyse-able way", + "type": "boolean" + }, + "unknownContextRegExp": { + "description": "Sets the regular expression when using the require function in a not statically analyse-able way", + "anyOf": [ + { + "type": "boolean" + }, + { + "instanceof": "RegExp" + } + ] + }, + "unknownContextRequest": { + "description": "Sets the request when using the require function in a not statically analyse-able way", + "type": "string" + }, + "unsafeCache": { + "description": "Cache the resolving of module requests", + "anyOf": [ + { + "type": "boolean" + }, + { + "instanceof": "Function" + } + ] + }, + "wrappedContextCritical": { + "description": "Enable warnings for partial dynamic dependencies", + "type": "boolean" + }, + "wrappedContextRecursive": { + "description": "Enable recursive directory lookup for partial dynamic dependencies", + "type": "boolean" + }, + "wrappedContextRegExp": { + "description": "Set the inner regular expression for partial dynamic dependencies", + "instanceof": "RegExp" + }, + "strictExportPresence": { + "description": "Emit errors instead of warnings when imported names don't exist in imported module", + "type": "boolean" + }, + "strictThisContextOnImports": { + "description": "Handle the this context correctly according to the spec for namespace objects", + "type": "boolean" + } + }, + "type": "object" + }, + "output": { + "additionalProperties": false, + "properties": { + "auxiliaryComment": { + "description": "Add a comment in the UMD wrapper.", + "anyOf": [ + { + "description": "Append the same comment above each import style.", + "type": "string" + }, + { + "additionalProperties": false, + "description": "Set explicit comments for `commonjs`, `commonjs2`, `amd`, and `root`.", + "properties": { + "amd": { + "description": "Set comment for `amd` section in UMD", + "type": "string" + }, + "commonjs": { + "description": "Set comment for `commonjs` (exports) section in UMD", + "type": "string" + }, + "commonjs2": { + "description": "Set comment for `commonjs2` (module.exports) section in UMD", + "type": "string" + }, + "root": { + "description": "Set comment for `root` (global variable) section in UMD", + "type": "string" + } + }, + "type": "object" + } + ] + }, + "chunkFilename": { + "description": "The filename of non-entry chunks as relative path inside the `output.path` directory.", + "type": "string", + "absolutePath": false + }, + "webassemblyModuleFilename": { + "description": "The filename of WebAssembly modules as relative path inside the `output.path` directory.", + "type": "string", + "absolutePath": false + }, + "globalObject": { + "description": "An expression which is used to address the global object/scope in runtime code", + "type": "string", + "minLength": 1 + }, + "crossOriginLoading": { + "description": "This option enables cross-origin loading of chunks.", + "enum": [ + false, + "anonymous", + "use-credentials" + ] + }, + "jsonpScriptType": { + "description": "This option enables loading async chunks via a custom script type, such as script type=\"module\"", + "enum": [ + false, + "text/javascript", + "module" + ] + }, + "chunkLoadTimeout": { + "description": "Number of milliseconds before chunk request expires", + "type": "number" + }, + "devtoolFallbackModuleFilenameTemplate": { + "description": "Similar to `output.devtoolModuleFilenameTemplate`, but used in the case of duplicate module identifiers.", + "anyOf": [ + { + "type": "string" + }, + { + "instanceof": "Function" + } + ] + }, + "devtoolLineToLine": { + "description": "Enable line to line mapped mode for all/specified modules. Line to line mapped mode uses a simple SourceMap where each line of the generated source is mapped to the same line of the original source. It’s a performance optimization. Only use it if your performance need to be better and you are sure that input lines match which generated lines.", + "anyOf": [ + { + "description": "`true` enables it for all modules (not recommended)", + "type": "boolean" + }, + { + "description": "An object similar to `module.loaders` enables it for specific files.", + "type": "object" + } + ] + }, + "devtoolModuleFilenameTemplate": { + "description": "Filename template string of function for the sources array in a generated SourceMap.", + "anyOf": [ + { + "type": "string" + }, + { + "instanceof": "Function" + } + ] + }, + "devtoolNamespace": { + "description": "Module namespace to use when interpolating filename template string for the sources array in a generated SourceMap. Defaults to `output.library` if not set. It's useful for avoiding runtime collisions in sourcemaps from multiple webpack projects built as libraries.", + "type": "string" + }, + "filename": { + "description": "Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.", + "anyOf": [ + { + "type": "string" + }, + { + "instanceof": "Function" + } + ], + "absolutePath": false + }, + "hashDigest": { + "description": "Digest type used for the hash", + "enum": [ + "latin1", + "hex", + "base64" + ] + }, + "hashDigestLength": { + "description": "Number of chars which are used for the hash", + "minimum": 1, + "type": "number" + }, + "hashFunction": { + "description": "Algorithm used for generation the hash (see node.js crypto package)", + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "instanceof": "Function" + } + ] + }, + "hashSalt": { + "description": "Any string which is added to the hash to salt it", + "minLength": 1, + "type": "string" + }, + "hotUpdateChunkFilename": { + "description": "The filename of the Hot Update Chunks. They are inside the output.path directory.", + "anyOf": [ + { + "type": "string" + }, + { + "instanceof": "Function" + } + ], + "absolutePath": false + }, + "hotUpdateFunction": { + "description": "The JSONP function used by webpack for async loading of hot update chunks.", + "type": "string" + }, + "hotUpdateMainFilename": { + "description": "The filename of the Hot Update Main File. It is inside the `output.path` directory.", + "anyOf": [ + { + "type": "string" + }, + { + "instanceof": "Function" + } + ], + "absolutePath": false + }, + "jsonpFunction": { + "description": "The JSONP function used by webpack for async loading of chunks.", + "type": "string" + }, + "chunkCallbackName": { + "description": "The callback function name used by webpack for loading of chunks in WebWorkers.", + "type": "string" + }, + "library": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "description": "A part of the library name", + "type": "string" + }, + "type": "array" + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "root": { + "description": "Name of the property exposed globally by a UMD library", + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/common.arrayOfStringValues" + } + ] + }, + "amd": { + "description": "Name of the exposed AMD library in the UMD", + "type": "string" + }, + "commonjs": { + "description": "Name of the exposed commonjs export in the UMD", + "type": "string" + } + } + } + ], + "description": "If set, export the bundle as library. `output.library` is the name." + }, + "libraryTarget": { + "description": "Type of library", + "enum": [ + "var", + "assign", + "this", + "window", + "self", + "global", + "commonjs", + "commonjs2", + "commonjs-module", + "amd", + "umd", + "umd2", + "jsonp" + ] + }, + "libraryExport": { + "description": "Specify which export should be exposed as library", + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/common.arrayOfStringValues" + } + ] + }, + "path": { + "description": "The output directory as **absolute path** (required).", + "type": "string", + "absolutePath": true + }, + "pathinfo": { + "description": "Include comments with information about the modules.", + "type": "boolean" + }, + "publicPath": { + "description": "The `publicPath` specifies the public URL address of the output files when referenced in a browser.", + "anyOf": [ + { + "type": "string" + }, + { + "instanceof": "Function" + } + ] + }, + "sourceMapFilename": { + "description": "The filename of the SourceMaps for the JavaScript files. They are inside the `output.path` directory.", + "type": "string", + "absolutePath": false + }, + "sourcePrefix": { + "description": "Prefixes every line of the source in the bundle with this string.", + "type": "string" + }, + "strictModuleExceptionHandling": { + "description": "Handles exceptions in module loading correctly at a performance cost.", + "type": "boolean" + }, + "umdNamedDefine": { + "description": "If `output.libraryTarget` is set to umd and `output.library` is set, setting this to true will name the AMD module.", + "type": "boolean" + } + }, + "type": "object" + }, + "resolve": { + "additionalProperties": false, + "properties": { + "alias": { + "description": "Redirect module requests", + "anyOf": [ + { + "additionalProperties": { + "description": "New request", + "type": "string" + }, + "type": "object" + }, + { + "items": { + "description": "Alias configuration", + "additionalProperties": false, + "properties": { + "alias": { + "description": "New request", + "type": "string" + }, + "name": { + "description": "Request to be redirected", + "type": "string" + }, + "onlyModule": { + "description": "Redirect only exact matching request", + "type": "boolean" + } + }, + "type": "object" + }, + "type": "array" + } + ] + }, + "aliasFields": { + "description": "Fields in the description file (package.json) which are used to redirect requests inside the module", + "anyOf": [ + { + "$ref": "#/definitions/common.arrayOfStringOrStringArrayValues" + } + ] + }, + "cachePredicate": { + "description": "Predicate function to decide which requests should be cached", + "instanceof": "Function" + }, + "cacheWithContext": { + "description": "Include the context information in the cache identifier when caching", + "type": "boolean" + }, + "descriptionFiles": { + "description": "Filenames used to find a description file", + "anyOf": [ + { + "$ref": "#/definitions/common.arrayOfStringValues" + } + ] + }, + "enforceExtension": { + "description": "Enforce using one of the extensions from the extensions option", + "type": "boolean" + }, + "enforceModuleExtension": { + "description": "Enforce using one of the module extensions from the moduleExtensions option", + "type": "boolean" + }, + "extensions": { + "description": "Extensions added to the request when trying to find the file", + "anyOf": [ + { + "$ref": "#/definitions/common.arrayOfStringValues" + } + ] + }, + "fileSystem": { + "description": "Filesystem for the resolver" + }, + "mainFields": { + "description": "Field names from the description file (package.json) which are used to find the default entry point", + "anyOf": [ + { + "$ref": "#/definitions/common.arrayOfStringOrStringArrayValues" + } + ] + }, + "mainFiles": { + "description": "Filenames used to find the default entry point if there is no description file or main field", + "anyOf": [ + { + "$ref": "#/definitions/common.arrayOfStringValues" + } + ] + }, + "moduleExtensions": { + "description": "Extensions added to the module request when trying to find the module", + "anyOf": [ + { + "$ref": "#/definitions/common.arrayOfStringValues" + } + ] + }, + "modules": { + "description": "Folder names or directory paths where to find modules", + "anyOf": [ + { + "$ref": "#/definitions/common.arrayOfStringValues" + } + ] + }, + "plugins": { + "description": "Plugins for the resolver", + "type": "array", + "items": { + "description": "Plugin of type object or instanceof Function", + "anyOf": [ + { + "$ref": "#/definitions/common.pluginObject" + }, + { + "$ref": "#/definitions/common.pluginFunction" + } + ] + } + }, + "resolver": { + "description": "Custom resolver" + }, + "symlinks": { + "description": "Enable resolving symlinks to the original location", + "type": "boolean" + }, + "concord": { + "description": "Enable concord resolving extras", + "type": "boolean" + }, + "unsafeCache": { + "description": "Enable caching of successfully resolved requests", + "anyOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": true, + "type": "object" + } + ] + }, + "useSyncFileSystemCalls": { + "description": "Use synchronous filesystem calls for the resolver", + "type": "boolean" + } + }, + "type": "object" + }, + "ruleSet-condition": { + "anyOf": [ + { + "instanceof": "RegExp" + }, + { + "minLength": 1, + "type": "string" + }, + { + "instanceof": "Function" + }, + { + "$ref": "#/definitions/ruleSet-conditions" + }, + { + "additionalProperties": false, + "properties": { + "and": { + "description": "Logical AND", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-conditions" + } + ] + }, + "exclude": { + "description": "Exclude all modules matching any of these conditions", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-condition" + } + ] + }, + "include": { + "description": "Exclude all modules matching not any of these conditions", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-condition" + } + ] + }, + "not": { + "description": "Logical NOT", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-conditions" + } + ] + }, + "or": { + "description": "Logical OR", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-conditions" + } + ] + }, + "test": { + "description": "Exclude all modules matching any of these conditions", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-condition" + } + ] + } + }, + "type": "object" + } + ] + }, + "ruleSet-conditions": { + "items": { + "description": "A rule condition", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-condition" + } + ] + }, + "type": "array" + }, + "ruleSet-loader": { + "minLength": 1, + "type": "string" + }, + "ruleSet-query": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "string" + } + ] + }, + "ruleSet-rule": { + "additionalProperties": false, + "properties": { + "enforce": { + "description": "Enforce this rule as pre or post step", + "enum": [ + "pre", + "post" + ] + }, + "exclude": { + "description": "Shortcut for resource.exclude", + "allOf": [ + { + "$ref": "#/definitions/ruleSet-condition" + }, + { + "absolutePath": true + } + ] + }, + "include": { + "description": "Shortcut for resource.include", + "allOf": [ + { + "$ref": "#/definitions/ruleSet-condition" + }, + { + "absolutePath": true + } + ] + }, + "issuer": { + "description": "Match the issuer of the module (The module pointing to this module)", + "allOf": [ + { + "$ref": "#/definitions/ruleSet-condition" + }, + { + "absolutePath": true + } + ] + }, + "loader": { + "description": "Shortcut for use.loader", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-loader" + }, + { + "$ref": "#/definitions/ruleSet-use" + } + ] + }, + "loaders": { + "description": "Shortcut for use.loader", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-use" + } + ] + }, + "oneOf": { + "description": "Only execute the first matching rule in this array", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-rules" + } + ] + }, + "options": { + "description": "Shortcut for use.options", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-query" + } + ] + }, + "parser": { + "description": "Options for parsing", + "additionalProperties": true, + "type": "object" + }, + "resolve": { + "description": "Options for the resolver", + "type": "object", + "anyOf": [ + { + "$ref": "#/definitions/resolve" + } + ] + }, + "sideEffects": { + "description": "Flags a module as with or without side effects", + "type": "boolean" + }, + "query": { + "description": "Shortcut for use.query", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-query" + } + ] + }, + "type": { + "description": "Module type to use for the module", + "enum": [ + "javascript/auto", + "javascript/dynamic", + "javascript/esm", + "json", + "webassembly/experimental" + ] + }, + "resource": { + "description": "Match the resource path of the module", + "allOf": [ + { + "$ref": "#/definitions/ruleSet-condition" + }, + { + "absolutePath": true + } + ] + }, + "resourceQuery": { + "description": "Match the resource query of the module", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-condition" + } + ] + }, + "compiler": { + "description": "Match the child compiler name", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-condition" + } + ] + }, + "rules": { + "description": "Match and execute these rules when this rule is matched", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-rules" + } + ] + }, + "test": { + "description": "Shortcut for resource.test", + "allOf": [ + { + "$ref": "#/definitions/ruleSet-condition" + }, + { + "absolutePath": true + } + ] + }, + "use": { + "description": "Modifiers applied to the module when rule is matched", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-use" + } + ] + } + }, + "type": "object" + }, + "ruleSet-rules": { + "items": { + "description": "A rule", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-rule" + } + ] + }, + "type": "array" + }, + "ruleSet-use": { + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-use-item" + }, + { + "instanceof": "Function" + }, + { + "items": { + "description": "An use item", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-use-item" + } + ] + }, + "type": "array" + } + ] + }, + "ruleSet-use-item": { + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-loader" + }, + { + "instanceof": "Function" + }, + { + "additionalProperties": false, + "properties": { + "loader": { + "description": "Loader name", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-loader" + } + ] + }, + "options": { + "description": "Loader options", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-query" + } + ] + }, + "ident": { + "description": "Unique loader identifier", + "type": "string" + }, + "query": { + "description": "Loader query", + "anyOf": [ + { + "$ref": "#/definitions/ruleSet-query" + } + ] + } + }, + "type": "object" + } + ] + }, + "filter-item-types": { + "anyOf": [ + { + "instanceof": "RegExp" + }, + { + "type": "string" + }, + { + "instanceof": "Function" + } + ] + }, + "filter-types": { + "anyOf": [ + { + "$ref": "#/definitions/filter-item-types" + }, + { + "type": "array", + "items": { + "description": "Rule to filter", + "anyOf": [ + { + "$ref": "#/definitions/filter-item-types" + } + ] + } + } + ] + } + }, + "properties": { + "mode": { + "description": "Enable production optimizations or development hints.", + "enum": [ + "development", + "production", + "none" + ] + }, + "amd": { + "description": "Set the value of `require.amd` and `define.amd`." + }, + "bail": { + "description": "Report the first error as a hard error instead of tolerating it.", + "type": "boolean" + }, + "cache": { + "description": "Cache generated modules and chunks to improve performance for multiple incremental builds.", + "anyOf": [ + { + "description": "You can pass `false` to disable it.", + "type": "boolean" + }, + { + "description": "You can pass an object to enable it and let webpack use the passed object as cache. This way you can share the cache object between multiple compiler calls.", + "type": "object" + } + ] + }, + "context": { + "description": "The base directory (absolute path!) for resolving the `entry` option. If `output.pathinfo` is set, the included pathinfo is shortened to this directory.", + "type": "string", + "absolutePath": true + }, + "dependencies": { + "description": "References to other configurations to depend on.", + "items": { + "description": "References to another configuration to depend on.", + "type": "string" + }, + "type": "array" + }, + "devServer": { + "description": "Options for the webpack-dev-server", + "type": "object" + }, + "devtool": { + "description": "A developer tool to enhance debugging.", + "anyOf": [ + { + "type": "string" + }, + { + "enum": [ + false + ] + } + ] + }, + "entry": { + "description": "The entry point(s) of the compilation.", + "anyOf": [ + { + "$ref": "#/definitions/entry" + } + ] + }, + "externals": { + "description": "Specify dependencies that shouldn't be resolved by webpack, but should become dependencies of the resulting bundle. The kind of the dependency depends on `output.libraryTarget`.", + "anyOf": [ + { + "$ref": "#/definitions/externals" + } + ] + }, + "loader": { + "description": "Custom values available in the loader context.", + "type": "object" + }, + "module": { + "description": "Options affecting the normal modules (`NormalModuleFactory`).", + "anyOf": [ + { + "$ref": "#/definitions/module" + } + ] + }, + "name": { + "description": "Name of the configuration. Used when loading multiple configurations.", + "type": "string" + }, + "node": { + "description": "Include polyfills or mocks for various node stuff.", + "anyOf": [ + { + "enum": [ + false + ] + }, + { + "additionalProperties": { + "description": "Include a polyfill for the node.js module", + "enum": [ + false, + true, + "mock", + "empty" + ] + }, + "properties": { + "Buffer": { + "description": "Include a polyfill for the 'Buffer' variable", + "enum": [ + false, + true, + "mock" + ] + }, + "__dirname": { + "description": "Include a polyfill for the '__dirname' variable", + "enum": [ + false, + true, + "mock" + ] + }, + "__filename": { + "description": "Include a polyfill for the '__filename' variable", + "enum": [ + false, + true, + "mock" + ] + }, + "console": { + "description": "Include a polyfill for the 'console' variable", + "enum": [ + false, + true, + "mock" + ] + }, + "global": { + "description": "Include a polyfill for the 'global' variable", + "type": "boolean" + }, + "process": { + "description": "Include a polyfill for the 'process' variable", + "enum": [ + false, + true, + "mock" + ] + } + }, + "type": "object" + } + ] + }, + "output": { + "description": "Options affecting the output of the compilation. `output` options tell webpack how to write the compiled files to disk.", + "anyOf": [ + { + "$ref": "#/definitions/output" + } + ] + }, + "optimization": { + "description": "Enables/Disables integrated optimizations", + "type": "object", + "additionalProperties": false, + "properties": { + "removeAvailableModules": { + "description": "Removes modules from chunks when these modules are already included in all parents", + "type": "boolean" + }, + "removeEmptyChunks": { + "description": "Remove chunks which are empty", + "type": "boolean" + }, + "mergeDuplicateChunks": { + "description": "Merge chunks which contain the same modules", + "type": "boolean" + }, + "flagIncludedChunks": { + "description": "Also flag chunks as loaded which contain a subset of the modules", + "type": "boolean" + }, + "occurrenceOrder": { + "description": "Figure out a order of modules which results in the smallest initial bundle", + "type": "boolean" + }, + "sideEffects": { + "description": "Skip over modules which are flagged to contain no side effects when exports are not used", + "type": "boolean" + }, + "providedExports": { + "description": "Figure out which exports are provided by modules to generate more efficient code", + "type": "boolean" + }, + "usedExports": { + "description": "Figure out which exports are used by modules to mangle export names, omit unused exports and generate more efficient code", + "type": "boolean" + }, + "concatenateModules": { + "description": "Concatenate modules when possible to generate less modules, more efficient code and enable more optimizations by the minimizer", + "type": "boolean" + }, + "splitChunks": { + "description": "Optimize duplication and caching by splitting chunks by shared modules and cache group", + "oneOf": [ + { + "enum": [ + false + ] + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "chunks": { + "description": "Select chunks for determining shared modules (defaults to \"async\", \"initial\" and \"all\" requires adding these chunks to the HTML)", + "oneOf": [ + { + "enum": [ + "initial", + "async", + "all" + ] + }, + { + "instanceof": "Function" + } + ] + }, + "minSize": { + "description": "Minimal size for the created chunk", + "type": "number", + "minimum": 0 + }, + "minChunks": { + "description": "Minimum number of times a module has to be duplicated until it's considered for splitting", + "type": "number", + "minimum": 1 + }, + "maxAsyncRequests": { + "description": "Maximum number of requests which are accepted for on-demand loading", + "type": "number", + "minimum": 1 + }, + "maxInitialRequests": { + "description": "Maximum number of initial chunks which are accepted for an entry point", + "type": "number", + "minimum": 1 + }, + "name": { + "description": "Give chunks created a name (chunks with equal name are merged)", + "oneOf": [ + { + "type": "boolean" + }, + { + "instanceof": "Function" + }, + { + "type": "string" + } + ] + }, + "filename": { + "description": "Sets the template for the filename for created chunks (Only works for initial chunks)", + "type": "string", + "minLength": 1 + }, + "automaticNameDelimiter": { + "description": "Sets the name delimiter for created chunks", + "type": "string", + "minLength": 1 + }, + "cacheGroups": { + "description": "Assign modules to a cache group (modules from different cache groups are tried to keep in separate chunks)", + "type": "object", + "additionalProperties": { + "description": "Configuration for a cache group", + "anyOf": [ + { + "enum": [ + false + ] + }, + { + "instanceof": "Function" + }, + { + "type": "string" + }, + { + "instanceof": "RegExp" + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "test": { + "description": "Assign modules to a cache group", + "oneOf": [ + { + "instanceof": "Function" + }, + { + "type": "string" + }, + { + "instanceof": "RegExp" + } + ] + }, + "chunks": { + "description": "Select chunks for determining cache group content (defaults to \"initial\", \"initial\" and \"all\" requires adding these chunks to the HTML)", + "oneOf": [ + { + "enum": [ + "initial", + "async", + "all" + ] + }, + { + "instanceof": "Function" + } + ] + }, + "enforce": { + "description": "Ignore minimum size, minimum chunks and maximum requests and always create chunks for this cache group", + "type": "boolean" + }, + "priority": { + "description": "Priority of this cache group", + "type": "number" + }, + "minSize": { + "description": "Minimal size for the created chunk", + "type": "number", + "minimum": 0 + }, + "minChunks": { + "description": "Minimum number of times a module has to be duplicated until it's considered for splitting", + "type": "number", + "minimum": 1 + }, + "maxAsyncRequests": { + "description": "Maximum number of requests which are accepted for on-demand loading", + "type": "number", + "minimum": 1 + }, + "maxInitialRequests": { + "description": "Maximum number of initial chunks which are accepted for an entry point", + "type": "number", + "minimum": 1 + }, + "reuseExistingChunk": { + "description": "Try to reuse existing chunk (with name) when it has matching modules", + "type": "boolean" + }, + "name": { + "description": "Give chunks for this cache group a name (chunks with equal name are merged)", + "oneOf": [ + { + "type": "boolean" + }, + { + "instanceof": "Function" + }, + { + "type": "string" + } + ] + }, + "filename": { + "description": "Sets the template for the filename for created chunks (Only works for initial chunks)", + "type": "string", + "minLength": 1 + } + } + } + ] + } + } + } + } + ] + }, + "runtimeChunk": { + "description": "Create an additional chunk which contains only the webpack runtime and chunk hash maps", + "oneOf": [ + { + "type": "boolean" + }, + { + "enum": [ + "single", + "multiple" + ] + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "description": "The name or name factory for the runtime chunks", + "oneOf": [ + { + "type": "string" + }, + { + "instanceof": "Function" + } + ] + } + } + } + ] + }, + "noEmitOnErrors": { + "description": "Avoid emitting assets when errors occur", + "type": "boolean" + }, + "namedModules": { + "description": "Use readable module identifiers for better debugging", + "type": "boolean" + }, + "namedChunks": { + "description": "Use readable chunk identifiers for better debugging", + "type": "boolean" + }, + "portableRecords": { + "description": "Generate records with relative paths to be able to move the context folder", + "type": "boolean" + }, + "minimize": { + "description": "Enable minimizing the output. Uses optimization.minimizer.", + "type": "boolean" + }, + "minimizer": { + "description": "Minimizer(s) to use for minimizing the output", + "type": "array", + "items": { + "description": "Plugin of type object or instanceof Function", + "anyOf": [ + { + "$ref": "#/definitions/common.pluginObject" + }, + { + "$ref": "#/definitions/common.pluginFunction" + } + ] + } + }, + "nodeEnv": { + "description": "Set process.env.NODE_ENV to a specific value", + "anyOf": [ + { + "enum": [ + false + ] + }, + { + "type": "string" + } + ] + } + } + }, + "parallelism": { + "description": "The number of parallel processed modules in the compilation.", + "minimum": 1, + "type": "number" + }, + "performance": { + "description": "Configuration for web performance recommendations.", + "anyOf": [ + { + "enum": [ + false + ] + }, + { + "additionalProperties": false, + "properties": { + "assetFilter": { + "description": "Filter function to select assets that are checked", + "instanceof": "Function" + }, + "hints": { + "description": "Sets the format of the hints: warnings, errors or nothing at all", + "enum": [ + false, + "warning", + "error" + ] + }, + "maxEntrypointSize": { + "description": "Total size of an entry point (in bytes)", + "type": "number" + }, + "maxAssetSize": { + "description": "Filesize limit (in bytes) when exceeded, that webpack will provide performance hints", + "type": "number" + } + }, + "type": "object" + } + ] + }, + "plugins": { + "description": "Add additional plugins to the compiler.", + "type": "array", + "items": { + "description": "Plugin of type object or instanceof Function", + "anyOf": [ + { + "$ref": "#/definitions/common.pluginObject" + }, + { + "$ref": "#/definitions/common.pluginFunction" + } + ] + } + }, + "profile": { + "description": "Capture timing information for each module.", + "type": "boolean" + }, + "recordsInputPath": { + "description": "Store compiler state to a json file.", + "type": "string", + "absolutePath": true + }, + "recordsOutputPath": { + "description": "Load compiler state from a json file.", + "type": "string", + "absolutePath": true + }, + "recordsPath": { + "description": "Store/Load compiler state from/to a json file. This will result in persistent ids of modules and chunks. An absolute path is expected. `recordsPath` is used for `recordsInputPath` and `recordsOutputPath` if they left undefined.", + "type": "string", + "absolutePath": true + }, + "resolve": { + "description": "Options for the resolver", + "anyOf": [ + { + "$ref": "#/definitions/resolve" + } + ] + }, + "resolveLoader": { + "description": "Options for the resolver when resolving loaders", + "anyOf": [ + { + "$ref": "#/definitions/resolve" + } + ] + }, + "serve": { + "description": "Options for webpack-serve", + "type": "object" + }, + "stats": { + "description": "Used by the webpack CLI program to pass stats options.", + "anyOf": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "all": { + "type": "boolean", + "description": "fallback value for stats options when an option is not defined (has precedence over local webpack defaults)" + }, + "context": { + "type": "string", + "description": "context directory for request shortening", + "absolutePath": true + }, + "hash": { + "type": "boolean", + "description": "add the hash of the compilation" + }, + "version": { + "type": "boolean", + "description": "add webpack version information" + }, + "timings": { + "type": "boolean", + "description": "add timing information" + }, + "builtAt": { + "type": "boolean", + "description": "add built at time information" + }, + "performance": { + "type": "boolean", + "description": "add performance hint flags" + }, + "depth": { + "type": "boolean", + "description": "add module depth in module graph" + }, + "assets": { + "type": "boolean", + "description": "add assets information" + }, + "env": { + "type": "boolean", + "description": "add --env information" + }, + "colors": { + "description": "Enables/Disables colorful output", + "oneOf": [ + { + "type": "boolean", + "description": "`webpack --colors` equivalent" + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "bold": { + "description": "Custom color for bold text", + "type": "string" + }, + "red": { + "description": "Custom color for red text", + "type": "string" + }, + "green": { + "description": "Custom color for green text", + "type": "string" + }, + "cyan": { + "description": "Custom color for cyan text", + "type": "string" + }, + "magenta": { + "description": "Custom color for magenta text", + "type": "string" + }, + "yellow": { + "description": "Custom color for yellow text", + "type": "string" + } + } + } + ] + }, + "maxModules": { + "type": "number", + "description": "Set the maximum number of modules to be shown" + }, + "chunks": { + "type": "boolean", + "description": "add chunk information" + }, + "chunkModules": { + "type": "boolean", + "description": "add built modules information to chunk information" + }, + "modules": { + "type": "boolean", + "description": "add built modules information" + }, + "nestedModules": { + "type": "boolean", + "description": "add information about modules nested in other modules (like with module concatenation)" + }, + "moduleAssets": { + "type": "boolean", + "description": "add information about assets inside modules" + }, + "children": { + "type": "boolean", + "description": "add children information" + }, + "cached": { + "type": "boolean", + "description": "add also information about cached (not built) modules" + }, + "cachedAssets": { + "type": "boolean", + "description": "Show cached assets (setting this to `false` only shows emitted files)" + }, + "reasons": { + "type": "boolean", + "description": "add information about the reasons why modules are included" + }, + "source": { + "type": "boolean", + "description": "add the source code of modules" + }, + "warnings": { + "type": "boolean", + "description": "add warnings" + }, + "errors": { + "type": "boolean", + "description": "add errors" + }, + "warningsFilter": { + "description": "Suppress warnings that match the specified filters. Filters can be Strings, RegExps or Functions", + "anyOf": [ + { + "$ref": "#/definitions/filter-types" + } + ] + }, + "excludeAssets": { + "description": "Suppress assets that match the specified filters. Filters can be Strings, RegExps or Functions", + "anyOf": [ + { + "$ref": "#/definitions/filter-types" + } + ] + }, + "excludeModules": { + "description": "Suppress modules that match the specified filters. Filters can be Strings, RegExps, Booleans or Functions", + "anyOf": [ + { + "$ref": "#/definitions/filter-types" + }, + { + "type": "boolean" + } + ] + }, + "exclude": { + "description": "Please use excludeModules instead.", + "anyOf": [ + { + "$ref": "#/definitions/filter-types" + }, + { + "type": "boolean" + } + ] + }, + "entrypoints": { + "type": "boolean", + "description": "Display the entry points with the corresponding bundles" + }, + "chunkGroups": { + "type": "boolean", + "description": "Display all chunk groups with the corresponding bundles" + }, + "errorDetails": { + "type": "boolean", + "description": "add details to errors (like resolving log)" + }, + "chunkOrigins": { + "type": "boolean", + "description": "add the origins of chunks and chunk merging info" + }, + "modulesSort": { + "type": "string", + "description": "sort the modules by that field" + }, + "moduleTrace": { + "type": "boolean", + "description": "add dependencies and origin of warnings/errors" + }, + "chunksSort": { + "type": "string", + "description": "sort the chunks by that field" + }, + "assetsSort": { + "type": "string", + "description": "sort the assets by that field" + }, + "publicPath": { + "type": "boolean", + "description": "Add public path information" + }, + "outputPath": { + "type": "boolean", + "description": "Add output path information" + }, + "providedExports": { + "type": "boolean", + "description": "show exports provided by modules" + }, + "usedExports": { + "type": "boolean", + "description": "show exports used by modules" + }, + "optimizationBailout": { + "type": "boolean", + "description": "show reasons why optimization bailed out for modules" + } + } + }, + { + "type": "boolean" + }, + { + "enum": [ + "none", + "errors-only", + "minimal", + "normal", + "detailed", + "verbose" + ] + } + ] + }, + "target": { + "description": "Environment to build for", + "anyOf": [ + { + "enum": [ + "web", + "webworker", + "node", + "async-node", + "node-webkit", + "electron-main", + "electron-renderer" + ] + }, + { + "instanceof": "Function" + } + ] + }, + "watch": { + "description": "Enter watch mode, which rebuilds on file change.", + "type": "boolean" + }, + "watchOptions": { + "description": "Options for the watcher", + "additionalProperties": false, + "properties": { + "aggregateTimeout": { + "description": "Delay the rebuilt after the first change. Value is a time in ms.", + "type": "number" + }, + "ignored": { + "description": "Ignore some files from watching" + }, + "stdin": { + "description": "Stop watching when stdin stream has ended", + "type": "boolean" + }, + "poll": { + "description": "Enable polling mode for watching", + "anyOf": [ + { + "description": "`true`: use polling.", + "type": "boolean" + }, + { + "description": "`number`: use polling with specified interval.", + "type": "number" + } + ] + } + }, + "type": "object" + } + }, + "type": "object" + } + \ No newline at end of file From ccf0dce0464d8301d24e7f833427db5389ffc29a Mon Sep 17 00:00:00 2001 From: rishabh3112 Date: Tue, 26 Mar 2019 23:38:55 +0530 Subject: [PATCH 07/34] fix(add): apply suggestions --- packages/generators/add-generator.ts | 2 +- packages/utils/generators/add/questions/index.ts | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index ee775757668..0c9e33dfc52 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -116,7 +116,7 @@ export default class AddGenerator extends Generator { .then((mergeFileAnswer: { mergeFile: string; }) => { - const resolvedPath = resolve(process.env.PWD, mergeFileAnswer.mergeFile); + const resolvedPath = resolve(process.cwd(), mergeFileAnswer.mergeFile); const mergeConfig = require(resolvedPath); this.configuration.config.merge = mergeConfig; }); diff --git a/packages/utils/generators/add/questions/index.ts b/packages/utils/generators/add/questions/index.ts index 9ee042fdc13..350bce2873e 100644 --- a/packages/utils/generators/add/questions/index.ts +++ b/packages/utils/generators/add/questions/index.ts @@ -45,16 +45,15 @@ export const topScopeQuestion = Input( const mergeFileQuestionFunction = () => { const question = "What is the location of webpack configuration with which you want to merge current configuration?"; const validator = (path: string) => { - const resolvedPath = resolve(process.env.PWD, path); + const resolvedPath = resolve(process.cwd(), path); if (existsSync(resolvedPath)) { if (/\.js$/.test(path)) { if (typeof require(resolvedPath) !== "object") { return "Given file doesn't export an Object"; } return true; - } else { - return "Path doesn't corresponds to a javascript file"; } + return "Path doesn't corresponds to a javascript file"; } return "Invalid path provided"; }; From 915c4abc40e871b82a7740f35913c36d61345f03 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Tue, 28 May 2019 15:57:35 +0530 Subject: [PATCH 08/34] chore(refactor): move questions to utils --- packages/generators/add-generator.ts | 99 +- .../utils}/add/index.ts | 4 +- .../utils}/add/questions/index.ts | 0 packages/utils/generators/optionsSchema.json | 1989 ----------------- 4 files changed, 25 insertions(+), 2067 deletions(-) rename packages/{utils/generators => generators/utils}/add/index.ts (93%) rename packages/{utils/generators => generators/utils}/add/questions/index.ts (100%) delete mode 100644 packages/utils/generators/optionsSchema.json diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 727230344d3..3de5bcde66b 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -6,72 +6,24 @@ import { manualOrListInput, mergeFileQuestion, topScopeQuestion, -} from "@webpack-cli/utils/generators/add/questions"; +} from "./utils/add/questions"; + +import { + replaceAt, + traverseAndGetProperties, + webpackDevServerSchema, + webpackSchema +} from './utils/add' + import npmExists from "@webpack-cli/utils/npm-exists"; import { getPackageManager } from "@webpack-cli/utils/package-manager"; -import PROP_TYPES from "@webpack-cli/utils/prop-types"; -import { AutoComplete, Confirm, Input, List } from "@webpack-cli/webpack-scaffold"; +import { Input, List } from "@webpack-cli/webpack-scaffold"; import { SchemaProperties, WebpackOptions } from "./types"; import entryQuestions from "./utils/entry"; - -import webpackDevServerSchema from "webpack-dev-server/lib/options.json"; -import webpackSchema from "./utils/optionsSchema.json"; -const PROPS: string[] = Array.from(PROP_TYPES.keys()); - -/** - * - * Replaces the string with a substring at the given index - * https://gist.github.com/efenacigiray/9367920 - * - * @param {String} str - string to be modified - * @param {Number} index - index to replace from - * @param {String} replace - string to replace starting from index - * - * @returns {String} string - The newly mutated string - * - */ -function replaceAt(str: string, index: number, replace: string): string { - return str.substring(0, index) + replace + str.substring(index + 1); -} - -/** - * - * Checks if the given array has a given property - * - * @param {Array} arr - array to check - * @param {String} prop - property to check existence of - * - * @returns {Boolean} hasProp - Boolean indicating if the property - * is present - */ -const traverseAndGetProperties = (arr: object[], prop: string): boolean => { - let hasProp = false; - arr.forEach( - (p: object): void => { - if (p[prop]) { - hasProp = true; - } - } - ); - return hasProp; -}; - -/** - * - * Search config properties - * - * @param {Object} answers Prompt answers object - * @param {String} input Input search string - * - * @returns {Promise} Returns promise which resolves to filtered props - * - */ -const searchProps = (answers: object, input: string): Promise => { - input = input || ""; - return Promise.resolve(PROPS.filter((prop: string): boolean => prop.toLowerCase().includes(input.toLowerCase()))); -}; +import { AutoComplete } from "@webpack-cli/webpack-scaffold"; +import { resolve } from "path"; /** * @@ -103,15 +55,13 @@ export default class AddGenerator extends Generator { } }; const { registerPrompt } = this.env.adapter.promptModule; - registerPrompt("autocomplete", autoComplete); + registerPrompt("autocomplete", AutoComplete); } public prompting(): Promise { const done: () => {} = this.async(); let action: string; const self: this = this; - const manualOrListInput: (promptAction: string) => Generator.Question = (promptAction: string): Generator.Question => - Input("actionAnswer", `What do you want to add to ${promptAction}?`); let inputPrompt: Generator.Question; // first index indicates if it has a deep prop, 2nd indicates what kind of @@ -120,13 +70,7 @@ export default class AddGenerator extends Generator { // eslint-disable-next-line const isDeepProp: any[] = [false, false]; - return this.prompt([ - AutoComplete("actionType", "What property do you want to add to?", { - pageSize: 7, - source: searchProps, - suggestOnly: false - }) - ]) + return this.prompt(actionTypeQuestion) .then( (actionTypeAnswer: { actionType: string }): void => { // Set initial prop, like devtool @@ -138,9 +82,7 @@ export default class AddGenerator extends Generator { .then( (): Promise => { if (action === "entry") { - return this.prompt([ - Confirm("entryType", "Will your application have multiple bundles?", false) - ]) + return this.prompt(entryTypeQuestion) .then( (entryTypeAnswer: { entryType: boolean }): Promise => { // Ask different questions for entry points @@ -155,7 +97,7 @@ export default class AddGenerator extends Generator { ); } else { if (action === "topScope") { - return this.prompt([Input("topScope", "What do you want to add to topScope?")]).then( + return this.prompt(topScopeQuestion).then( (topScopeAnswer: { topScope: string }): void => { this.configuration.config.topScope.push(topScopeAnswer.topScope); done(); @@ -169,7 +111,12 @@ export default class AddGenerator extends Generator { }) => { const resolvedPath = resolve(process.cwd(), mergeFileAnswer.mergeFile); const mergeConfig = require(resolvedPath); - this.configuration.config.merge = mergeConfig; + (this.configuration.config.merge as { + configName?: string; + topScope?: string[]; + item?: string; + webpackOptions?: WebpackOptions; + }) = mergeConfig; }); } } @@ -446,7 +393,7 @@ export default class AddGenerator extends Generator { (action === "devtool" || action === "watch" || action === "mode") ) { this.configuration.config.item = action; - this.configuration.config.webpackOptions[action] = answerToAction.actionAnswer; + (this.configuration.config.webpackOptions[action] as string) = answerToAction.actionAnswer; done(); return; } diff --git a/packages/utils/generators/add/index.ts b/packages/generators/utils/add/index.ts similarity index 93% rename from packages/utils/generators/add/index.ts rename to packages/generators/utils/add/index.ts index ead88bc2816..9b6e9eaac22 100644 --- a/packages/utils/generators/add/index.ts +++ b/packages/generators/utils/add/index.ts @@ -1,6 +1,6 @@ -import PROP_TYPES from "../../prop-types"; +import PROP_TYPES from "@webpack-cli/utils/prop-types"; -const PROPS: string[] = Array.from(PROP_TYPES.keys()); +export const PROPS: string[] = Array.from(PROP_TYPES.keys()); // tslint:disable:no-var-requires export const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); diff --git a/packages/utils/generators/add/questions/index.ts b/packages/generators/utils/add/questions/index.ts similarity index 100% rename from packages/utils/generators/add/questions/index.ts rename to packages/generators/utils/add/questions/index.ts diff --git a/packages/utils/generators/optionsSchema.json b/packages/utils/generators/optionsSchema.json deleted file mode 100644 index aa272397d03..00000000000 --- a/packages/utils/generators/optionsSchema.json +++ /dev/null @@ -1,1989 +0,0 @@ -{ - "additionalProperties": false, - "definitions": { - "common.pluginFunction": { - "description": "Function acting as plugin", - "instanceof": "Function", - "properties": { - "apply": { - "description": "The run point of the plugin, required method.", - "instanceof": "Function" - } - }, - "additionalProperties": true, - "required": [ - "apply" - ] - }, - "common.pluginObject": { - "description": "Plugin instance", - "type": "object", - "properties": { - "apply": { - "description": "The run point of the plugin, required method.", - "instanceof": "Function" - } - }, - "additionalProperties": true, - "required": [ - "apply" - ] - }, - "common.arrayOfStringOrStringArrayValues": { - "items": { - "description": "string or array of strings", - "anyOf": [ - { - "minLength": 1, - "type": "string" - }, - { - "items": { - "description": "A non-empty string", - "minLength": 1, - "type": "string" - }, - "type": "array" - } - ] - }, - "type": "array" - }, - "common.arrayOfStringValues": { - "items": { - "description": "A non-empty string", - "minLength": 1, - "type": "string" - }, - "type": "array" - }, - "common.nonEmptyArrayOfUniqueStringValues": { - "items": { - "description": "A non-empty string", - "minLength": 1, - "type": "string" - }, - "minItems": 1, - "type": "array", - "uniqueItems": true - }, - "entry": { - "oneOf": [ - { - "minProperties": 1, - "additionalProperties": { - "description": "An entry point with name", - "oneOf": [ - { - "description": "The string is resolved to a module which is loaded upon startup.", - "minLength": 1, - "type": "string" - }, - { - "description": "All modules are loaded upon startup. The last one is exported.", - "anyOf": [ - { - "$ref": "#/definitions/common.nonEmptyArrayOfUniqueStringValues" - } - ] - } - ] - }, - "description": "Multiple entry bundles are created. The key is the chunk name. The value can be a string or an array.", - "type": "object" - }, - { - "description": "An entry point without name. The string is resolved to a module which is loaded upon startup.", - "minLength": 1, - "type": "string" - }, - { - "description": "An entry point without name. All modules are loaded upon startup. The last one is exported.", - "anyOf": [ - { - "$ref": "#/definitions/common.nonEmptyArrayOfUniqueStringValues" - } - ] - }, - { - "description": "A Function returning an entry object, an entry string, an entry array or a promise to these things.", - "instanceof": "Function" - } - ] - }, - "externals": { - "anyOf": [ - { - "description": "An exact matched dependency becomes external. The same string is used as external dependency.", - "type": "string" - }, - { - "additionalProperties": { - "description": "The dependency used for the external", - "anyOf": [ - { - "type": "string" - }, - { - "type": "object" - }, - { - "type": "boolean" - } - ] - }, - "description": "If an dependency matches exactly a property of the object, the property value is used as dependency.", - "type": "object" - }, - { - "description": "`function(context, request, callback(err, result))` The function is called on each dependency.", - "instanceof": "Function" - }, - { - "description": "Every matched dependency becomes external.", - "instanceof": "RegExp" - }, - { - "items": { - "description": "External configuration", - "anyOf": [ - { - "$ref": "#/definitions/externals" - } - ] - }, - "type": "array" - } - ] - }, - "module": { - "additionalProperties": false, - "properties": { - "exprContextCritical": { - "description": "Enable warnings for full dynamic dependencies", - "type": "boolean" - }, - "exprContextRecursive": { - "description": "Enable recursive directory lookup for full dynamic dependencies", - "type": "boolean" - }, - "exprContextRegExp": { - "description": "Sets the default regular expression for full dynamic dependencies", - "anyOf": [ - { - "type": "boolean" - }, - { - "instanceof": "RegExp" - } - ] - }, - "exprContextRequest": { - "description": "Set the default request for full dynamic dependencies", - "type": "string" - }, - "noParse": { - "description": "Don't parse files matching. It's matched against the full resolved request.", - "anyOf": [ - { - "items": { - "description": "A regular expression, when matched the module is not parsed", - "instanceof": "RegExp" - }, - "minItems": 1, - "type": "array" - }, - { - "instanceof": "RegExp" - }, - { - "instanceof": "Function" - }, - { - "items": { - "description": "An absolute path, when the module starts with this path it is not parsed", - "type": "string", - "absolutePath": true - }, - "minItems": 1, - "type": "array" - }, - { - "type": "string", - "absolutePath": true - } - ] - }, - "rules": { - "allOf": [ - { - "$ref": "#/definitions/ruleSet-rules" - } - ], - "description": "An array of rules applied for modules." - }, - "defaultRules": { - "description": "An array of rules applied by default for modules.", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-rules" - } - ] - }, - "unknownContextCritical": { - "description": "Enable warnings when using the require function in a not statically analyse-able way", - "type": "boolean" - }, - "unknownContextRecursive": { - "description": "Enable recursive directory lookup when using the require function in a not statically analyse-able way", - "type": "boolean" - }, - "unknownContextRegExp": { - "description": "Sets the regular expression when using the require function in a not statically analyse-able way", - "anyOf": [ - { - "type": "boolean" - }, - { - "instanceof": "RegExp" - } - ] - }, - "unknownContextRequest": { - "description": "Sets the request when using the require function in a not statically analyse-able way", - "type": "string" - }, - "unsafeCache": { - "description": "Cache the resolving of module requests", - "anyOf": [ - { - "type": "boolean" - }, - { - "instanceof": "Function" - } - ] - }, - "wrappedContextCritical": { - "description": "Enable warnings for partial dynamic dependencies", - "type": "boolean" - }, - "wrappedContextRecursive": { - "description": "Enable recursive directory lookup for partial dynamic dependencies", - "type": "boolean" - }, - "wrappedContextRegExp": { - "description": "Set the inner regular expression for partial dynamic dependencies", - "instanceof": "RegExp" - }, - "strictExportPresence": { - "description": "Emit errors instead of warnings when imported names don't exist in imported module", - "type": "boolean" - }, - "strictThisContextOnImports": { - "description": "Handle the this context correctly according to the spec for namespace objects", - "type": "boolean" - } - }, - "type": "object" - }, - "output": { - "additionalProperties": false, - "properties": { - "auxiliaryComment": { - "description": "Add a comment in the UMD wrapper.", - "anyOf": [ - { - "description": "Append the same comment above each import style.", - "type": "string" - }, - { - "additionalProperties": false, - "description": "Set explicit comments for `commonjs`, `commonjs2`, `amd`, and `root`.", - "properties": { - "amd": { - "description": "Set comment for `amd` section in UMD", - "type": "string" - }, - "commonjs": { - "description": "Set comment for `commonjs` (exports) section in UMD", - "type": "string" - }, - "commonjs2": { - "description": "Set comment for `commonjs2` (module.exports) section in UMD", - "type": "string" - }, - "root": { - "description": "Set comment for `root` (global variable) section in UMD", - "type": "string" - } - }, - "type": "object" - } - ] - }, - "chunkFilename": { - "description": "The filename of non-entry chunks as relative path inside the `output.path` directory.", - "type": "string", - "absolutePath": false - }, - "webassemblyModuleFilename": { - "description": "The filename of WebAssembly modules as relative path inside the `output.path` directory.", - "type": "string", - "absolutePath": false - }, - "globalObject": { - "description": "An expression which is used to address the global object/scope in runtime code", - "type": "string", - "minLength": 1 - }, - "crossOriginLoading": { - "description": "This option enables cross-origin loading of chunks.", - "enum": [ - false, - "anonymous", - "use-credentials" - ] - }, - "jsonpScriptType": { - "description": "This option enables loading async chunks via a custom script type, such as script type=\"module\"", - "enum": [ - false, - "text/javascript", - "module" - ] - }, - "chunkLoadTimeout": { - "description": "Number of milliseconds before chunk request expires", - "type": "number" - }, - "devtoolFallbackModuleFilenameTemplate": { - "description": "Similar to `output.devtoolModuleFilenameTemplate`, but used in the case of duplicate module identifiers.", - "anyOf": [ - { - "type": "string" - }, - { - "instanceof": "Function" - } - ] - }, - "devtoolLineToLine": { - "description": "Enable line to line mapped mode for all/specified modules. Line to line mapped mode uses a simple SourceMap where each line of the generated source is mapped to the same line of the original source. It’s a performance optimization. Only use it if your performance need to be better and you are sure that input lines match which generated lines.", - "anyOf": [ - { - "description": "`true` enables it for all modules (not recommended)", - "type": "boolean" - }, - { - "description": "An object similar to `module.loaders` enables it for specific files.", - "type": "object" - } - ] - }, - "devtoolModuleFilenameTemplate": { - "description": "Filename template string of function for the sources array in a generated SourceMap.", - "anyOf": [ - { - "type": "string" - }, - { - "instanceof": "Function" - } - ] - }, - "devtoolNamespace": { - "description": "Module namespace to use when interpolating filename template string for the sources array in a generated SourceMap. Defaults to `output.library` if not set. It's useful for avoiding runtime collisions in sourcemaps from multiple webpack projects built as libraries.", - "type": "string" - }, - "filename": { - "description": "Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.", - "anyOf": [ - { - "type": "string" - }, - { - "instanceof": "Function" - } - ], - "absolutePath": false - }, - "hashDigest": { - "description": "Digest type used for the hash", - "enum": [ - "latin1", - "hex", - "base64" - ] - }, - "hashDigestLength": { - "description": "Number of chars which are used for the hash", - "minimum": 1, - "type": "number" - }, - "hashFunction": { - "description": "Algorithm used for generation the hash (see node.js crypto package)", - "anyOf": [ - { - "type": "string", - "minLength": 1 - }, - { - "instanceof": "Function" - } - ] - }, - "hashSalt": { - "description": "Any string which is added to the hash to salt it", - "minLength": 1, - "type": "string" - }, - "hotUpdateChunkFilename": { - "description": "The filename of the Hot Update Chunks. They are inside the output.path directory.", - "anyOf": [ - { - "type": "string" - }, - { - "instanceof": "Function" - } - ], - "absolutePath": false - }, - "hotUpdateFunction": { - "description": "The JSONP function used by webpack for async loading of hot update chunks.", - "type": "string" - }, - "hotUpdateMainFilename": { - "description": "The filename of the Hot Update Main File. It is inside the `output.path` directory.", - "anyOf": [ - { - "type": "string" - }, - { - "instanceof": "Function" - } - ], - "absolutePath": false - }, - "jsonpFunction": { - "description": "The JSONP function used by webpack for async loading of chunks.", - "type": "string" - }, - "chunkCallbackName": { - "description": "The callback function name used by webpack for loading of chunks in WebWorkers.", - "type": "string" - }, - "library": { - "anyOf": [ - { - "type": "string" - }, - { - "items": { - "description": "A part of the library name", - "type": "string" - }, - "type": "array" - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "root": { - "description": "Name of the property exposed globally by a UMD library", - "anyOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/common.arrayOfStringValues" - } - ] - }, - "amd": { - "description": "Name of the exposed AMD library in the UMD", - "type": "string" - }, - "commonjs": { - "description": "Name of the exposed commonjs export in the UMD", - "type": "string" - } - } - } - ], - "description": "If set, export the bundle as library. `output.library` is the name." - }, - "libraryTarget": { - "description": "Type of library", - "enum": [ - "var", - "assign", - "this", - "window", - "self", - "global", - "commonjs", - "commonjs2", - "commonjs-module", - "amd", - "umd", - "umd2", - "jsonp" - ] - }, - "libraryExport": { - "description": "Specify which export should be exposed as library", - "anyOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/common.arrayOfStringValues" - } - ] - }, - "path": { - "description": "The output directory as **absolute path** (required).", - "type": "string", - "absolutePath": true - }, - "pathinfo": { - "description": "Include comments with information about the modules.", - "type": "boolean" - }, - "publicPath": { - "description": "The `publicPath` specifies the public URL address of the output files when referenced in a browser.", - "anyOf": [ - { - "type": "string" - }, - { - "instanceof": "Function" - } - ] - }, - "sourceMapFilename": { - "description": "The filename of the SourceMaps for the JavaScript files. They are inside the `output.path` directory.", - "type": "string", - "absolutePath": false - }, - "sourcePrefix": { - "description": "Prefixes every line of the source in the bundle with this string.", - "type": "string" - }, - "strictModuleExceptionHandling": { - "description": "Handles exceptions in module loading correctly at a performance cost.", - "type": "boolean" - }, - "umdNamedDefine": { - "description": "If `output.libraryTarget` is set to umd and `output.library` is set, setting this to true will name the AMD module.", - "type": "boolean" - } - }, - "type": "object" - }, - "resolve": { - "additionalProperties": false, - "properties": { - "alias": { - "description": "Redirect module requests", - "anyOf": [ - { - "additionalProperties": { - "description": "New request", - "type": "string" - }, - "type": "object" - }, - { - "items": { - "description": "Alias configuration", - "additionalProperties": false, - "properties": { - "alias": { - "description": "New request", - "type": "string" - }, - "name": { - "description": "Request to be redirected", - "type": "string" - }, - "onlyModule": { - "description": "Redirect only exact matching request", - "type": "boolean" - } - }, - "type": "object" - }, - "type": "array" - } - ] - }, - "aliasFields": { - "description": "Fields in the description file (package.json) which are used to redirect requests inside the module", - "anyOf": [ - { - "$ref": "#/definitions/common.arrayOfStringOrStringArrayValues" - } - ] - }, - "cachePredicate": { - "description": "Predicate function to decide which requests should be cached", - "instanceof": "Function" - }, - "cacheWithContext": { - "description": "Include the context information in the cache identifier when caching", - "type": "boolean" - }, - "descriptionFiles": { - "description": "Filenames used to find a description file", - "anyOf": [ - { - "$ref": "#/definitions/common.arrayOfStringValues" - } - ] - }, - "enforceExtension": { - "description": "Enforce using one of the extensions from the extensions option", - "type": "boolean" - }, - "enforceModuleExtension": { - "description": "Enforce using one of the module extensions from the moduleExtensions option", - "type": "boolean" - }, - "extensions": { - "description": "Extensions added to the request when trying to find the file", - "anyOf": [ - { - "$ref": "#/definitions/common.arrayOfStringValues" - } - ] - }, - "fileSystem": { - "description": "Filesystem for the resolver" - }, - "mainFields": { - "description": "Field names from the description file (package.json) which are used to find the default entry point", - "anyOf": [ - { - "$ref": "#/definitions/common.arrayOfStringOrStringArrayValues" - } - ] - }, - "mainFiles": { - "description": "Filenames used to find the default entry point if there is no description file or main field", - "anyOf": [ - { - "$ref": "#/definitions/common.arrayOfStringValues" - } - ] - }, - "moduleExtensions": { - "description": "Extensions added to the module request when trying to find the module", - "anyOf": [ - { - "$ref": "#/definitions/common.arrayOfStringValues" - } - ] - }, - "modules": { - "description": "Folder names or directory paths where to find modules", - "anyOf": [ - { - "$ref": "#/definitions/common.arrayOfStringValues" - } - ] - }, - "plugins": { - "description": "Plugins for the resolver", - "type": "array", - "items": { - "description": "Plugin of type object or instanceof Function", - "anyOf": [ - { - "$ref": "#/definitions/common.pluginObject" - }, - { - "$ref": "#/definitions/common.pluginFunction" - } - ] - } - }, - "resolver": { - "description": "Custom resolver" - }, - "symlinks": { - "description": "Enable resolving symlinks to the original location", - "type": "boolean" - }, - "concord": { - "description": "Enable concord resolving extras", - "type": "boolean" - }, - "unsafeCache": { - "description": "Enable caching of successfully resolved requests", - "anyOf": [ - { - "type": "boolean" - }, - { - "additionalProperties": true, - "type": "object" - } - ] - }, - "useSyncFileSystemCalls": { - "description": "Use synchronous filesystem calls for the resolver", - "type": "boolean" - } - }, - "type": "object" - }, - "ruleSet-condition": { - "anyOf": [ - { - "instanceof": "RegExp" - }, - { - "minLength": 1, - "type": "string" - }, - { - "instanceof": "Function" - }, - { - "$ref": "#/definitions/ruleSet-conditions" - }, - { - "additionalProperties": false, - "properties": { - "and": { - "description": "Logical AND", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-conditions" - } - ] - }, - "exclude": { - "description": "Exclude all modules matching any of these conditions", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-condition" - } - ] - }, - "include": { - "description": "Exclude all modules matching not any of these conditions", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-condition" - } - ] - }, - "not": { - "description": "Logical NOT", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-conditions" - } - ] - }, - "or": { - "description": "Logical OR", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-conditions" - } - ] - }, - "test": { - "description": "Exclude all modules matching any of these conditions", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-condition" - } - ] - } - }, - "type": "object" - } - ] - }, - "ruleSet-conditions": { - "items": { - "description": "A rule condition", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-condition" - } - ] - }, - "type": "array" - }, - "ruleSet-loader": { - "minLength": 1, - "type": "string" - }, - "ruleSet-query": { - "anyOf": [ - { - "type": "object" - }, - { - "type": "string" - } - ] - }, - "ruleSet-rule": { - "additionalProperties": false, - "properties": { - "enforce": { - "description": "Enforce this rule as pre or post step", - "enum": [ - "pre", - "post" - ] - }, - "exclude": { - "description": "Shortcut for resource.exclude", - "allOf": [ - { - "$ref": "#/definitions/ruleSet-condition" - }, - { - "absolutePath": true - } - ] - }, - "include": { - "description": "Shortcut for resource.include", - "allOf": [ - { - "$ref": "#/definitions/ruleSet-condition" - }, - { - "absolutePath": true - } - ] - }, - "issuer": { - "description": "Match the issuer of the module (The module pointing to this module)", - "allOf": [ - { - "$ref": "#/definitions/ruleSet-condition" - }, - { - "absolutePath": true - } - ] - }, - "loader": { - "description": "Shortcut for use.loader", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-loader" - }, - { - "$ref": "#/definitions/ruleSet-use" - } - ] - }, - "loaders": { - "description": "Shortcut for use.loader", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-use" - } - ] - }, - "oneOf": { - "description": "Only execute the first matching rule in this array", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-rules" - } - ] - }, - "options": { - "description": "Shortcut for use.options", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-query" - } - ] - }, - "parser": { - "description": "Options for parsing", - "additionalProperties": true, - "type": "object" - }, - "resolve": { - "description": "Options for the resolver", - "type": "object", - "anyOf": [ - { - "$ref": "#/definitions/resolve" - } - ] - }, - "sideEffects": { - "description": "Flags a module as with or without side effects", - "type": "boolean" - }, - "query": { - "description": "Shortcut for use.query", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-query" - } - ] - }, - "type": { - "description": "Module type to use for the module", - "enum": [ - "javascript/auto", - "javascript/dynamic", - "javascript/esm", - "json", - "webassembly/experimental" - ] - }, - "resource": { - "description": "Match the resource path of the module", - "allOf": [ - { - "$ref": "#/definitions/ruleSet-condition" - }, - { - "absolutePath": true - } - ] - }, - "resourceQuery": { - "description": "Match the resource query of the module", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-condition" - } - ] - }, - "compiler": { - "description": "Match the child compiler name", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-condition" - } - ] - }, - "rules": { - "description": "Match and execute these rules when this rule is matched", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-rules" - } - ] - }, - "test": { - "description": "Shortcut for resource.test", - "allOf": [ - { - "$ref": "#/definitions/ruleSet-condition" - }, - { - "absolutePath": true - } - ] - }, - "use": { - "description": "Modifiers applied to the module when rule is matched", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-use" - } - ] - } - }, - "type": "object" - }, - "ruleSet-rules": { - "items": { - "description": "A rule", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-rule" - } - ] - }, - "type": "array" - }, - "ruleSet-use": { - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-use-item" - }, - { - "instanceof": "Function" - }, - { - "items": { - "description": "An use item", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-use-item" - } - ] - }, - "type": "array" - } - ] - }, - "ruleSet-use-item": { - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-loader" - }, - { - "instanceof": "Function" - }, - { - "additionalProperties": false, - "properties": { - "loader": { - "description": "Loader name", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-loader" - } - ] - }, - "options": { - "description": "Loader options", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-query" - } - ] - }, - "ident": { - "description": "Unique loader identifier", - "type": "string" - }, - "query": { - "description": "Loader query", - "anyOf": [ - { - "$ref": "#/definitions/ruleSet-query" - } - ] - } - }, - "type": "object" - } - ] - }, - "filter-item-types": { - "anyOf": [ - { - "instanceof": "RegExp" - }, - { - "type": "string" - }, - { - "instanceof": "Function" - } - ] - }, - "filter-types": { - "anyOf": [ - { - "$ref": "#/definitions/filter-item-types" - }, - { - "type": "array", - "items": { - "description": "Rule to filter", - "anyOf": [ - { - "$ref": "#/definitions/filter-item-types" - } - ] - } - } - ] - } - }, - "properties": { - "mode": { - "description": "Enable production optimizations or development hints.", - "enum": [ - "development", - "production", - "none" - ] - }, - "amd": { - "description": "Set the value of `require.amd` and `define.amd`." - }, - "bail": { - "description": "Report the first error as a hard error instead of tolerating it.", - "type": "boolean" - }, - "cache": { - "description": "Cache generated modules and chunks to improve performance for multiple incremental builds.", - "anyOf": [ - { - "description": "You can pass `false` to disable it.", - "type": "boolean" - }, - { - "description": "You can pass an object to enable it and let webpack use the passed object as cache. This way you can share the cache object between multiple compiler calls.", - "type": "object" - } - ] - }, - "context": { - "description": "The base directory (absolute path!) for resolving the `entry` option. If `output.pathinfo` is set, the included pathinfo is shortened to this directory.", - "type": "string", - "absolutePath": true - }, - "dependencies": { - "description": "References to other configurations to depend on.", - "items": { - "description": "References to another configuration to depend on.", - "type": "string" - }, - "type": "array" - }, - "devServer": { - "description": "Options for the webpack-dev-server", - "type": "object" - }, - "devtool": { - "description": "A developer tool to enhance debugging.", - "anyOf": [ - { - "type": "string" - }, - { - "enum": [ - false - ] - } - ] - }, - "entry": { - "description": "The entry point(s) of the compilation.", - "anyOf": [ - { - "$ref": "#/definitions/entry" - } - ] - }, - "externals": { - "description": "Specify dependencies that shouldn't be resolved by webpack, but should become dependencies of the resulting bundle. The kind of the dependency depends on `output.libraryTarget`.", - "anyOf": [ - { - "$ref": "#/definitions/externals" - } - ] - }, - "loader": { - "description": "Custom values available in the loader context.", - "type": "object" - }, - "module": { - "description": "Options affecting the normal modules (`NormalModuleFactory`).", - "anyOf": [ - { - "$ref": "#/definitions/module" - } - ] - }, - "name": { - "description": "Name of the configuration. Used when loading multiple configurations.", - "type": "string" - }, - "node": { - "description": "Include polyfills or mocks for various node stuff.", - "anyOf": [ - { - "enum": [ - false - ] - }, - { - "additionalProperties": { - "description": "Include a polyfill for the node.js module", - "enum": [ - false, - true, - "mock", - "empty" - ] - }, - "properties": { - "Buffer": { - "description": "Include a polyfill for the 'Buffer' variable", - "enum": [ - false, - true, - "mock" - ] - }, - "__dirname": { - "description": "Include a polyfill for the '__dirname' variable", - "enum": [ - false, - true, - "mock" - ] - }, - "__filename": { - "description": "Include a polyfill for the '__filename' variable", - "enum": [ - false, - true, - "mock" - ] - }, - "console": { - "description": "Include a polyfill for the 'console' variable", - "enum": [ - false, - true, - "mock" - ] - }, - "global": { - "description": "Include a polyfill for the 'global' variable", - "type": "boolean" - }, - "process": { - "description": "Include a polyfill for the 'process' variable", - "enum": [ - false, - true, - "mock" - ] - } - }, - "type": "object" - } - ] - }, - "output": { - "description": "Options affecting the output of the compilation. `output` options tell webpack how to write the compiled files to disk.", - "anyOf": [ - { - "$ref": "#/definitions/output" - } - ] - }, - "optimization": { - "description": "Enables/Disables integrated optimizations", - "type": "object", - "additionalProperties": false, - "properties": { - "removeAvailableModules": { - "description": "Removes modules from chunks when these modules are already included in all parents", - "type": "boolean" - }, - "removeEmptyChunks": { - "description": "Remove chunks which are empty", - "type": "boolean" - }, - "mergeDuplicateChunks": { - "description": "Merge chunks which contain the same modules", - "type": "boolean" - }, - "flagIncludedChunks": { - "description": "Also flag chunks as loaded which contain a subset of the modules", - "type": "boolean" - }, - "occurrenceOrder": { - "description": "Figure out a order of modules which results in the smallest initial bundle", - "type": "boolean" - }, - "sideEffects": { - "description": "Skip over modules which are flagged to contain no side effects when exports are not used", - "type": "boolean" - }, - "providedExports": { - "description": "Figure out which exports are provided by modules to generate more efficient code", - "type": "boolean" - }, - "usedExports": { - "description": "Figure out which exports are used by modules to mangle export names, omit unused exports and generate more efficient code", - "type": "boolean" - }, - "concatenateModules": { - "description": "Concatenate modules when possible to generate less modules, more efficient code and enable more optimizations by the minimizer", - "type": "boolean" - }, - "splitChunks": { - "description": "Optimize duplication and caching by splitting chunks by shared modules and cache group", - "oneOf": [ - { - "enum": [ - false - ] - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "chunks": { - "description": "Select chunks for determining shared modules (defaults to \"async\", \"initial\" and \"all\" requires adding these chunks to the HTML)", - "oneOf": [ - { - "enum": [ - "initial", - "async", - "all" - ] - }, - { - "instanceof": "Function" - } - ] - }, - "minSize": { - "description": "Minimal size for the created chunk", - "type": "number", - "minimum": 0 - }, - "minChunks": { - "description": "Minimum number of times a module has to be duplicated until it's considered for splitting", - "type": "number", - "minimum": 1 - }, - "maxAsyncRequests": { - "description": "Maximum number of requests which are accepted for on-demand loading", - "type": "number", - "minimum": 1 - }, - "maxInitialRequests": { - "description": "Maximum number of initial chunks which are accepted for an entry point", - "type": "number", - "minimum": 1 - }, - "name": { - "description": "Give chunks created a name (chunks with equal name are merged)", - "oneOf": [ - { - "type": "boolean" - }, - { - "instanceof": "Function" - }, - { - "type": "string" - } - ] - }, - "filename": { - "description": "Sets the template for the filename for created chunks (Only works for initial chunks)", - "type": "string", - "minLength": 1 - }, - "automaticNameDelimiter": { - "description": "Sets the name delimiter for created chunks", - "type": "string", - "minLength": 1 - }, - "cacheGroups": { - "description": "Assign modules to a cache group (modules from different cache groups are tried to keep in separate chunks)", - "type": "object", - "additionalProperties": { - "description": "Configuration for a cache group", - "anyOf": [ - { - "enum": [ - false - ] - }, - { - "instanceof": "Function" - }, - { - "type": "string" - }, - { - "instanceof": "RegExp" - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "test": { - "description": "Assign modules to a cache group", - "oneOf": [ - { - "instanceof": "Function" - }, - { - "type": "string" - }, - { - "instanceof": "RegExp" - } - ] - }, - "chunks": { - "description": "Select chunks for determining cache group content (defaults to \"initial\", \"initial\" and \"all\" requires adding these chunks to the HTML)", - "oneOf": [ - { - "enum": [ - "initial", - "async", - "all" - ] - }, - { - "instanceof": "Function" - } - ] - }, - "enforce": { - "description": "Ignore minimum size, minimum chunks and maximum requests and always create chunks for this cache group", - "type": "boolean" - }, - "priority": { - "description": "Priority of this cache group", - "type": "number" - }, - "minSize": { - "description": "Minimal size for the created chunk", - "type": "number", - "minimum": 0 - }, - "minChunks": { - "description": "Minimum number of times a module has to be duplicated until it's considered for splitting", - "type": "number", - "minimum": 1 - }, - "maxAsyncRequests": { - "description": "Maximum number of requests which are accepted for on-demand loading", - "type": "number", - "minimum": 1 - }, - "maxInitialRequests": { - "description": "Maximum number of initial chunks which are accepted for an entry point", - "type": "number", - "minimum": 1 - }, - "reuseExistingChunk": { - "description": "Try to reuse existing chunk (with name) when it has matching modules", - "type": "boolean" - }, - "name": { - "description": "Give chunks for this cache group a name (chunks with equal name are merged)", - "oneOf": [ - { - "type": "boolean" - }, - { - "instanceof": "Function" - }, - { - "type": "string" - } - ] - }, - "filename": { - "description": "Sets the template for the filename for created chunks (Only works for initial chunks)", - "type": "string", - "minLength": 1 - } - } - } - ] - } - } - } - } - ] - }, - "runtimeChunk": { - "description": "Create an additional chunk which contains only the webpack runtime and chunk hash maps", - "oneOf": [ - { - "type": "boolean" - }, - { - "enum": [ - "single", - "multiple" - ] - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "description": "The name or name factory for the runtime chunks", - "oneOf": [ - { - "type": "string" - }, - { - "instanceof": "Function" - } - ] - } - } - } - ] - }, - "noEmitOnErrors": { - "description": "Avoid emitting assets when errors occur", - "type": "boolean" - }, - "namedModules": { - "description": "Use readable module identifiers for better debugging", - "type": "boolean" - }, - "namedChunks": { - "description": "Use readable chunk identifiers for better debugging", - "type": "boolean" - }, - "portableRecords": { - "description": "Generate records with relative paths to be able to move the context folder", - "type": "boolean" - }, - "minimize": { - "description": "Enable minimizing the output. Uses optimization.minimizer.", - "type": "boolean" - }, - "minimizer": { - "description": "Minimizer(s) to use for minimizing the output", - "type": "array", - "items": { - "description": "Plugin of type object or instanceof Function", - "anyOf": [ - { - "$ref": "#/definitions/common.pluginObject" - }, - { - "$ref": "#/definitions/common.pluginFunction" - } - ] - } - }, - "nodeEnv": { - "description": "Set process.env.NODE_ENV to a specific value", - "anyOf": [ - { - "enum": [ - false - ] - }, - { - "type": "string" - } - ] - } - } - }, - "parallelism": { - "description": "The number of parallel processed modules in the compilation.", - "minimum": 1, - "type": "number" - }, - "performance": { - "description": "Configuration for web performance recommendations.", - "anyOf": [ - { - "enum": [ - false - ] - }, - { - "additionalProperties": false, - "properties": { - "assetFilter": { - "description": "Filter function to select assets that are checked", - "instanceof": "Function" - }, - "hints": { - "description": "Sets the format of the hints: warnings, errors or nothing at all", - "enum": [ - false, - "warning", - "error" - ] - }, - "maxEntrypointSize": { - "description": "Total size of an entry point (in bytes)", - "type": "number" - }, - "maxAssetSize": { - "description": "Filesize limit (in bytes) when exceeded, that webpack will provide performance hints", - "type": "number" - } - }, - "type": "object" - } - ] - }, - "plugins": { - "description": "Add additional plugins to the compiler.", - "type": "array", - "items": { - "description": "Plugin of type object or instanceof Function", - "anyOf": [ - { - "$ref": "#/definitions/common.pluginObject" - }, - { - "$ref": "#/definitions/common.pluginFunction" - } - ] - } - }, - "profile": { - "description": "Capture timing information for each module.", - "type": "boolean" - }, - "recordsInputPath": { - "description": "Store compiler state to a json file.", - "type": "string", - "absolutePath": true - }, - "recordsOutputPath": { - "description": "Load compiler state from a json file.", - "type": "string", - "absolutePath": true - }, - "recordsPath": { - "description": "Store/Load compiler state from/to a json file. This will result in persistent ids of modules and chunks. An absolute path is expected. `recordsPath` is used for `recordsInputPath` and `recordsOutputPath` if they left undefined.", - "type": "string", - "absolutePath": true - }, - "resolve": { - "description": "Options for the resolver", - "anyOf": [ - { - "$ref": "#/definitions/resolve" - } - ] - }, - "resolveLoader": { - "description": "Options for the resolver when resolving loaders", - "anyOf": [ - { - "$ref": "#/definitions/resolve" - } - ] - }, - "serve": { - "description": "Options for webpack-serve", - "type": "object" - }, - "stats": { - "description": "Used by the webpack CLI program to pass stats options.", - "anyOf": [ - { - "type": "object", - "additionalProperties": false, - "properties": { - "all": { - "type": "boolean", - "description": "fallback value for stats options when an option is not defined (has precedence over local webpack defaults)" - }, - "context": { - "type": "string", - "description": "context directory for request shortening", - "absolutePath": true - }, - "hash": { - "type": "boolean", - "description": "add the hash of the compilation" - }, - "version": { - "type": "boolean", - "description": "add webpack version information" - }, - "timings": { - "type": "boolean", - "description": "add timing information" - }, - "builtAt": { - "type": "boolean", - "description": "add built at time information" - }, - "performance": { - "type": "boolean", - "description": "add performance hint flags" - }, - "depth": { - "type": "boolean", - "description": "add module depth in module graph" - }, - "assets": { - "type": "boolean", - "description": "add assets information" - }, - "env": { - "type": "boolean", - "description": "add --env information" - }, - "colors": { - "description": "Enables/Disables colorful output", - "oneOf": [ - { - "type": "boolean", - "description": "`webpack --colors` equivalent" - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "bold": { - "description": "Custom color for bold text", - "type": "string" - }, - "red": { - "description": "Custom color for red text", - "type": "string" - }, - "green": { - "description": "Custom color for green text", - "type": "string" - }, - "cyan": { - "description": "Custom color for cyan text", - "type": "string" - }, - "magenta": { - "description": "Custom color for magenta text", - "type": "string" - }, - "yellow": { - "description": "Custom color for yellow text", - "type": "string" - } - } - } - ] - }, - "maxModules": { - "type": "number", - "description": "Set the maximum number of modules to be shown" - }, - "chunks": { - "type": "boolean", - "description": "add chunk information" - }, - "chunkModules": { - "type": "boolean", - "description": "add built modules information to chunk information" - }, - "modules": { - "type": "boolean", - "description": "add built modules information" - }, - "nestedModules": { - "type": "boolean", - "description": "add information about modules nested in other modules (like with module concatenation)" - }, - "moduleAssets": { - "type": "boolean", - "description": "add information about assets inside modules" - }, - "children": { - "type": "boolean", - "description": "add children information" - }, - "cached": { - "type": "boolean", - "description": "add also information about cached (not built) modules" - }, - "cachedAssets": { - "type": "boolean", - "description": "Show cached assets (setting this to `false` only shows emitted files)" - }, - "reasons": { - "type": "boolean", - "description": "add information about the reasons why modules are included" - }, - "source": { - "type": "boolean", - "description": "add the source code of modules" - }, - "warnings": { - "type": "boolean", - "description": "add warnings" - }, - "errors": { - "type": "boolean", - "description": "add errors" - }, - "warningsFilter": { - "description": "Suppress warnings that match the specified filters. Filters can be Strings, RegExps or Functions", - "anyOf": [ - { - "$ref": "#/definitions/filter-types" - } - ] - }, - "excludeAssets": { - "description": "Suppress assets that match the specified filters. Filters can be Strings, RegExps or Functions", - "anyOf": [ - { - "$ref": "#/definitions/filter-types" - } - ] - }, - "excludeModules": { - "description": "Suppress modules that match the specified filters. Filters can be Strings, RegExps, Booleans or Functions", - "anyOf": [ - { - "$ref": "#/definitions/filter-types" - }, - { - "type": "boolean" - } - ] - }, - "exclude": { - "description": "Please use excludeModules instead.", - "anyOf": [ - { - "$ref": "#/definitions/filter-types" - }, - { - "type": "boolean" - } - ] - }, - "entrypoints": { - "type": "boolean", - "description": "Display the entry points with the corresponding bundles" - }, - "chunkGroups": { - "type": "boolean", - "description": "Display all chunk groups with the corresponding bundles" - }, - "errorDetails": { - "type": "boolean", - "description": "add details to errors (like resolving log)" - }, - "chunkOrigins": { - "type": "boolean", - "description": "add the origins of chunks and chunk merging info" - }, - "modulesSort": { - "type": "string", - "description": "sort the modules by that field" - }, - "moduleTrace": { - "type": "boolean", - "description": "add dependencies and origin of warnings/errors" - }, - "chunksSort": { - "type": "string", - "description": "sort the chunks by that field" - }, - "assetsSort": { - "type": "string", - "description": "sort the assets by that field" - }, - "publicPath": { - "type": "boolean", - "description": "Add public path information" - }, - "outputPath": { - "type": "boolean", - "description": "Add output path information" - }, - "providedExports": { - "type": "boolean", - "description": "show exports provided by modules" - }, - "usedExports": { - "type": "boolean", - "description": "show exports used by modules" - }, - "optimizationBailout": { - "type": "boolean", - "description": "show reasons why optimization bailed out for modules" - } - } - }, - { - "type": "boolean" - }, - { - "enum": [ - "none", - "errors-only", - "minimal", - "normal", - "detailed", - "verbose" - ] - } - ] - }, - "target": { - "description": "Environment to build for", - "anyOf": [ - { - "enum": [ - "web", - "webworker", - "node", - "async-node", - "node-webkit", - "electron-main", - "electron-renderer" - ] - }, - { - "instanceof": "Function" - } - ] - }, - "watch": { - "description": "Enter watch mode, which rebuilds on file change.", - "type": "boolean" - }, - "watchOptions": { - "description": "Options for the watcher", - "additionalProperties": false, - "properties": { - "aggregateTimeout": { - "description": "Delay the rebuilt after the first change. Value is a time in ms.", - "type": "number" - }, - "ignored": { - "description": "Ignore some files from watching" - }, - "stdin": { - "description": "Stop watching when stdin stream has ended", - "type": "boolean" - }, - "poll": { - "description": "Enable polling mode for watching", - "anyOf": [ - { - "description": "`true`: use polling.", - "type": "boolean" - }, - { - "description": "`number`: use polling with specified interval.", - "type": "number" - } - ] - } - }, - "type": "object" - } - }, - "type": "object" - } - \ No newline at end of file From 5778bdfdc1cf4dc862701cb5322bac48708a4930 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Tue, 28 May 2019 16:15:58 +0530 Subject: [PATCH 09/34] chore: lint --- packages/generators/add-generator.ts | 11 +++++++++-- packages/generators/utils/add/questions/index.ts | 6 +++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 3de5bcde66b..ef846d6411b 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -22,8 +22,9 @@ import { Input, List } from "@webpack-cli/webpack-scaffold"; import { SchemaProperties, WebpackOptions } from "./types"; import entryQuestions from "./utils/entry"; -import { AutoComplete } from "@webpack-cli/webpack-scaffold"; -import { resolve } from "path"; +import * as AutoComplete from "inquirer-autocomplete-prompt"; +import path, { resolve } from "path"; +import glob from 'glob' /** * @@ -41,6 +42,12 @@ export default class AddGenerator extends Generator { configName?: string; topScope?: string[]; item?: string; + merge?: { + configName?: string; + topScope?: string[]; + item?: string; + webpackOptions?: WebpackOptions; + }; webpackOptions?: WebpackOptions; }; }; diff --git a/packages/generators/utils/add/questions/index.ts b/packages/generators/utils/add/questions/index.ts index 350bce2873e..93be7644639 100644 --- a/packages/generators/utils/add/questions/index.ts +++ b/packages/generators/utils/add/questions/index.ts @@ -1,22 +1,22 @@ import { AutoComplete, Confirm, - IInquirerInput, + InquirerInput, Input, InputValidate, - List, } from "@webpack-cli/webpack-scaffold"; import { existsSync } from "fs"; import { resolve } from "path"; import { searchProps, } from "../index"; +import { Question } from "inquirer"; /** * Returns Inquirer question for given action * @param action string */ -export const manualOrListInput: (action: string) => IInquirerInput = (action: string) => { +export const manualOrListInput: (action: string) => Question = (action: string) => { const actionQuestion = `What do you want to add to ${action}?`; return Input("actionAnswer", actionQuestion); }; From 078294438d85991b2dec95eba16cc282100cf844 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Tue, 28 May 2019 16:24:55 +0530 Subject: [PATCH 10/34] chore: lint --- packages/generators/add-generator.ts | 2 +- packages/generators/utils/add/questions/index.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index ef846d6411b..82755ba9d28 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -24,7 +24,7 @@ import { SchemaProperties, WebpackOptions } from "./types"; import entryQuestions from "./utils/entry"; import * as AutoComplete from "inquirer-autocomplete-prompt"; import path, { resolve } from "path"; -import glob from 'glob' +import glob from 'glob-all' /** * diff --git a/packages/generators/utils/add/questions/index.ts b/packages/generators/utils/add/questions/index.ts index 93be7644639..1d632b41c18 100644 --- a/packages/generators/utils/add/questions/index.ts +++ b/packages/generators/utils/add/questions/index.ts @@ -1,7 +1,6 @@ import { AutoComplete, Confirm, - InquirerInput, Input, InputValidate, } from "@webpack-cli/webpack-scaffold"; From cb5a15f04732a358afd1b705199a07492125b59d Mon Sep 17 00:00:00 2001 From: Rishabh Date: Tue, 28 May 2019 16:38:52 +0530 Subject: [PATCH 11/34] chore: lint --- packages/generators/add-generator.ts | 1 + packages/generators/utils/add/index.ts | 6 ++++-- packages/generators/utils/add/questions/index.ts | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 82755ba9d28..eb3822edd1e 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -117,6 +117,7 @@ export default class AddGenerator extends Generator { mergeFile: string; }) => { const resolvedPath = resolve(process.cwd(), mergeFileAnswer.mergeFile); + // eslint-disable-next-line const mergeConfig = require(resolvedPath); (this.configuration.config.merge as { configName?: string; diff --git a/packages/generators/utils/add/index.ts b/packages/generators/utils/add/index.ts index 9b6e9eaac22..f9743d9ecd6 100644 --- a/packages/generators/utils/add/index.ts +++ b/packages/generators/utils/add/index.ts @@ -3,7 +3,9 @@ import PROP_TYPES from "@webpack-cli/utils/prop-types"; export const PROPS: string[] = Array.from(PROP_TYPES.keys()); // tslint:disable:no-var-requires +// eslint-disable-next-line export const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); +// eslint-disable-next-line export const webpackSchema = require("../optionsSchema.json"); /** @@ -11,7 +13,7 @@ export const webpackSchema = require("../optionsSchema.json"); * Replaces the string with a substring at the given index * https://gist.github.com/efenacigiray/9367920 * - * @param {String} string - string to be modified + * @param {String} str - string to be modified * @param {Number} index - index to replace from * @param {String} replace - string to replace starting from index * @@ -33,7 +35,7 @@ export function replaceAt(str: string, index: number, replace: string): string { * is present */ export const traverseAndGetProperties = (arr: object[], prop: string): boolean => { - let hasProp: boolean = false; + let hasProp = false; arr.forEach((p: object): void => { if (p[prop]) { hasProp = true; diff --git a/packages/generators/utils/add/questions/index.ts b/packages/generators/utils/add/questions/index.ts index 1d632b41c18..81b0cfd23c3 100644 --- a/packages/generators/utils/add/questions/index.ts +++ b/packages/generators/utils/add/questions/index.ts @@ -13,7 +13,8 @@ import { Question } from "inquirer"; /** * Returns Inquirer question for given action - * @param action string + * @param {string} action + * @returns {Question} */ export const manualOrListInput: (action: string) => Question = (action: string) => { const actionQuestion = `What do you want to add to ${action}?`; From e023d230c3d9ae6f489717d5165b6e22f6995a64 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Tue, 28 May 2019 16:45:23 +0530 Subject: [PATCH 12/34] chore: add JSDoc descriptions --- packages/generators/utils/add/questions/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/generators/utils/add/questions/index.ts b/packages/generators/utils/add/questions/index.ts index 81b0cfd23c3..1dabd0056e8 100644 --- a/packages/generators/utils/add/questions/index.ts +++ b/packages/generators/utils/add/questions/index.ts @@ -13,8 +13,8 @@ import { Question } from "inquirer"; /** * Returns Inquirer question for given action - * @param {string} action - * @returns {Question} + * @param {string} action action for which question has to be prompted + * @returns {Question} Question for given action */ export const manualOrListInput: (action: string) => Question = (action: string) => { const actionQuestion = `What do you want to add to ${action}?`; From 248b9cc8fecf389bdf841dbf09aea3ba8e29c7ed Mon Sep 17 00:00:00 2001 From: Rishabh Date: Wed, 29 May 2019 16:55:36 +0530 Subject: [PATCH 13/34] feat: add mergeHandler --- .../generators/utils/add/questions/index.ts | 14 +++++--- packages/utils/scaffold.ts | 32 ++++++++++++++++--- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/packages/generators/utils/add/questions/index.ts b/packages/generators/utils/add/questions/index.ts index 1dabd0056e8..d4e5cc5d1c1 100644 --- a/packages/generators/utils/add/questions/index.ts +++ b/packages/generators/utils/add/questions/index.ts @@ -42,9 +42,9 @@ export const topScopeQuestion = Input( "What do you want to add to topScope?", ); -const mergeFileQuestionFunction = () => { - const question = "What is the location of webpack configuration with which you want to merge current configuration?"; - const validator = (path: string) => { +const mergeFileQuestionsFunction = () => { + const mergePathQuestion = "What is the location of webpack configuration with which you want to merge current configuration?"; + const mergePathValidator = (path: string) => { const resolvedPath = resolve(process.cwd(), path); if (existsSync(resolvedPath)) { if (/\.js$/.test(path)) { @@ -57,6 +57,10 @@ const mergeFileQuestionFunction = () => { } return "Invalid path provided"; }; - return InputValidate("mergeFile", question, validator); + const mergeConfigNameQuestion = "What is the name by which you want to denote above configuration?"; + return [ + InputValidate("mergeFile", mergeFileQuestion, mergePathValidator), + Input("mergeConfigName", mergeConfigNameQuestion) +] }; -export const mergeFileQuestion = mergeFileQuestionFunction(); +export const mergeFileQuestion = mergeFileQuestionsFunction(); diff --git a/packages/utils/scaffold.ts b/packages/utils/scaffold.ts index c5347482c42..86300589320 100644 --- a/packages/utils/scaffold.ts +++ b/packages/utils/scaffold.ts @@ -11,6 +11,28 @@ import astTransform from "./recursive-parser"; import runPrettier from "./run-prettier"; import { Node } from "./types/NodePath"; + + +function mergeHandler(config: Config, transformations: string[]): [Config, string[]]{ + if(transformations.indexOf("topScope") === -1) + { + config["topScope"] = [ + `const merge = require('webpack-merge')`, + `const ${config.merge[0]} = require(${config.merge[1]})` + ]; + } else { + config.topScope.push( + `const merge = require('webpack-merge')`, + `const ${config.merge[0]} = require(${config.merge[1]})` + ) + } + + config.merge = config.merge[0]; + transformations.push("merge", "topScope"); + return [config, transformations] +} + + /** * * Maps back transforms that needs to be run using the configuration @@ -45,17 +67,17 @@ export default function runTransform(transformConfig: TransformConfig, action: s webpackConfig.forEach( (scaffoldPiece: string): Promise => { - const config: Config = transformConfig[scaffoldPiece]; + let config: Config = transformConfig[scaffoldPiece]; - const transformations = mapOptionsToTransform(config); + let transformations = mapOptionsToTransform(config); if (config.topScope && transformations.indexOf("topScope") === -1) { transformations.push("topScope"); } - if (config.merge && transformations.indexOf("merge") === -1) { - transformations.push("merge"); - } + if (config.merge && transformations.indexOf("merge") === -1) { + [config, transformations] = mergeHandler(config, transformations); + } const ast: Node = j(initActionNotDefined ? transformConfig.configFile : "module.exports = {}"); From 1323bbf0353e43a84e19d276e34f657abb260538 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Wed, 29 May 2019 16:56:48 +0530 Subject: [PATCH 14/34] chore: update variable name --- packages/generators/utils/add/questions/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/generators/utils/add/questions/index.ts b/packages/generators/utils/add/questions/index.ts index d4e5cc5d1c1..90981a70007 100644 --- a/packages/generators/utils/add/questions/index.ts +++ b/packages/generators/utils/add/questions/index.ts @@ -59,7 +59,7 @@ const mergeFileQuestionsFunction = () => { }; const mergeConfigNameQuestion = "What is the name by which you want to denote above configuration?"; return [ - InputValidate("mergeFile", mergeFileQuestion, mergePathValidator), + InputValidate("mergeFile", mergePathQuestion, mergePathValidator), Input("mergeConfigName", mergeConfigNameQuestion) ] }; From a2c49e2b4505b24d0a707f11352ac1509c73a314 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Wed, 29 May 2019 17:04:16 +0530 Subject: [PATCH 15/34] chore: update types of the config --- packages/generators/add-generator.ts | 20 +++++--------------- packages/utils/modify-config-helper.ts | 2 +- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index eb3822edd1e..dfbb660173c 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -42,12 +42,7 @@ export default class AddGenerator extends Generator { configName?: string; topScope?: string[]; item?: string; - merge?: { - configName?: string; - topScope?: string[]; - item?: string; - webpackOptions?: WebpackOptions; - }; + merge?: string|string[]; webpackOptions?: WebpackOptions; }; }; @@ -112,19 +107,14 @@ export default class AddGenerator extends Generator { ); } if (action === "merge") { - return this.prompt([mergeFileQuestion]) + return this.prompt(mergeFileQuestion) .then((mergeFileAnswer: { - mergeFile: string; + mergeFile: string, + mergeConfigName: string }) => { const resolvedPath = resolve(process.cwd(), mergeFileAnswer.mergeFile); // eslint-disable-next-line - const mergeConfig = require(resolvedPath); - (this.configuration.config.merge as { - configName?: string; - topScope?: string[]; - item?: string; - webpackOptions?: WebpackOptions; - }) = mergeConfig; + this.configuration.config["merge"] = [mergeFileAnswer.mergeConfigName, resolvedPath]; }); } } diff --git a/packages/utils/modify-config-helper.ts b/packages/utils/modify-config-helper.ts index 5d25385c8c0..b1e40368cc4 100644 --- a/packages/utils/modify-config-helper.ts +++ b/packages/utils/modify-config-helper.ts @@ -14,7 +14,7 @@ export interface Config extends Object { }; topScope?: string[]; configName?: string; - merge: object; + merge: string|string[]; webpackOptions: object; } From 88eec7c7ac43980946f7873cd5a80472369c8a39 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Wed, 29 May 2019 17:06:56 +0530 Subject: [PATCH 16/34] chore: made condition strict --- packages/utils/scaffold.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/utils/scaffold.ts b/packages/utils/scaffold.ts index 86300589320..64b4e1e07d6 100644 --- a/packages/utils/scaffold.ts +++ b/packages/utils/scaffold.ts @@ -14,12 +14,13 @@ import { Node } from "./types/NodePath"; function mergeHandler(config: Config, transformations: string[]): [Config, string[]]{ - if(transformations.indexOf("topScope") === -1) + if(!config["topScope"]) { config["topScope"] = [ `const merge = require('webpack-merge')`, `const ${config.merge[0]} = require(${config.merge[1]})` ]; + transformations.push("topScope"); } else { config.topScope.push( `const merge = require('webpack-merge')`, @@ -29,7 +30,7 @@ function mergeHandler(config: Config, transformations: string[]): [Config, strin config.merge = config.merge[0]; transformations.push("merge", "topScope"); - return [config, transformations] + return [config, transformations]; } From cf8553591aa134f8f6c027775e723c99cb50ab4d Mon Sep 17 00:00:00 2001 From: Rishabh Date: Thu, 30 May 2019 15:26:08 +0530 Subject: [PATCH 17/34] chore: update parseMerge --- packages/generators/add-generator.ts | 1 + .../generators/utils/add/questions/index.ts | 9 ++---- packages/utils/ast-utils.ts | 4 +-- packages/utils/recursive-parser.ts | 2 +- packages/utils/scaffold.ts | 31 +++++-------------- packages/utils/types/NodePath.ts | 2 +- 6 files changed, 16 insertions(+), 33 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index dfbb660173c..e4149ed6226 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -115,6 +115,7 @@ export default class AddGenerator extends Generator { const resolvedPath = resolve(process.cwd(), mergeFileAnswer.mergeFile); // eslint-disable-next-line this.configuration.config["merge"] = [mergeFileAnswer.mergeConfigName, resolvedPath]; + done(); }); } } diff --git a/packages/generators/utils/add/questions/index.ts b/packages/generators/utils/add/questions/index.ts index 90981a70007..6b08b8709bf 100644 --- a/packages/generators/utils/add/questions/index.ts +++ b/packages/generators/utils/add/questions/index.ts @@ -31,13 +31,13 @@ export const actionTypeQuestion = AutoComplete( }, ); -export const entryTypeQuestion = Confirm( +export const entryTypeQuestion: Question = Confirm( "entryType", "Will your application have multiple bundles?", false, ); -export const topScopeQuestion = Input( +export const topScopeQuestion: Question = Input( "topScope", "What do you want to add to topScope?", ); @@ -48,9 +48,6 @@ const mergeFileQuestionsFunction = () => { const resolvedPath = resolve(process.cwd(), path); if (existsSync(resolvedPath)) { if (/\.js$/.test(path)) { - if (typeof require(resolvedPath) !== "object") { - return "Given file doesn't export an Object"; - } return true; } return "Path doesn't corresponds to a javascript file"; @@ -63,4 +60,4 @@ const mergeFileQuestionsFunction = () => { Input("mergeConfigName", mergeConfigNameQuestion) ] }; -export const mergeFileQuestion = mergeFileQuestionsFunction(); +export const mergeFileQuestion: Question[] = mergeFileQuestionsFunction(); diff --git a/packages/utils/ast-utils.ts b/packages/utils/ast-utils.ts index 7a6fed5a657..ed0745ef53b 100644 --- a/packages/utils/ast-utils.ts +++ b/packages/utils/ast-utils.ts @@ -605,7 +605,7 @@ function parseTopScope(j: JSCodeshift, ast: Node, value: string[], action: strin */ // eslint-disable-next-line @typescript-eslint/no-unused-vars -function parseMerge(j: JSCodeshift, ast: Node, value: string, action: string): boolean | Node { +function parseMerge(j: JSCodeshift, ast: Node, value: string[], action: string): boolean | Node { function createMergeProperty(p: Node): boolean { // FIXME Use j.callExp() const exportsDecl: Node[] = (p.value as Node).body.map( @@ -626,7 +626,7 @@ function parseMerge(j: JSCodeshift, ast: Node, value: string, action: string): b type: "MemberExpression" }, operator: "=", - right: j.callExpression(j.identifier("merge"), [j.identifier(value), exportsDecl.pop()]), + right: j.callExpression(j.identifier("merge"), [j.identifier(value[0]), exportsDecl.pop()]), type: "AssignmentExpression" }; (p.value as Node).body[bodyLength - 1] = newVal; diff --git a/packages/utils/recursive-parser.ts b/packages/utils/recursive-parser.ts index a6312798f5b..a592581f651 100644 --- a/packages/utils/recursive-parser.ts +++ b/packages/utils/recursive-parser.ts @@ -15,7 +15,7 @@ export default function recursiveTransform( console.error("Error in parsing top scope, Array required"); return false; } else if (key === "merge") { - if (typeof value === "string") { + if (typeof value[0] === "string" && Array.isArray(value)) { return utils.parseMerge(j, ast, value, action); } } diff --git a/packages/utils/scaffold.ts b/packages/utils/scaffold.ts index 64b4e1e07d6..dce90abb648 100644 --- a/packages/utils/scaffold.ts +++ b/packages/utils/scaffold.ts @@ -12,28 +12,6 @@ import runPrettier from "./run-prettier"; import { Node } from "./types/NodePath"; - -function mergeHandler(config: Config, transformations: string[]): [Config, string[]]{ - if(!config["topScope"]) - { - config["topScope"] = [ - `const merge = require('webpack-merge')`, - `const ${config.merge[0]} = require(${config.merge[1]})` - ]; - transformations.push("topScope"); - } else { - config.topScope.push( - `const merge = require('webpack-merge')`, - `const ${config.merge[0]} = require(${config.merge[1]})` - ) - } - - config.merge = config.merge[0]; - transformations.push("merge", "topScope"); - return [config, transformations]; -} - - /** * * Maps back transforms that needs to be run using the configuration @@ -77,7 +55,14 @@ export default function runTransform(transformConfig: TransformConfig, action: s } if (config.merge && transformations.indexOf("merge") === -1) { - [config, transformations] = mergeHandler(config, transformations); + transformations.push("merge"); + } + + if (config.merge) { + config.topScope.push( + `const merge = require('webpack-merge')`, + `const ${config.merge[0]} = require('${config.merge[1]}')` + ) } const ast: Node = j(initActionNotDefined ? transformConfig.configFile : "module.exports = {}"); diff --git a/packages/utils/types/NodePath.ts b/packages/utils/types/NodePath.ts index 1b828378ddb..61d7e539847 100644 --- a/packages/utils/types/NodePath.ts +++ b/packages/utils/types/NodePath.ts @@ -96,4 +96,4 @@ export interface JSCodeshift extends Object { }; } -export type valueType = string | number | boolean | Node | null; +export type valueType = string[] | string | number | boolean | Node | null; From 445ab311720feac0c35bf26d954358f41e4a6828 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Thu, 30 May 2019 15:30:11 +0530 Subject: [PATCH 18/34] chore: make config const --- packages/utils/scaffold.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/utils/scaffold.ts b/packages/utils/scaffold.ts index dce90abb648..688e3978de6 100644 --- a/packages/utils/scaffold.ts +++ b/packages/utils/scaffold.ts @@ -46,9 +46,9 @@ export default function runTransform(transformConfig: TransformConfig, action: s webpackConfig.forEach( (scaffoldPiece: string): Promise => { - let config: Config = transformConfig[scaffoldPiece]; + const config: Config = transformConfig[scaffoldPiece]; - let transformations = mapOptionsToTransform(config); + const transformations = mapOptionsToTransform(config); if (config.topScope && transformations.indexOf("topScope") === -1) { transformations.push("topScope"); From b6a438d6925ba9ca1fa866f412ed074b509f3d70 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Fri, 31 May 2019 12:34:15 +0530 Subject: [PATCH 19/34] chore: update parseMerge --- packages/utils/ast-utils.ts | 27 ++++++++++++++++++++++++--- packages/utils/recursive-parser.ts | 2 +- packages/utils/scaffold.ts | 7 ------- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/packages/utils/ast-utils.ts b/packages/utils/ast-utils.ts index ed0745ef53b..f52645dd87a 100644 --- a/packages/utils/ast-utils.ts +++ b/packages/utils/ast-utils.ts @@ -606,7 +606,7 @@ function parseTopScope(j: JSCodeshift, ast: Node, value: string[], action: strin // eslint-disable-next-line @typescript-eslint/no-unused-vars function parseMerge(j: JSCodeshift, ast: Node, value: string[], action: string): boolean | Node { - function createMergeProperty(p: Node): boolean { + function createMergeProperty(p: Node, configIdentifier: string): boolean { // FIXME Use j.callExp() const exportsDecl: Node[] = (p.value as Node).body.map( (n: Node): Node => { @@ -626,14 +626,35 @@ function parseMerge(j: JSCodeshift, ast: Node, value: string[], action: string): type: "MemberExpression" }, operator: "=", - right: j.callExpression(j.identifier("merge"), [j.identifier(value[0]), exportsDecl.pop()]), + right: j.callExpression(j.identifier("merge"), [j.identifier(configIdentifier), exportsDecl.pop()]), type: "AssignmentExpression" }; (p.value as Node).body[bodyLength - 1] = newVal; return false; // TODO: debug later } + + function addMergeImports(ast: Node, mergeImports: string[]) { + ast.find(j.Program).filter((program: Node): boolean => { + mergeImports.forEach( + (imp: string): void => { + if ((program.value as Node).body.indexOf(imp) === -1){ + (program.value as Node).body.splice(-1, 0, imp); + } + } + ) + return false; + }); + return ast; + } + if (value) { - return ast.find(j.Program).filter((p: Node): boolean => createMergeProperty(p)); + const [configIdentifier, configPath] = value; + const mergeImports = [ + `const ${configIdentifier} = require('${configPath}')`, + `const merge = require('webpack-merge')` + ]; + ast = addMergeImports(ast, mergeImports); + return ast.find(j.Program).filter((p: Node): boolean => createMergeProperty(p, configIdentifier)); } else { return ast; } diff --git a/packages/utils/recursive-parser.ts b/packages/utils/recursive-parser.ts index a592581f651..275c30651af 100644 --- a/packages/utils/recursive-parser.ts +++ b/packages/utils/recursive-parser.ts @@ -15,7 +15,7 @@ export default function recursiveTransform( console.error("Error in parsing top scope, Array required"); return false; } else if (key === "merge") { - if (typeof value[0] === "string" && Array.isArray(value)) { + if (Array.isArray(value) && typeof value[0] === "string" && typeof value[1] === "string") { return utils.parseMerge(j, ast, value, action); } } diff --git a/packages/utils/scaffold.ts b/packages/utils/scaffold.ts index 688e3978de6..855bf2c6ff7 100644 --- a/packages/utils/scaffold.ts +++ b/packages/utils/scaffold.ts @@ -58,13 +58,6 @@ export default function runTransform(transformConfig: TransformConfig, action: s transformations.push("merge"); } - if (config.merge) { - config.topScope.push( - `const merge = require('webpack-merge')`, - `const ${config.merge[0]} = require('${config.merge[1]}')` - ) - } - const ast: Node = j(initActionNotDefined ? transformConfig.configFile : "module.exports = {}"); const transformAction: string = action || null; From 55d237beea651b9b4bfc979850d8b2d064d795df Mon Sep 17 00:00:00 2001 From: Rishabh Date: Fri, 31 May 2019 13:06:06 +0530 Subject: [PATCH 20/34] chore: update prop name --- packages/generators/add-generator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 8488b01c1ab..014ac28f798 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -115,7 +115,7 @@ export default class AddGenerator extends Generator { }) => { const resolvedPath = resolve(process.cwd(), mergeFileAnswer.mergeFile); // eslint-disable-next-line - this.configuration.config["merge"] = [mergeFileAnswer.mergeConfigName, resolvedPath]; + this.configuration.config[action] = [mergeFileAnswer.mergeConfigName, resolvedPath]; done(); }); } From 6a7e662639a8d63e62f3de6944a480ae24480fbf Mon Sep 17 00:00:00 2001 From: Rishabh Date: Fri, 31 May 2019 14:17:03 +0530 Subject: [PATCH 21/34] chore: use replaceWith --- packages/utils/ast-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/ast-utils.ts b/packages/utils/ast-utils.ts index fc13060d338..d61604be15b 100644 --- a/packages/utils/ast-utils.ts +++ b/packages/utils/ast-utils.ts @@ -653,7 +653,7 @@ function parseMerge(j: JSCodeshift, ast: Node, value: string[], action: string): `const ${configIdentifier} = require('${configPath}')`, `const merge = require('webpack-merge')` ]; - ast = addMergeImports(ast, mergeImports); + ast.replaceWith(addMergeImports(ast, mergeImports)); return ast.find(j.Program).filter((p: Node): boolean => createMergeProperty(p, configIdentifier)); } else { return ast; From a89645ae72075640eb8b8820466df54070f7646f Mon Sep 17 00:00:00 2001 From: Rishabh Date: Fri, 31 May 2019 17:24:42 +0530 Subject: [PATCH 22/34] chore: create isImportPresent --- packages/utils/ast-utils.ts | 37 +++++++++++++++++--------------- packages/utils/types/NodePath.ts | 1 + 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/packages/utils/ast-utils.ts b/packages/utils/ast-utils.ts index d61604be15b..3f0f3a46480 100644 --- a/packages/utils/ast-utils.ts +++ b/packages/utils/ast-utils.ts @@ -1,6 +1,17 @@ import { JSCodeshift, Node, valueType } from "./types/NodePath"; import * as validateIdentifier from "./validate-identifier"; + +function isImportPresent (j: JSCodeshift, ast: Node, path: string): boolean { + let isPresent: boolean = false; + ast.find(j.CallExpression).forEach(callExp => { + if ((callExp.value as Node).callee.name === 'require' && (callExp.value as Node).arguments[0].value === path) { + isPresent = true; + } + }) + return isPresent; +} + /** * * Traverse safely over a path object for array for paths @@ -629,31 +640,23 @@ function parseMerge(j: JSCodeshift, ast: Node, value: string[], action: string): right: j.callExpression(j.identifier("merge"), [j.identifier(configIdentifier), exportsDecl.pop()]), type: "AssignmentExpression" }; + (p.value as Node).body[bodyLength - 1] = newVal; return false; // TODO: debug later } - function addMergeImports(ast: Node, mergeImports: string[]) { - ast.find(j.Program).filter((program: Node): boolean => { - mergeImports.forEach( - (imp: string): void => { - if ((program.value as Node).body.indexOf(imp) === -1){ - (program.value as Node).body.splice(-1, 0, imp); - } - } - ) - return false; - }); - return ast; + function addMergeImports(configIdentifier: string, configPath: string) { + ast.find(j.Program).forEach(p => { + if (!isImportPresent(j, ast, 'webpack-merge')) { + (p.value as Node).body.splice(-1, 0, `const merge = require('webpack-merge')`); + } + (p.value as Node).body.splice(-1, 0, `const ${configIdentifier} = require('${configPath}')`); + }) } if (value) { const [configIdentifier, configPath] = value; - const mergeImports = [ - `const ${configIdentifier} = require('${configPath}')`, - `const merge = require('webpack-merge')` - ]; - ast.replaceWith(addMergeImports(ast, mergeImports)); + addMergeImports(configIdentifier, configPath); return ast.find(j.Program).filter((p: Node): boolean => createMergeProperty(p, configIdentifier)); } else { return ast; diff --git a/packages/utils/types/NodePath.ts b/packages/utils/types/NodePath.ts index db1853deff7..0e09ab51672 100644 --- a/packages/utils/types/NodePath.ts +++ b/packages/utils/types/NodePath.ts @@ -2,6 +2,7 @@ export interface Node extends Object { id?: { name: string; }; + callee?: Node; arguments?: Node[]; body?: Node[]; elements?: Node[]; From 5e23da24698f97f384de3cb418777b5f5b431aad Mon Sep 17 00:00:00 2001 From: Rishabh Date: Fri, 31 May 2019 17:32:40 +0530 Subject: [PATCH 23/34] chore: remove trivial type --- packages/utils/ast-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/ast-utils.ts b/packages/utils/ast-utils.ts index 3f0f3a46480..67bc6b55b23 100644 --- a/packages/utils/ast-utils.ts +++ b/packages/utils/ast-utils.ts @@ -3,7 +3,7 @@ import * as validateIdentifier from "./validate-identifier"; function isImportPresent (j: JSCodeshift, ast: Node, path: string): boolean { - let isPresent: boolean = false; + let isPresent = false; ast.find(j.CallExpression).forEach(callExp => { if ((callExp.value as Node).callee.name === 'require' && (callExp.value as Node).arguments[0].value === path) { isPresent = true; From 27c6198b6b73d630a18997200353adabc9c4e2bb Mon Sep 17 00:00:00 2001 From: Rishabh Date: Tue, 4 Jun 2019 17:11:35 +0530 Subject: [PATCH 24/34] chore: add errors for invalid params --- packages/utils/ast-utils.ts | 11 ++++++++++- packages/utils/recursive-parser.ts | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/utils/ast-utils.ts b/packages/utils/ast-utils.ts index 67bc6b55b23..83b39f11f72 100644 --- a/packages/utils/ast-utils.ts +++ b/packages/utils/ast-utils.ts @@ -3,6 +3,9 @@ import * as validateIdentifier from "./validate-identifier"; function isImportPresent (j: JSCodeshift, ast: Node, path: string): boolean { + if (typeof path !== "string") { + throw new Error(`path parameter should be string, recieved ${typeof path}`); + } let isPresent = false; ast.find(j.CallExpression).forEach(callExp => { if ((callExp.value as Node).callee.name === 'require' && (callExp.value as Node).arguments[0].value === path) { @@ -646,11 +649,17 @@ function parseMerge(j: JSCodeshift, ast: Node, value: string[], action: string): } function addMergeImports(configIdentifier: string, configPath: string) { + if (typeof configIdentifier !== "string" || typeof configPath !== "string") { + throw new Error(`Both parameters should be string. Recieved ${configIdentifier}, ${configPath}`) + } ast.find(j.Program).forEach(p => { if (!isImportPresent(j, ast, 'webpack-merge')) { (p.value as Node).body.splice(-1, 0, `const merge = require('webpack-merge')`); } - (p.value as Node).body.splice(-1, 0, `const ${configIdentifier} = require('${configPath}')`); + + if (!isImportPresent(j, ast, configPath)) { + (p.value as Node).body.splice(-1, 0, `const ${configIdentifier} = require('${configPath}')`); + } }) } diff --git a/packages/utils/recursive-parser.ts b/packages/utils/recursive-parser.ts index 275c30651af..217d2289a9c 100644 --- a/packages/utils/recursive-parser.ts +++ b/packages/utils/recursive-parser.ts @@ -15,7 +15,7 @@ export default function recursiveTransform( console.error("Error in parsing top scope, Array required"); return false; } else if (key === "merge") { - if (Array.isArray(value) && typeof value[0] === "string" && typeof value[1] === "string") { + if (Array.isArray(value)) { return utils.parseMerge(j, ast, value, action); } } From 8b88980b5eeb31dc1fe2d892ba81ab27926d1440 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Tue, 4 Jun 2019 20:28:29 +0530 Subject: [PATCH 25/34] chore: add types to import functions --- packages/generators/add-generator.ts | 3 +-- packages/generators/utils/add/questions/index.ts | 6 +++--- packages/utils/ast-utils.ts | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 014ac28f798..985f7823547 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -9,7 +9,6 @@ import { } from "./utils/add/questions"; import { - replaceAt, traverseAndGetProperties, webpackDevServerSchema, webpackSchema @@ -112,7 +111,7 @@ export default class AddGenerator extends Generator { .then((mergeFileAnswer: { mergeFile: string, mergeConfigName: string - }) => { + }):void => { const resolvedPath = resolve(process.cwd(), mergeFileAnswer.mergeFile); // eslint-disable-next-line this.configuration.config[action] = [mergeFileAnswer.mergeConfigName, resolvedPath]; diff --git a/packages/generators/utils/add/questions/index.ts b/packages/generators/utils/add/questions/index.ts index 6b08b8709bf..fbbc0dfe138 100644 --- a/packages/generators/utils/add/questions/index.ts +++ b/packages/generators/utils/add/questions/index.ts @@ -16,7 +16,7 @@ import { Question } from "inquirer"; * @param {string} action action for which question has to be prompted * @returns {Question} Question for given action */ -export const manualOrListInput: (action: string) => Question = (action: string) => { +export const manualOrListInput = (action: string): Question => { const actionQuestion = `What do you want to add to ${action}?`; return Input("actionAnswer", actionQuestion); }; @@ -42,9 +42,9 @@ export const topScopeQuestion: Question = Input( "What do you want to add to topScope?", ); -const mergeFileQuestionsFunction = () => { +const mergeFileQuestionsFunction = (): Question[] => { const mergePathQuestion = "What is the location of webpack configuration with which you want to merge current configuration?"; - const mergePathValidator = (path: string) => { + const mergePathValidator = (path: string): boolean|string => { const resolvedPath = resolve(process.cwd(), path); if (existsSync(resolvedPath)) { if (/\.js$/.test(path)) { diff --git a/packages/utils/ast-utils.ts b/packages/utils/ast-utils.ts index 83b39f11f72..c1dc17a15f7 100644 --- a/packages/utils/ast-utils.ts +++ b/packages/utils/ast-utils.ts @@ -7,7 +7,7 @@ function isImportPresent (j: JSCodeshift, ast: Node, path: string): boolean { throw new Error(`path parameter should be string, recieved ${typeof path}`); } let isPresent = false; - ast.find(j.CallExpression).forEach(callExp => { + ast.find(j.CallExpression).forEach((callExp: Node): void => { if ((callExp.value as Node).callee.name === 'require' && (callExp.value as Node).arguments[0].value === path) { isPresent = true; } @@ -648,11 +648,11 @@ function parseMerge(j: JSCodeshift, ast: Node, value: string[], action: string): return false; // TODO: debug later } - function addMergeImports(configIdentifier: string, configPath: string) { + function addMergeImports(configIdentifier: string, configPath: string): void { if (typeof configIdentifier !== "string" || typeof configPath !== "string") { - throw new Error(`Both parameters should be string. Recieved ${configIdentifier}, ${configPath}`) + throw new Error(`Both parameters should be string. recieved ${typeof configIdentifier}, ${typeof configPath}`) } - ast.find(j.Program).forEach(p => { + ast.find(j.Program).forEach((p: Node): void => { if (!isImportPresent(j, ast, 'webpack-merge')) { (p.value as Node).body.splice(-1, 0, `const merge = require('webpack-merge')`); } From 748197475d30bb3c45c37f7e542bead8f62364bb Mon Sep 17 00:00:00 2001 From: Rishabh Date: Wed, 5 Jun 2019 17:25:31 +0530 Subject: [PATCH 26/34] chore: create questions.ts --- packages/generators/add-generator.ts | 22 +++---- packages/generators/utils/add/index.ts | 22 +++---- packages/generators/utils/add/questions.ts | 46 ++++++++++++++ .../generators/utils/add/questions/index.ts | 63 ------------------- 4 files changed, 64 insertions(+), 89 deletions(-) create mode 100644 packages/generators/utils/add/questions.ts delete mode 100644 packages/generators/utils/add/questions/index.ts diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index cf366ed27db..78a26567e9b 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -1,4 +1,12 @@ import * as Generator from "yeoman-generator"; +import npmExists from "@webpack-cli/utils/npm-exists"; +import { getPackageManager } from "@webpack-cli/utils/package-manager"; +import { Input, List } from "@webpack-cli/webpack-scaffold"; +// eslint-disable-next-line +export const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); +import * as AutoComplete from "inquirer-autocomplete-prompt"; +import path, { resolve } from "path"; +import glob from "glob-all"; import { actionTypeQuestion, @@ -7,19 +15,12 @@ import { mergeFileQuestion, topScopeQuestion } from "./utils/add/questions"; - -import { traverseAndGetProperties, webpackDevServerSchema, webpackSchema } from "./utils/add"; - -import npmExists from "@webpack-cli/utils/npm-exists"; -import { getPackageManager } from "@webpack-cli/utils/package-manager"; -import { Input, List } from "@webpack-cli/webpack-scaffold"; - +import { traverseAndGetProperties } from "./utils/add"; import { SchemaProperties, WebpackOptions } from "./types"; import entryQuestions from "./utils/entry"; -import * as AutoComplete from "inquirer-autocomplete-prompt"; -import path, { resolve } from "path"; -import glob from "glob-all"; import { generatePluginName } from "./utils/plugins"; +// eslint-disable-next-line +export const webpackSchema = require("../optionsSchema.json"); /** * @@ -105,7 +106,6 @@ export default class AddGenerator extends Generator { return this.prompt(mergeFileQuestion).then( (mergeFileAnswer: { mergeFile: string; mergeConfigName: string }): void => { const resolvedPath = resolve(process.cwd(), mergeFileAnswer.mergeFile); - // eslint-disable-next-line this.configuration.config[action] = [mergeFileAnswer.mergeConfigName, resolvedPath]; done(); } diff --git a/packages/generators/utils/add/index.ts b/packages/generators/utils/add/index.ts index f9743d9ecd6..494271a20e7 100644 --- a/packages/generators/utils/add/index.ts +++ b/packages/generators/utils/add/index.ts @@ -2,12 +2,6 @@ import PROP_TYPES from "@webpack-cli/utils/prop-types"; export const PROPS: string[] = Array.from(PROP_TYPES.keys()); -// tslint:disable:no-var-requires -// eslint-disable-next-line -export const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); -// eslint-disable-next-line -export const webpackSchema = require("../optionsSchema.json"); - /** * * Replaces the string with a substring at the given index @@ -36,11 +30,13 @@ export function replaceAt(str: string, index: number, replace: string): string { */ export const traverseAndGetProperties = (arr: object[], prop: string): boolean => { let hasProp = false; - arr.forEach((p: object): void => { - if (p[prop]) { - hasProp = true; + arr.forEach( + (p: object): void => { + if (p[prop]) { + hasProp = true; + } } - }); + ); return hasProp; }; @@ -56,9 +52,5 @@ export const traverseAndGetProperties = (arr: object[], prop: string): boolean = */ export const searchProps = (answers: object, input: string): Promise => { input = input || ""; - return Promise.resolve( - PROPS.filter((prop: string): boolean => - prop.toLowerCase().includes(input.toLowerCase()), - ), - ); + return Promise.resolve(PROPS.filter((prop: string): boolean => prop.toLowerCase().includes(input.toLowerCase()))); }; diff --git a/packages/generators/utils/add/questions.ts b/packages/generators/utils/add/questions.ts new file mode 100644 index 00000000000..4fbb5be2c8f --- /dev/null +++ b/packages/generators/utils/add/questions.ts @@ -0,0 +1,46 @@ +import { AutoComplete, Confirm, Input, InputValidate } from "@webpack-cli/webpack-scaffold"; +import { existsSync } from "fs"; +import { resolve } from "path"; +import { searchProps } from "./index"; +import { Question } from "inquirer"; + +/** + * Returns Inquirer question for given action + * @param {string} action action for which question has to be prompted + * @returns {Question} Question for given action + */ +export const manualOrListInput = (action: string): Question => { + const actionQuestion = `What do you want to add to ${action}?`; + return Input("actionAnswer", actionQuestion); +}; + +export const actionTypeQuestion = AutoComplete("actionType", "What property do you want to add to?", { + pageSize: 7, + source: searchProps, + suggestOnly: false +}); + +export const entryTypeQuestion: Question = Confirm("entryType", "Will your application have multiple bundles?", false); + +export const topScopeQuestion: Question = Input("topScope", "What do you want to add to topScope?"); + +const mergeFileQuestionsFunction = (): Question[] => { + const mergePathQuestion = + "What is the location of webpack configuration with which you want to merge current configuration?"; + const mergePathValidator = (path: string): boolean | string => { + const resolvedPath = resolve(process.cwd(), path); + if (existsSync(resolvedPath)) { + if (/\.js$/.test(path)) { + return true; + } + return "Path doesn't corresponds to a javascript file"; + } + return "Invalid path provided"; + }; + const mergeConfigNameQuestion = "What is the name by which you want to denote above configuration?"; + return [ + InputValidate("mergeFile", mergePathQuestion, mergePathValidator), + Input("mergeConfigName", mergeConfigNameQuestion) + ]; +}; +export const mergeFileQuestion: Question[] = mergeFileQuestionsFunction(); diff --git a/packages/generators/utils/add/questions/index.ts b/packages/generators/utils/add/questions/index.ts deleted file mode 100644 index fbbc0dfe138..00000000000 --- a/packages/generators/utils/add/questions/index.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { - AutoComplete, - Confirm, - Input, - InputValidate, -} from "@webpack-cli/webpack-scaffold"; -import { existsSync } from "fs"; -import { resolve } from "path"; -import { - searchProps, -} from "../index"; -import { Question } from "inquirer"; - -/** - * Returns Inquirer question for given action - * @param {string} action action for which question has to be prompted - * @returns {Question} Question for given action - */ -export const manualOrListInput = (action: string): Question => { - const actionQuestion = `What do you want to add to ${action}?`; - return Input("actionAnswer", actionQuestion); -}; - -export const actionTypeQuestion = AutoComplete( - "actionType", - "What property do you want to add to?", - { - pageSize: 7, - source: searchProps, - suggestOnly: false, - }, -); - -export const entryTypeQuestion: Question = Confirm( - "entryType", - "Will your application have multiple bundles?", - false, -); - -export const topScopeQuestion: Question = Input( - "topScope", - "What do you want to add to topScope?", -); - -const mergeFileQuestionsFunction = (): Question[] => { - const mergePathQuestion = "What is the location of webpack configuration with which you want to merge current configuration?"; - const mergePathValidator = (path: string): boolean|string => { - const resolvedPath = resolve(process.cwd(), path); - if (existsSync(resolvedPath)) { - if (/\.js$/.test(path)) { - return true; - } - return "Path doesn't corresponds to a javascript file"; - } - return "Invalid path provided"; - }; - const mergeConfigNameQuestion = "What is the name by which you want to denote above configuration?"; - return [ - InputValidate("mergeFile", mergePathQuestion, mergePathValidator), - Input("mergeConfigName", mergeConfigNameQuestion) -] -}; -export const mergeFileQuestion: Question[] = mergeFileQuestionsFunction(); From 8609b2bf9aeb2a6b3d505188bda34d9bfc34525f Mon Sep 17 00:00:00 2001 From: Rishabh Date: Wed, 5 Jun 2019 17:29:30 +0530 Subject: [PATCH 27/34] chore: update error message --- packages/generators/utils/add/questions.ts | 2 +- packages/utils/ast-utils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/generators/utils/add/questions.ts b/packages/generators/utils/add/questions.ts index 4fbb5be2c8f..a24d0bfe7a3 100644 --- a/packages/generators/utils/add/questions.ts +++ b/packages/generators/utils/add/questions.ts @@ -33,7 +33,7 @@ const mergeFileQuestionsFunction = (): Question[] => { if (/\.js$/.test(path)) { return true; } - return "Path doesn't corresponds to a javascript file"; + return "Path doesn't correspond to a javascript file"; } return "Invalid path provided"; }; diff --git a/packages/utils/ast-utils.ts b/packages/utils/ast-utils.ts index 46c3a9dee6a..f04a1061ce7 100644 --- a/packages/utils/ast-utils.ts +++ b/packages/utils/ast-utils.ts @@ -655,7 +655,7 @@ function parseMerge(j: JSCodeshift, ast: Node, value: string[], action: string): function addMergeImports(configIdentifier: string, configPath: string): void { if (typeof configIdentifier !== "string" || typeof configPath !== "string") { throw new Error( - `Both parameters should be string. recieved ${typeof configIdentifier}, ${typeof configPath}` + `Both parameters should be strings. recieved ${typeof configIdentifier}, ${typeof configPath}` ); } ast.find(j.Program).forEach( From 8e3f4aef672ba8e931a1e5381e37d16743c42906 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Wed, 5 Jun 2019 17:49:24 +0530 Subject: [PATCH 28/34] chore: update variable name --- packages/utils/ast-utils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/utils/ast-utils.ts b/packages/utils/ast-utils.ts index f04a1061ce7..8624d792b06 100644 --- a/packages/utils/ast-utils.ts +++ b/packages/utils/ast-utils.ts @@ -5,18 +5,18 @@ function isImportPresent(j: JSCodeshift, ast: Node, path: string): boolean { if (typeof path !== "string") { throw new Error(`path parameter should be string, recieved ${typeof path}`); } - let isPresent = false; + let importExists = false; ast.find(j.CallExpression).forEach( (callExp: Node): void => { if ( (callExp.value as Node).callee.name === "require" && (callExp.value as Node).arguments[0].value === path ) { - isPresent = true; + importExists = true; } } ); - return isPresent; + return importExists; } /** From 5ee41692c0f14f05edecccb28bc6fc280437edf5 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Wed, 5 Jun 2019 18:13:32 +0530 Subject: [PATCH 29/34] chore: use import instead of require --- packages/generators/add-generator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 78a26567e9b..2c2be2fd0e5 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -3,7 +3,7 @@ import npmExists from "@webpack-cli/utils/npm-exists"; import { getPackageManager } from "@webpack-cli/utils/package-manager"; import { Input, List } from "@webpack-cli/webpack-scaffold"; // eslint-disable-next-line -export const webpackDevServerSchema = require("webpack-dev-server/lib/options.json"); +import webpackDevServerSchema from "webpack-dev-server/lib/options.json"; import * as AutoComplete from "inquirer-autocomplete-prompt"; import path, { resolve } from "path"; import glob from "glob-all"; @@ -20,7 +20,7 @@ import { SchemaProperties, WebpackOptions } from "./types"; import entryQuestions from "./utils/entry"; import { generatePluginName } from "./utils/plugins"; // eslint-disable-next-line -export const webpackSchema = require("../optionsSchema.json"); +import webpackSchema from "../optionsSchema.json"; /** * From d72ac08b2f96e591f77dbbf934f043d63b97e0c0 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Wed, 5 Jun 2019 18:14:59 +0530 Subject: [PATCH 30/34] chore: remove eslint disable comments --- packages/generators/add-generator.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 2c2be2fd0e5..95270dd5167 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -2,7 +2,6 @@ import * as Generator from "yeoman-generator"; import npmExists from "@webpack-cli/utils/npm-exists"; import { getPackageManager } from "@webpack-cli/utils/package-manager"; import { Input, List } from "@webpack-cli/webpack-scaffold"; -// eslint-disable-next-line import webpackDevServerSchema from "webpack-dev-server/lib/options.json"; import * as AutoComplete from "inquirer-autocomplete-prompt"; import path, { resolve } from "path"; @@ -19,7 +18,6 @@ import { traverseAndGetProperties } from "./utils/add"; import { SchemaProperties, WebpackOptions } from "./types"; import entryQuestions from "./utils/entry"; import { generatePluginName } from "./utils/plugins"; -// eslint-disable-next-line import webpackSchema from "../optionsSchema.json"; /** From 57b47c3a187c66bf5d95e5047a7e78f3480edce3 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Thu, 6 Jun 2019 14:41:56 +0530 Subject: [PATCH 31/34] chore: reorder imports --- packages/generators/add-generator.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 95270dd5167..c9fa6d49ffb 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -1,11 +1,12 @@ +import * as AutoComplete from "inquirer-autocomplete-prompt"; import * as Generator from "yeoman-generator"; +import path, { resolve } from "path"; +import glob from "glob-all"; +import webpackDevServerSchema from "webpack-dev-server/lib/options.json"; + import npmExists from "@webpack-cli/utils/npm-exists"; import { getPackageManager } from "@webpack-cli/utils/package-manager"; import { Input, List } from "@webpack-cli/webpack-scaffold"; -import webpackDevServerSchema from "webpack-dev-server/lib/options.json"; -import * as AutoComplete from "inquirer-autocomplete-prompt"; -import path, { resolve } from "path"; -import glob from "glob-all"; import { actionTypeQuestion, From 8a66c2149000372077d06ec209c56d6cf832f382 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Thu, 6 Jun 2019 14:45:39 +0530 Subject: [PATCH 32/34] chore: reorder imports --- packages/generators/utils/add/questions.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/generators/utils/add/questions.ts b/packages/generators/utils/add/questions.ts index a24d0bfe7a3..7711ceddf60 100644 --- a/packages/generators/utils/add/questions.ts +++ b/packages/generators/utils/add/questions.ts @@ -1,9 +1,11 @@ -import { AutoComplete, Confirm, Input, InputValidate } from "@webpack-cli/webpack-scaffold"; import { existsSync } from "fs"; import { resolve } from "path"; -import { searchProps } from "./index"; import { Question } from "inquirer"; +import { AutoComplete, Confirm, Input, InputValidate } from "@webpack-cli/webpack-scaffold"; + +import { searchProps } from "./index"; + /** * Returns Inquirer question for given action * @param {string} action action for which question has to be prompted From 0e0ba8a183f39fb2735fc169299564eb5ea2c915 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Thu, 6 Jun 2019 14:47:45 +0530 Subject: [PATCH 33/34] chore: reorder imports --- packages/generators/add-generator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index c9fa6d49ffb..7f286eb0b9e 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -1,7 +1,7 @@ -import * as AutoComplete from "inquirer-autocomplete-prompt"; -import * as Generator from "yeoman-generator"; import path, { resolve } from "path"; import glob from "glob-all"; +import * as AutoComplete from "inquirer-autocomplete-prompt"; +import * as Generator from "yeoman-generator"; import webpackDevServerSchema from "webpack-dev-server/lib/options.json"; import npmExists from "@webpack-cli/utils/npm-exists"; From 7fe04e940b3de94c685fd7b0c9e15ad653b9156a Mon Sep 17 00:00:00 2001 From: Rishabh Date: Thu, 6 Jun 2019 15:04:09 +0530 Subject: [PATCH 34/34] chore: group imports --- packages/generators/add-generator.ts | 2 +- packages/generators/utils/add/questions.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 7f286eb0b9e..58bc6763c81 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -2,11 +2,11 @@ import path, { resolve } from "path"; import glob from "glob-all"; import * as AutoComplete from "inquirer-autocomplete-prompt"; import * as Generator from "yeoman-generator"; -import webpackDevServerSchema from "webpack-dev-server/lib/options.json"; import npmExists from "@webpack-cli/utils/npm-exists"; import { getPackageManager } from "@webpack-cli/utils/package-manager"; import { Input, List } from "@webpack-cli/webpack-scaffold"; +import webpackDevServerSchema from "webpack-dev-server/lib/options.json"; import { actionTypeQuestion, diff --git a/packages/generators/utils/add/questions.ts b/packages/generators/utils/add/questions.ts index 7711ceddf60..7614503781a 100644 --- a/packages/generators/utils/add/questions.ts +++ b/packages/generators/utils/add/questions.ts @@ -1,7 +1,6 @@ import { existsSync } from "fs"; import { resolve } from "path"; import { Question } from "inquirer"; - import { AutoComplete, Confirm, Input, InputValidate } from "@webpack-cli/webpack-scaffold"; import { searchProps } from "./index";