diff --git a/packages/generators/add-generator.ts b/packages/generators/add-generator.ts index 0b1969247e4..58bc6763c81 100644 --- a/packages/generators/add-generator.ts +++ b/packages/generators/add-generator.ts @@ -1,57 +1,25 @@ +import path, { resolve } from "path"; +import glob from "glob-all"; +import * as AutoComplete from "inquirer-autocomplete-prompt"; import * as Generator from "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"; -import { AutoComplete, Confirm, Input, List } from "@webpack-cli/webpack-scaffold"; +import { Input, List } from "@webpack-cli/webpack-scaffold"; +import webpackDevServerSchema from "webpack-dev-server/lib/options.json"; +import { + actionTypeQuestion, + entryTypeQuestion, + manualOrListInput, + mergeFileQuestion, + topScopeQuestion +} from "./utils/add/questions"; +import { traverseAndGetProperties } from "./utils/add"; import { SchemaProperties, WebpackOptions } from "./types"; -import { entryQuestions, generatePluginName } from "./utils"; -import * as webpackDevServerSchema from "webpack-dev-server/lib/options.json"; -import * as webpackSchema from "./utils/optionsSchema.json"; - -const PROPS: string[] = Array.from(PROP_TYPES.keys()); - -/** - * - * 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 entryQuestions from "./utils/entry"; +import { generatePluginName } from "./utils/plugins"; +import webpackSchema from "../optionsSchema.json"; /** * @@ -69,6 +37,7 @@ export default class AddGenerator extends Generator { configName?: string; topScope?: string[]; item?: string; + merge?: string | string[]; webpackOptions?: WebpackOptions; }; }; @@ -83,16 +52,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 @@ -101,13 +67,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 @@ -119,9 +79,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 @@ -136,13 +94,22 @@ 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(); } ); } + if (action === "merge") { + return this.prompt(mergeFileQuestion).then( + (mergeFileAnswer: { mergeFile: string; mergeConfigName: string }): void => { + const resolvedPath = resolve(process.cwd(), mergeFileAnswer.mergeFile); + this.configuration.config[action] = [mergeFileAnswer.mergeConfigName, resolvedPath]; + done(); + } + ); + } } const temp = action; if (action === "resolveLoader") { @@ -308,7 +275,11 @@ export default class AddGenerator extends Generator { .pop() .replace(".js", "") ) - .find((p: string): boolean => p.toLowerCase().indexOf(answeredPluginName) >= 0 || p.indexOf(answeredPluginName) >= 0); + .find( + (p: string): boolean => + p.toLowerCase().indexOf(answeredPluginName) >= 0 || + p.indexOf(answeredPluginName) >= 0 + ); if (pluginExist) { this.configuration.config.item = pluginExist; @@ -416,7 +387,9 @@ 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/generators/utils/add/index.ts b/packages/generators/utils/add/index.ts new file mode 100644 index 00000000000..494271a20e7 --- /dev/null +++ b/packages/generators/utils/add/index.ts @@ -0,0 +1,56 @@ +import PROP_TYPES from "@webpack-cli/utils/prop-types"; + +export 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 + * + */ +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 = 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/generators/utils/add/questions.ts b/packages/generators/utils/add/questions.ts new file mode 100644 index 00000000000..7614503781a --- /dev/null +++ b/packages/generators/utils/add/questions.ts @@ -0,0 +1,47 @@ +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"; + +/** + * 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 correspond 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/index.ts b/packages/generators/utils/index.ts index de2b14d7f4e..cb490073cc5 100644 --- a/packages/generators/utils/index.ts +++ b/packages/generators/utils/index.ts @@ -1,10 +1,10 @@ -import entryQuestions from './entry' +import entryQuestions from "./entry"; import langQuestionHandler, { LangType, getBabelLoader, getTypescriptLoader } from "./languageSupport"; -import plugins , { replaceAt, generatePluginName } from './plugins' -import styleQuestionHandler, { StylingType, LoaderName, StyleRegex, Loader } from './styleSupport' +import plugins, { replaceAt, generatePluginName } from "./plugins"; +import styleQuestionHandler, { StylingType, LoaderName, StyleRegex, Loader } from "./styleSupport"; import tooltip from "./tooltip"; -import validate from './validate' -import { getDefaultOptimization } from './webpackConfig'; +import validate from "./validate"; +import { getDefaultOptimization } from "./webpackConfig"; export { entryQuestions, diff --git a/packages/serve/index.ts b/packages/serve/index.ts index 1896c33a734..65528039252 100644 --- a/packages/serve/index.ts +++ b/packages/serve/index.ts @@ -24,11 +24,11 @@ import { List } from "@webpack-cli/webpack-scaffold"; */ interface ConfigType { - installCmd: string, - dependency: string, - devDependency: string, - optionalDependency: string -}; + installCmd: string; + dependency: string; + devDependency: string; + optionalDependency: string; +} const npmConfig: ConfigType = { installCmd: "install", @@ -47,7 +47,7 @@ const yarnConfig: ConfigType = { const spawnWithArg = (pm: string, cmd: string): SpawnSyncReturns => { const pmConfig: ConfigType = pm === "npm" ? npmConfig : yarnConfig; const options: string[] = [pmConfig.installCmd, "webpack-dev-server", pmConfig[cmd]]; - return spawn.sync(pm, options, {stdio: "inherit"}); + return spawn.sync(pm, options, { stdio: "inherit" }); }; /** diff --git a/packages/utils/ast-utils.ts b/packages/utils/ast-utils.ts index 93177062792..8624d792b06 100644 --- a/packages/utils/ast-utils.ts +++ b/packages/utils/ast-utils.ts @@ -1,6 +1,24 @@ import { JSCodeshift, Node, valueType } from "./types/NodePath"; 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 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 + ) { + importExists = true; + } + } + ); + return importExists; +} + /** * * Traverse safely over a path object for array for paths @@ -605,8 +623,8 @@ 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 parseMerge(j: JSCodeshift, ast: Node, value: string[], action: string): boolean | Node { + 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 +644,37 @@ 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(configIdentifier), exportsDecl.pop()]), type: "AssignmentExpression" }; + (p.value as Node).body[bodyLength - 1] = newVal; return false; // TODO: debug later } + + function addMergeImports(configIdentifier: string, configPath: string): void { + if (typeof configIdentifier !== "string" || typeof configPath !== "string") { + throw new Error( + `Both parameters should be strings. recieved ${typeof configIdentifier}, ${typeof configPath}` + ); + } + 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')`); + } + + if (!isImportPresent(j, ast, configPath)) { + (p.value as Node).body.splice(-1, 0, `const ${configIdentifier} = require('${configPath}')`); + } + } + ); + } + if (value) { - return ast.find(j.Program).filter((p: Node): boolean => createMergeProperty(p)); + const [configIdentifier, configPath] = value; + addMergeImports(configIdentifier, configPath); + return ast.find(j.Program).filter((p: Node): boolean => createMergeProperty(p, configIdentifier)); } else { return ast; } diff --git a/packages/utils/modify-config-helper.ts b/packages/utils/modify-config-helper.ts index 36f9c3bc897..4eead2415fb 100644 --- a/packages/utils/modify-config-helper.ts +++ b/packages/utils/modify-config-helper.ts @@ -8,6 +8,22 @@ import * as Generator from "yeoman-generator"; import { TransformConfig } from "./types/Config"; import runTransform from "./scaffold"; +export interface Config extends Object { + item?: { + name: string; + }; + topScope?: string[]; + configName?: string; + merge: string | string[]; + webpackOptions: object; +} + +export interface TransformConfig extends Object { + configPath?: string; + configFile?: string; + config?: Config; +} + const DEFAULT_WEBPACK_CONFIG_FILENAME = "webpack.config.js"; /** diff --git a/packages/utils/package-lock.json b/packages/utils/package-lock.json index efe1c450fdd..2ec44ee29af 100644 --- a/packages/utils/package-lock.json +++ b/packages/utils/package-lock.json @@ -200,7 +200,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": { @@ -875,47 +875,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": { @@ -2366,7 +2366,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" @@ -2384,7 +2384,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" @@ -2993,8 +2993,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -3012,13 +3011,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" @@ -3031,18 +3028,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", @@ -3145,8 +3139,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -3156,7 +3149,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3169,20 +3161,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" @@ -3199,7 +3188,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3272,8 +3260,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -3283,7 +3270,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3359,8 +3345,7 @@ }, "safe-buffer": { "version": "5.1.1", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -3390,7 +3375,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", @@ -3408,7 +3392,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3447,13 +3430,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.0.2", - "bundled": true, - "optional": true + "bundled": true } } }, @@ -3615,7 +3596,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", @@ -5273,7 +5254,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", diff --git a/packages/utils/recursive-parser.ts b/packages/utils/recursive-parser.ts index a6312798f5b..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 (typeof value === "string") { + if (Array.isArray(value)) { return utils.parseMerge(j, ast, value, action); } } diff --git a/packages/utils/scaffold.ts b/packages/utils/scaffold.ts index 4d4e2705263..94f8e7d911e 100644 --- a/packages/utils/scaffold.ts +++ b/packages/utils/scaffold.ts @@ -53,7 +53,7 @@ export default function runTransform(transformConfig: TransformConfig, action: s transformations.push("topScope"); } - if (config.merge) { + if (config.merge && transformations.indexOf("merge") === -1) { transformations.push("merge"); } diff --git a/packages/utils/types/NodePath.ts b/packages/utils/types/NodePath.ts index 66098c06894..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[]; @@ -92,4 +93,4 @@ export interface JSCodeshift extends Object { }; } -export type valueType = string | number | boolean | Node | null; +export type valueType = string[] | string | number | boolean | Node | null; diff --git a/packages/utils/types/index.ts b/packages/utils/types/index.ts index 94ae1b51916..a73286b5833 100644 --- a/packages/utils/types/index.ts +++ b/packages/utils/types/index.ts @@ -1,12 +1,5 @@ -import { Error } from './Error'; -import { Config, TransformConfig } from './Config'; +import { Error } from "./Error"; +import { Config, TransformConfig } from "./Config"; import { Node, JSCodeshift, valueType } from "./NodePath"; -export { - Error, - Config, - Node, - TransformConfig, - JSCodeshift, - valueType -} +export { Error, Config, Node, TransformConfig, JSCodeshift, valueType };