diff --git a/sbt-scalajs-esbuild-web/src/main/scala/scalajsesbuild/EsbuildWebScripts.scala b/sbt-scalajs-esbuild-web/src/main/scala/scalajsesbuild/EsbuildWebScripts.scala index 73d18413..fbaba551 100644 --- a/sbt-scalajs-esbuild-web/src/main/scala/scalajsesbuild/EsbuildWebScripts.scala +++ b/sbt-scalajs-esbuild-web/src/main/scala/scalajsesbuild/EsbuildWebScripts.scala @@ -139,6 +139,7 @@ object EsbuildWebScripts { | | const ctx = await esbuild.context({ | ...esbuildOptions( + | 'browser', | entryPoints, | outDirectory, | outputFilesDirectory, diff --git a/sbt-scalajs-esbuild-web/src/main/scala/scalajsesbuild/ScalaJSEsbuildWebPlugin.scala b/sbt-scalajs-esbuild-web/src/main/scala/scalajsesbuild/ScalaJSEsbuildWebPlugin.scala index 5ddbef16..10de79d3 100644 --- a/sbt-scalajs-esbuild-web/src/main/scala/scalajsesbuild/ScalaJSEsbuildWebPlugin.scala +++ b/sbt-scalajs-esbuild-web/src/main/scala/scalajsesbuild/ScalaJSEsbuildWebPlugin.scala @@ -1,7 +1,9 @@ package scalajsesbuild import org.scalajs.jsenv.Input.Script +import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.ModuleKind import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.jsEnvInput +import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.scalaJSLinkerConfig import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.scalaJSStage import org.scalajs.sbtplugin.Stage import org.typelevel.jawn.ast.JObject @@ -14,8 +16,9 @@ import scalajsesbuild.ScalaJSEsbuildPlugin.autoImport.esbuildBundleScript import scalajsesbuild.ScalaJSEsbuildPlugin.autoImport.esbuildCompile import scalajsesbuild.ScalaJSEsbuildPlugin.autoImport.esbuildInstall import scalajsesbuild.ScalaJSEsbuildPlugin.autoImport.esbuildRunner - +import scalajsesbuild.ScalaJSEsbuildPlugin.autoImport.esbuildScalaJSModuleConfigurations import java.nio.file.Path + import scala.sys.process.* object ScalaJSEsbuildWebPlugin extends AutoPlugin { @@ -39,6 +42,9 @@ object ScalaJSEsbuildWebPlugin extends AutoPlugin { override lazy val projectSettings: Seq[Setting[?]] = Seq( + scalaJSLinkerConfig ~= { + _.withModuleKind(ModuleKind.ESModule) + }, esbuildBundleHtmlEntryPoints := Seq( Path.of("index.html") ) @@ -93,7 +99,13 @@ object ScalaJSEsbuildWebPlugin extends AutoPlugin { Seq( stageTask / esbuildBundleScript := { val stageTaskReport = stageTask.value.data - val entryPoints = jsFileNames(stageTaskReport).toSeq + val moduleConfigurations = esbuildScalaJSModuleConfigurations.value + val entryPoints = + extractEntryPointsByPlatform(stageTaskReport, moduleConfigurations) + .getOrElse( + EsbuildScalaJSModuleConfiguration.EsbuildPlatform.Browser, + Set.empty + ) val entryPointsJsArray = entryPoints.map("'" + _ + "'").mkString("[", ",", "]") val targetDirectory = (esbuildInstall / crossTarget).value @@ -107,6 +119,7 @@ object ScalaJSEsbuildWebPlugin extends AutoPlugin { s"Target directory [$targetDirectory] must be parent directory of output directory [$outputDirectory]" ) ) + val relativeOutputDirectoryJs = s"'$relativeOutputDirectory'" val htmlEntryPoints = esbuildBundleHtmlEntryPoints.value require( !htmlEntryPoints.forall(_.isAbsolute), @@ -132,8 +145,9 @@ object ScalaJSEsbuildWebPlugin extends AutoPlugin { |${EsbuildWebScripts.transformHtmlEntryPoints} | |const metaFilePromise = bundle( + | ${EsbuildScalaJSModuleConfiguration.EsbuildPlatform.Browser.jsValue}, | $entryPointsJsArray, - | ${s"'$relativeOutputDirectory'"}, + | $relativeOutputDirectoryJs, | 'assets', | $hashOutputFiles, | $minify, @@ -144,7 +158,7 @@ object ScalaJSEsbuildWebPlugin extends AutoPlugin { | .then((metaFile) => { | transformHtmlEntryPoints( | $htmlEntryPointsJsArray, - | ${s"'$relativeOutputDirectory'"}, + | $relativeOutputDirectoryJs, | metaFile | ); | }); @@ -164,7 +178,13 @@ object ScalaJSEsbuildWebPlugin extends AutoPlugin { Seq( stageTask / esbuildServeScript := { val stageTaskReport = stageTask.value.data - val entryPoints = jsFileNames(stageTaskReport).toSeq + val moduleConfigurations = esbuildScalaJSModuleConfigurations.value + val entryPoints = + extractEntryPointsByPlatform(stageTaskReport, moduleConfigurations) + .getOrElse( + EsbuildScalaJSModuleConfiguration.EsbuildPlatform.Browser, + Set.empty + ) val entryPointsJsArray = entryPoints.map("'" + _ + "'").mkString("[", ",", "]") val targetDirectory = (esbuildInstall / crossTarget).value @@ -178,6 +198,7 @@ object ScalaJSEsbuildWebPlugin extends AutoPlugin { s"Target directory [$targetDirectory] must be parent directory of output directory [$outputDirectory]" ) ) + val relativeOutputDirectoryJs = s"'$relativeOutputDirectory'" val htmlEntryPoints = esbuildBundleHtmlEntryPoints.value require( !htmlEntryPoints.forall(_.isAbsolute), @@ -200,7 +221,7 @@ object ScalaJSEsbuildWebPlugin extends AutoPlugin { | |serve( | $entryPointsJsArray, - | ${s"'$relativeOutputDirectory'"}, + | $relativeOutputDirectoryJs, | 'assets', | 'sbt-scalajs-esbuild-serve-meta.json', | 8001, diff --git a/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/EsbuildScalaJSModuleConfiguration.scala b/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/EsbuildScalaJSModuleConfiguration.scala new file mode 100644 index 00000000..3bdeec7f --- /dev/null +++ b/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/EsbuildScalaJSModuleConfiguration.scala @@ -0,0 +1,20 @@ +package scalajsesbuild + +import scalajsesbuild.EsbuildScalaJSModuleConfiguration.EsbuildPlatform + +final class EsbuildScalaJSModuleConfiguration(val platform: EsbuildPlatform) { + override def toString: String = { + s"EsbuildScalaJSModuleConfiguration($platform)" + } +} + +object EsbuildScalaJSModuleConfiguration { + sealed trait EsbuildPlatform { + def jsValue: String = s"'${toString.toLowerCase}'" + } + object EsbuildPlatform { + case object Browser extends EsbuildPlatform + case object Node extends EsbuildPlatform + case object Neutral extends EsbuildPlatform + } +} diff --git a/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/EsbuildScripts.scala b/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/EsbuildScripts.scala index f99fd173..45170eec 100644 --- a/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/EsbuildScripts.scala +++ b/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/EsbuildScripts.scala @@ -5,6 +5,7 @@ object EsbuildScripts { private[scalajsesbuild] def esbuildOptions = { // language=JS """const esbuildOptions = ( + | platform, | entryPoints, | outDirectory, | outputFilesDirectory, @@ -64,6 +65,7 @@ object EsbuildScripts { | } | | return { + | platform: platform, | entryPoints: entryPoints, | bundle: true, | outdir: path.normalize(outDirectory), @@ -93,6 +95,7 @@ object EsbuildScripts { private[scalajsesbuild] def bundle = { // language=JS """const bundle = async ( + | platform, | entryPoints, | outDirectory, | outputFilesDirectory, @@ -105,6 +108,7 @@ object EsbuildScripts { | | const result = await esbuild.build( | esbuildOptions( + | platform, | entryPoints, | outDirectory, | outputFilesDirectory, @@ -113,10 +117,45 @@ object EsbuildScripts { | ) | ); | - | fs.writeFileSync(metaFileName, JSON.stringify(result.metafile)); + | if (metaFileName) { + | fs.writeFileSync(metaFileName, JSON.stringify(result.metafile)); + | } | | return result.metafile; |}; |""".stripMargin } + + private[scalajsesbuild] def bundleByPlatform = { + // language=JS + """const bundleByPlatform = async ( + | entryPointsByPlatform, + | outDirectory, + | outputFilesDirectory, + | hashOutputFiles, + | minify + |) => { + | return await Promise + | .all( + | Object.keys(entryPointsByPlatform).reduce((acc, platform) => { + | const platformMetafilePromise = + | bundle( + | platform, + | entryPointsByPlatform[platform], + | outDirectory, + | outputFilesDirectory, + | hashOutputFiles, + | minify + | ) + | .then((metafile) => { + | return {[platform]: metafile}; + | }); + | acc.push(platformMetafilePromise); + | return acc; + | }, []) + | ) + | .then((results) => results.reduce((acc, result) => ({...acc, ...result}) , {})); + |}; + |""".stripMargin + } } diff --git a/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/ScalaJSEsbuildPlugin.scala b/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/ScalaJSEsbuildPlugin.scala index 7fcffcd5..da9e8b5b 100644 --- a/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/ScalaJSEsbuildPlugin.scala +++ b/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/ScalaJSEsbuildPlugin.scala @@ -11,6 +11,7 @@ import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.fullLinkJS import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.jsEnvInput import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.scalaJSLinkerConfig import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.scalaJSLinkerOutputDirectory +import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.scalaJSModuleInitializers import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport.scalaJSStage import org.scalajs.sbtplugin.Stage import sbt.* @@ -41,6 +42,10 @@ object ScalaJSEsbuildPlugin extends AutoPlugin { taskKey( "Compiles module and copies output to target directory" ) + val esbuildScalaJSModuleConfigurations + : TaskKey[Map[String, EsbuildScalaJSModuleConfiguration]] = taskKey( + "esbuild configurations for Scala.js modules" + ) val esbuildBundleScript: TaskKey[String] = taskKey( "esbuild script used for bundling" ) // TODO consider doing the writing of the script upon call of this task, then use FileChanges to track changes to the script @@ -58,9 +63,6 @@ object ScalaJSEsbuildPlugin extends AutoPlugin { import autoImport.* override lazy val projectSettings: Seq[Setting[?]] = Seq( - scalaJSLinkerConfig ~= { - _.withModuleKind(ModuleKind.ESModule) - }, esbuildRunner := EsbuildRunner.Default, esbuildResourcesDirectory := baseDirectory.value / "esbuild", esbuildPackageManager := PackageManager.Npm, @@ -82,6 +84,21 @@ object ScalaJSEsbuildPlugin extends AutoPlugin { inConfig(Test)(perConfigSettings) private lazy val perConfigSettings: Seq[Setting[?]] = Seq( + esbuildScalaJSModuleConfigurations := { + val moduleKind = scalaJSLinkerConfig.value.moduleKind + val esbuildModuleConfiguration = new EsbuildScalaJSModuleConfiguration( + platform = moduleKind match { + case ModuleKind.CommonJSModule => + EsbuildScalaJSModuleConfiguration.EsbuildPlatform.Node + case _ => + EsbuildScalaJSModuleConfiguration.EsbuildPlatform.Browser + } + ) + val modules = scalaJSModuleInitializers.value + modules + .map(module => module.moduleID -> esbuildModuleConfiguration) + .toMap + }, esbuildInstall / crossTarget := { crossTarget.value / "esbuild" / @@ -193,7 +210,13 @@ object ScalaJSEsbuildPlugin extends AutoPlugin { stageTask / esbuildBundle / crossTarget := (esbuildInstall / crossTarget).value / "out", stageTask / esbuildBundleScript := { val stageTaskReport = stageTask.value.data - val entryPoints = jsFileNames(stageTaskReport).toSeq + val moduleConfigurations = esbuildScalaJSModuleConfigurations.value + val entryPointsByPlatform = + extractEntryPointsByPlatform(stageTaskReport, moduleConfigurations) + val entryPointsByPlatformJs = "{" + entryPointsByPlatform + .foldLeft("") { case (acc, (platform, entryPoints)) => + acc + s"${platform.jsValue}:${entryPoints.map("'" + _ + "'").mkString("[", ",", "]")}" + } + "}" val targetDirectory = (esbuildInstall / crossTarget).value val outputDirectory = (stageTask / esbuildBundle / crossTarget).value @@ -205,6 +228,7 @@ object ScalaJSEsbuildPlugin extends AutoPlugin { s"Target directory [$targetDirectory] must be parent directory of output directory [$outputDirectory]" ) ) + val relativeOutputDirectoryJs = s"'$relativeOutputDirectory'" val minify = if (configuration.value == Test) { false @@ -218,13 +242,14 @@ object ScalaJSEsbuildPlugin extends AutoPlugin { | |${EsbuildScripts.bundle} | - |bundle( - | ${entryPoints.map("'" + _ + "'").mkString("[", ",", "]")}, - | ${s"'$relativeOutputDirectory'"}, + |${EsbuildScripts.bundleByPlatform} + | + |bundleByPlatform( + | $entryPointsByPlatformJs, + | $relativeOutputDirectoryJs, | null, | false, - | $minify, - | 'sbt-scalajs-esbuild-bundle-meta.json' + | $minify |); |""".stripMargin }, diff --git a/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/package.scala b/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/package.scala index b5f81689..8c9a8d04 100644 --- a/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/package.scala +++ b/sbt-scalajs-esbuild/src/main/scala/scalajsesbuild/package.scala @@ -26,6 +26,36 @@ package object scalajsesbuild { } } + private[scalajsesbuild] def extractEntryPointsByPlatform( + report: Report, + moduleConfigurations: Map[String, EsbuildScalaJSModuleConfiguration] + ) = { + report match { + case report: unstable.ReportImpl => + report.publicModules + .foldLeft( + Map.empty[EsbuildScalaJSModuleConfiguration.EsbuildPlatform, Set[ + String + ]] + ) { case (acc, publicModule) => + val platform = moduleConfigurations + .getOrElse( + publicModule.moduleID, + sys.error( + s"esbuild module configuration missing for moduleID [${publicModule.moduleID}]" + ) + ) + .platform + acc.updated( + platform, + acc.getOrElse(platform, Set.empty) + publicModule.jsFileName + ) + } + case unhandled => + sys.error(s"Unhandled report type [$unhandled]") + } + } + private[scalajsesbuild] def jsFileNames(report: Report) = { report match { case report: unstable.ReportImpl => diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/build.sbt b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/build.sbt new file mode 100644 index 00000000..87dd7786 --- /dev/null +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/build.sbt @@ -0,0 +1,28 @@ +enablePlugins(ScalaJSEsbuildPlugin) + +scalaVersion := "2.13.8" + +scalaJSLinkerConfig ~= { + _.withModuleKind(ModuleKind.ESModule) +} + +scalaJSUseMainModuleInitializer := true + +libraryDependencies ++= Seq( + "org.scala-js" %%% "scalajs-dom" % "2.2.0", + "org.scalatest" %%% "scalatest" % "3.2.15" % "test" +) + +lazy val perConfigSettings = Seq( + jsEnv := new org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv( + org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv + .Config() + .withEnv( + Map( + "NODE_PATH" -> ((esbuildInstall / crossTarget).value / "node_modules").absolutePath + ) + ) + ) +) +inConfig(Compile)(perConfigSettings) +inConfig(Test)(perConfigSettings) diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/esbuild/package.json b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/esbuild/package.json new file mode 100644 index 00000000..df166f05 --- /dev/null +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/esbuild/package.json @@ -0,0 +1,10 @@ +{ + "name": "basic-project", + "private": true, + "version": "0.0.0", + "devDependencies": { + "esbuild": "0.19.5", + "jsdom": "22.1.0", + "lodash": "4.17.21" + } +} \ No newline at end of file diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/project/plugins.sbt b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/project/plugins.sbt new file mode 100644 index 00000000..2a068612 --- /dev/null +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/project/plugins.sbt @@ -0,0 +1,32 @@ +val sourcePlugins = sys.props + .get("plugin.version") + .map { version => + println(s"Using plugin(s) version [${version}]") + Seq.empty + } + .getOrElse { + println("Building plugin(s) from source") + Seq( + ProjectRef( + file("../../../../../../"), + "sbt-scalajs-esbuild" + ): ClasspathDep[ProjectReference] + ) + } + +lazy val root = (project in file(".")) + .dependsOn(sourcePlugins: _*) + +if (sourcePlugins.nonEmpty) { + Seq.empty +} else { + val scalaJSEsbuildVersion = sys.props.getOrElse( + "plugin.version", + sys.error("'plugin.version' environment variable is not set") + ) + Seq( + addSbtPlugin("me.ptrdom" % "sbt-scalajs-esbuild" % scalaJSEsbuildVersion) + ) +} + +libraryDependencies += "org.scala-js" %% "scalajs-env-jsdom-nodejs" % "1.1.0" diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/src/main/scala/example/Main.scala b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/src/main/scala/example/Main.scala new file mode 100644 index 00000000..441d1a05 --- /dev/null +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/src/main/scala/example/Main.scala @@ -0,0 +1,29 @@ +package example + +import example.facade.Lodash +import org.scalajs.dom +import org.scalajs.dom.document + +import scala.scalajs.js +import scala.scalajs.js.annotation.JSImport + +object Main { + def main(args: Array[String]): Unit = { + document.addEventListener( + "DOMContentLoaded", + { (_: dom.Event) => + setupUI() + } + ) + } + + def setupUI(): Unit = { + val h1 = document.createElement("h1") + h1.textContent = testString() + document.body.append(h1) + } + + def testString(): String = { + Lodash.toUpper("basic-web-project works!") + } +} diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/src/main/scala/example/facade/Lodash.scala b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/src/main/scala/example/facade/Lodash.scala new file mode 100644 index 00000000..75c61f70 --- /dev/null +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/src/main/scala/example/facade/Lodash.scala @@ -0,0 +1,10 @@ +package example.facade + +import scala.scalajs.js +import scala.scalajs.js.annotation.JSImport + +@JSImport("lodash", JSImport.Namespace) +@js.native +object Lodash extends js.Object { + def toUpper(string: String): String = js.native +} diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/src/test/scala/example/MainSpec.scala b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/src/test/scala/example/MainSpec.scala new file mode 100644 index 00000000..6b48c990 --- /dev/null +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/src/test/scala/example/MainSpec.scala @@ -0,0 +1,18 @@ +package example + +import org.scalajs.dom.document +import org.scalatest.matchers.should.Matchers +import org.scalatest.wordspec.AnyWordSpec + +class MainSpec extends AnyWordSpec with Matchers { + + "Main" should { + "work" in { + Main.setupUI() + + document + .querySelector("h1") + .textContent shouldEqual "BASIC-WEB-PROJECT WORKS!" + } + } +} diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/test b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/test new file mode 100644 index 00000000..817effc7 --- /dev/null +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-browser-project/test @@ -0,0 +1,21 @@ +$ absent esbuild/package-lock.json +> set Test/scalaJSStage := org.scalajs.sbtplugin.Stage.FastOpt +> run +$ exists esbuild/package-lock.json + +$ delete esbuild/package-lock.json +> clean +> set Test/scalaJSStage := org.scalajs.sbtplugin.Stage.FullOpt +> run +$ exists esbuild/package-lock.json + +$ delete esbuild/package-lock.json +> set Test/scalaJSStage := org.scalajs.sbtplugin.Stage.FastOpt +> test +$ exists esbuild/package-lock.json + +$ delete esbuild/package-lock.json +> clean +> set Test/scalaJSStage := org.scalajs.sbtplugin.Stage.FullOpt +> test +$ exists esbuild/package-lock.json diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/build.sbt b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/build.sbt index bf36adba..3ad402cd 100644 --- a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/build.sbt +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/build.sbt @@ -2,6 +2,10 @@ enablePlugins(ScalaJSEsbuildPlugin) scalaVersion := "2.13.8" +scalaJSLinkerConfig ~= { + _.withModuleKind(ModuleKind.CommonJSModule) +} + scalaJSUseMainModuleInitializer := true libraryDependencies += "org.scalatest" %%% "scalatest" % "3.2.15" % "test" diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/esbuild/package.json b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/esbuild/package.json index ed296a9f..3958966b 100644 --- a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/esbuild/package.json +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/esbuild/package.json @@ -2,10 +2,8 @@ "name": "basic-project", "private": true, "version": "0.0.0", - "dependencies": { - "lodash": "4.17.21" - }, "devDependencies": { - "esbuild": "0.19.5" + "esbuild": "0.19.5", + "lodash": "4.17.21" } } \ No newline at end of file diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/Main.scala b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/Main.scala index 157b164d..85f8fcf8 100644 --- a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/Main.scala +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/Main.scala @@ -1,13 +1,18 @@ package example +import example.facade.Fs import example.facade.Lodash +import example.facade.Os +import example.facade.Path object Main { def main(args: Array[String]): Unit = { - println(testString()) + println(test()) } - def testString(): String = { - Lodash.toUpper("basic-node-project works!") + def test(): String = { + val file = Path.join(Fs.mkdtempSync(s"${Os.tmpdir()}${Path.sep}"), "test") + Fs.writeFileSync(file, Lodash.toUpper("basic-node-project works!"), "utf8") + Fs.readFileSync(file, "utf8") } } diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/facade/Fs.scala b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/facade/Fs.scala new file mode 100644 index 00000000..ea44fb97 --- /dev/null +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/facade/Fs.scala @@ -0,0 +1,15 @@ +package example.facade + +import scala.scalajs.js +import scala.scalajs.js.annotation.JSImport + +@js.native +@JSImport("node:fs", JSImport.Default) +object Fs extends js.Object { + def mkdtempSync(paths: String): String = js.native + + def writeFileSync(file: String, data: String, encoding: String): Unit = + js.native + + def readFileSync(path: String, encoding: String): String = js.native +} diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/facade/Os.scala b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/facade/Os.scala new file mode 100644 index 00000000..bba62fd0 --- /dev/null +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/facade/Os.scala @@ -0,0 +1,10 @@ +package example.facade + +import scala.scalajs.js +import scala.scalajs.js.annotation.JSImport + +@js.native +@JSImport("node:os", JSImport.Default) +object Os extends js.Object { + def tmpdir(): String = js.native +} diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/facade/Path.scala b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/facade/Path.scala new file mode 100644 index 00000000..fd2eb649 --- /dev/null +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/main/scala/example/facade/Path.scala @@ -0,0 +1,12 @@ +package example.facade + +import scala.scalajs.js +import scala.scalajs.js.annotation.JSImport + +@js.native +@JSImport("node:path", JSImport.Default) +object Path extends js.Object { + def join(paths: String*): String = js.native + + val sep: String = js.native +} diff --git a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/test/scala/example/MainSpec.scala b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/test/scala/example/MainSpec.scala index 430173a5..8c27fed3 100644 --- a/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/test/scala/example/MainSpec.scala +++ b/sbt-scalajs-esbuild/src/sbt-test/sbt-scalajs-esbuild/basic-node-project/src/test/scala/example/MainSpec.scala @@ -7,7 +7,7 @@ class MainSpec extends AnyWordSpec with Matchers { "Main" should { "work" in { - Main.testString() shouldEqual "BASIC-NODE-PROJECT WORKS!" + Main.test() shouldEqual "BASIC-NODE-PROJECT WORKS!" } } }