Skip to content

Commit 3709b9c

Browse files
Multiple fixes for vue transpilation (#293)
* fixed browserslist filename * create custom vue.config.js (always enable sourcemaps, overwrite user-specific settings) * use --modern vue cli build flag to create ES2015+ code. Transpiled and polyfilled bundles for older ES versions are useless. * fixed vue transpilation dependencies for mixed TS/Vue.js projects. vue-cli does not support that out of the box if the dependencies are not installed explicitly. For: https://shiftleftinc.atlassian.net/browse/SEN-1120
1 parent 2e49842 commit 3709b9c

File tree

4 files changed

+57
-31
lines changed

4 files changed

+57
-31
lines changed

src/main/scala/io/shiftleft/js2cpg/io/FileDefaults.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ object FileDefaults {
3434
".*babel\\.config\\.js".r,
3535
".*chunk-vendors.*\\.js".r, // commonly found in webpack / vue.js projects
3636
".*app~.*\\.js".r, // commonly found in webpack / vue.js projects
37+
".*app-legacy\\.js".r, // commonly found in webpack / vue.js projects
3738
".*\\.chunk\\.js".r, // see: https://github.com/ShiftLeftSecurity/product/issues/8197
3839
".*\\.babelrc.*".r,
3940
".*\\.eslint.*".r,

src/main/scala/io/shiftleft/js2cpg/preprocessing/VueTranspiler.scala

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,58 @@ import better.files.File
44
import io.shiftleft.js2cpg.core.Config
55
import io.shiftleft.js2cpg.io.ExternalCommand
66
import io.shiftleft.js2cpg.io.FileDefaults
7-
import io.shiftleft.js2cpg.io.FileDefaults.VUE_SUFFIX
7+
import io.shiftleft.js2cpg.io.FileDefaults._
88
import io.shiftleft.js2cpg.io.FileUtils
99
import io.shiftleft.js2cpg.parser.PackageJsonParser
1010
import org.slf4j.LoggerFactory
1111

1212
import java.nio.file.{Path, Paths}
1313
import scala.util.{Failure, Success}
14+
import scala.util.Try
1415

1516
object VueTranspiler {
1617

18+
private val BrowsersListRc: String = ".browserslistrc"
19+
private val VueConfigJs: String = "vue.config.js"
20+
private val Vue2Config: String =
21+
"""
22+
|module.exports = {
23+
| configureWebpack: {
24+
| devtool: 'source-map'
25+
| }
26+
|}
27+
|""".stripMargin
28+
private val Vue3Config: String =
29+
"""
30+
|const { defineConfig } = require('@vue/cli-service');
31+
|module.exports = defineConfig({
32+
| configureWebpack: {
33+
| devtool: 'source-map',
34+
| }
35+
|});
36+
|""".stripMargin
37+
1738
private def hasVueFiles(config: Config, projectPath: Path): Boolean =
1839
FileUtils.getFileTree(projectPath, config, List(VUE_SUFFIX)).nonEmpty
1940

2041
def isVueProject(config: Config, projectPath: Path): Boolean = {
2142
val hasVueDep =
22-
PackageJsonParser
23-
.dependencies((File(config.srcDir) / FileDefaults.PACKAGE_JSON_FILENAME).path)
24-
.contains("vue")
43+
PackageJsonParser.dependencies((File(config.srcDir) / FileDefaults.PACKAGE_JSON_FILENAME).path).contains("vue")
2544
hasVueDep && hasVueFiles(config, projectPath)
2645
}
46+
47+
private def vueVersion(config: Config): Int = {
48+
val versionString =
49+
PackageJsonParser.dependencies((File(config.srcDir) / FileDefaults.PACKAGE_JSON_FILENAME).path)("vue")
50+
// ignore ~, ^, and more from semver; see: https://stackoverflow.com/a/25861938
51+
val c = versionString.collectFirst { case c if Try(c.toString.toInt).isSuccess => c.toString.toInt }
52+
c.getOrElse(3) // 3 is the latest version; we default to that
53+
}
2754
}
2855

2956
class VueTranspiler(override val config: Config, override val projectPath: Path) extends Transpiler {
3057

31-
import VueTranspiler.isVueProject
58+
import VueTranspiler._
3259

3360
private val logger = LoggerFactory.getLogger(getClass)
3461

@@ -48,13 +75,17 @@ class VueTranspiler(override val config: Config, override val projectPath: Path)
4875
}
4976
}
5077

78+
private def hasTsFiles: Boolean =
79+
FileUtils.getFileTree(projectPath, config, List(TS_SUFFIX)).nonEmpty
80+
5181
private def installVuePlugins(): Boolean = {
82+
val additionalPlugins = if (hasTsFiles) "typescript @vue/cli-plugin-typescript" else ""
5283
val command = if (pnpmAvailable(projectPath)) {
53-
s"${TranspilingEnvironment.PNPM_ADD} $vueAndVersion && ${TranspilingEnvironment.PNPM_INSTALL}"
84+
s"${TranspilingEnvironment.PNPM_ADD} $vueAndVersion $additionalPlugins && ${TranspilingEnvironment.PNPM_INSTALL}"
5485
} else if (yarnAvailable()) {
55-
s"${TranspilingEnvironment.YARN_ADD} $vueAndVersion && ${TranspilingEnvironment.YARN_INSTALL}"
86+
s"${TranspilingEnvironment.YARN_ADD} $vueAndVersion $additionalPlugins && ${TranspilingEnvironment.YARN_INSTALL}"
5687
} else {
57-
s"${TranspilingEnvironment.NPM_INSTALL} $vueAndVersion"
88+
s"${TranspilingEnvironment.NPM_INSTALL} $vueAndVersion $additionalPlugins"
5889
}
5990
logger.info("Installing Vue.js dependencies and plugins. That will take a while.")
6091
logger.debug(s"\t+ Installing Vue.js plugins with command '$command' in path '$projectPath'")
@@ -69,20 +100,29 @@ class VueTranspiler(override val config: Config, override val projectPath: Path)
69100
}
70101

71102
private def createCustomBrowserslistFile(): Unit = {
72-
val browserslistFile = File(projectPath) / ".browserslistrc"
73-
if (browserslistFile.exists) {
74-
browserslistFile.delete(swallowIOExceptions = true)
103+
val browserslistFile = File(projectPath) / BrowsersListRc
104+
browserslistFile.delete(swallowIOExceptions = true)
105+
browserslistFile.createFile().deleteOnExit(swallowIOExceptions = true)
106+
browserslistFile.writeText("last 2 years")
107+
}
108+
109+
private def createCustomVueConfigFile(): Unit = {
110+
val vueConfigJsFile = File(projectPath) / VueConfigJs
111+
vueConfigJsFile.delete(swallowIOExceptions = true)
112+
vueConfigJsFile.createFile().deleteOnExit(swallowIOExceptions = true)
113+
if (vueVersion(config) <= 2) {
114+
vueConfigJsFile.writeText(Vue2Config)
115+
} else {
116+
vueConfigJsFile.writeText(Vue3Config)
75117
}
76-
val customBrowserslistFile = File
77-
.newTemporaryFile(".browserslistrc", parent = Some(projectPath))
78-
.deleteOnExit(swallowIOExceptions = true)
79-
customBrowserslistFile.writeText("last 2 years")
80118
}
81119

82120
override protected def transpile(tmpTranspileDir: Path): Boolean = {
83121
if (installVuePlugins()) {
84122
createCustomBrowserslistFile()
85-
val command = s"${ExternalCommand.toOSCommand(vue)} build --dest '$tmpTranspileDir' --mode development --no-clean"
123+
createCustomVueConfigFile()
124+
val command =
125+
s"${ExternalCommand.toOSCommand(vue)} build --dest '$tmpTranspileDir' --mode development --no-clean --modern"
86126
logger.debug(s"\t+ Vue.js transpiling $projectPath to '$tmpTranspileDir'")
87127
ExternalCommand.run(command, projectPath.toString, extraEnv = VUE_NODE_OPTIONS) match {
88128
case Success(_) => logger.debug("\t+ Vue.js transpiling finished")

src/test/resources/vue2/vue.config.js

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/test/resources/vue3/vue.config.js

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)