From 58174b5e136948717e70772816adde586a50e6eb Mon Sep 17 00:00:00 2001 From: ChristophP Date: Sun, 8 May 2022 21:53:45 +0200 Subject: [PATCH 01/25] Add multi module compilation for Elm The Elm compiler can compile multiple entrypoints into one bundle, which helps keep the asset size small since they all share the same runtime. Use like this: import { Elm } from './Main.elm?with=./AnotherModule.elm,./YetAnotherModule.elm' Elm.Main.init(); Elm.AnotherModule.init(); Elm.YetAnotherModule.init(); --- packages/transformers/elm/src/ElmTransformer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index fbbf0f045c4..d13cb21c646 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -115,7 +115,11 @@ function resolveLocalElmBinary() { } function compileToString(elm, elmBinary, asset, config) { - return elm.compileToString(asset.filePath, { + const extraSources = asset.query.get('with'); + const sources = extraSources + ? [asset.filePath, ...extraSources.split(',')] + : asset.filePath; + return elm.compileToString(sources, { pathToElm: elmBinary, ...config, }); From 21d7832a9ee8fad55241672d1561394514066bc3 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Sun, 8 May 2022 22:34:50 +0200 Subject: [PATCH 02/25] add invalidation for extra Elm sources --- .../transformers/elm/src/ElmTransformer.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index d13cb21c646..4d9730f3bf4 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -115,11 +115,20 @@ function resolveLocalElmBinary() { } function compileToString(elm, elmBinary, asset, config) { - const extraSources = asset.query.get('with'); - const sources = extraSources - ? [asset.filePath, ...extraSources.split(',')] - : asset.filePath; - return elm.compileToString(sources, { + const withParam = asset.query.get('with'); + const dirname = path.dirname(asset.filePath); + let extraSources = []; + if (withParam) { + extraSources = withParam + .split(',') + .map(relPath => path.join(dirname, relPath)); + + extraSources.forEach(filePath => { + asset.invalidateOnFileChange(filePath); + }); + } + + return elm.compileToString([asset.filePath, ...extraSources], { pathToElm: elmBinary, ...config, }); From 4f80133e7e094551b68e0701d5de302291198ea8 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Mon, 9 May 2022 21:17:36 +0200 Subject: [PATCH 03/25] add cache invalidations for all elm dependencies as well --- .../transformers/elm/src/ElmTransformer.js | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index 4d9730f3bf4..3406ca90010 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -48,7 +48,18 @@ export default (new Transformer({ optimize: asset.env.shouldOptimize, }; asset.invalidateOnEnvChange('PARCEL_ELM_NO_DEBUG'); - for (const filePath of await elm.findAllDependencies(asset.filePath)) { + + const dirname = path.dirname(asset.filePath); + const extraSources = resolveExtraSources(asset); + + extraSources.forEach(filePath => { + asset.invalidateOnFileChange(filePath); + }); + const sources = [asset.filePath, ...extraSources]; + const dependencies = await Promise.all( + sources.map(elm.findAllDependencies), + ); + for (const filePath of new Set(dependencies)) { asset.invalidateOnFileChange(filePath); } @@ -58,7 +69,7 @@ export default (new Transformer({ process.chdir.disabled = isWorker; let code; try { - code = await compileToString(elm, elmBinary, asset, compilerConfig); + code = await compileToString(elm, elmBinary, sources, compilerConfig); } catch (e) { throw new ThrowableDiagnostic({ diagnostic: { @@ -80,6 +91,16 @@ export default (new Transformer({ }, }): Transformer); +// gather extra modules that should be added to the compilation process +function resolveExtraSources(asset) { + const withParam = asset.query.get('with'); + if (withParam === null) { + return []; + } + const dirname = path.dirname(asset.filePath); + return withParam.split(',').map(relPath => path.join(dirname, relPath)); +} + function elmBinaryPath() { let elmBinary = resolveLocalElmBinary(); @@ -114,21 +135,8 @@ function resolveLocalElmBinary() { } } -function compileToString(elm, elmBinary, asset, config) { - const withParam = asset.query.get('with'); - const dirname = path.dirname(asset.filePath); - let extraSources = []; - if (withParam) { - extraSources = withParam - .split(',') - .map(relPath => path.join(dirname, relPath)); - - extraSources.forEach(filePath => { - asset.invalidateOnFileChange(filePath); - }); - } - - return elm.compileToString([asset.filePath, ...extraSources], { +function compileToString(elm, elmBinary, sources, config) { + return elm.compileToString(sources, { pathToElm: elmBinary, ...config, }); From 004a39490eed125d52234d1970348ace5bd99767 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Mon, 9 May 2022 21:34:53 +0200 Subject: [PATCH 04/25] fix nested dependencies in elm transform for multi module compilation --- packages/transformers/elm/src/ElmTransformer.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index 3406ca90010..7636a101bf9 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -59,9 +59,10 @@ export default (new Transformer({ const dependencies = await Promise.all( sources.map(elm.findAllDependencies), ); - for (const filePath of new Set(dependencies)) { + const uniqueDeps = new Set(dependencies.flat()); + Array.from(uniqueDeps).forEach(filePath => { asset.invalidateOnFileChange(filePath); - } + }); // Workaround for `chdir` not working in workers // this can be removed after https://github.com/isaacs/node-graceful-fs/pull/200 was mergend and used in parcel From 4e8eec78eaf01b4371b181c92567c365db2463a9 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Fri, 20 May 2022 20:38:17 +0200 Subject: [PATCH 05/25] elm: use multiple "with" query params for multi module compilation --- packages/transformers/elm/src/ElmTransformer.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index 21aa53460bc..c72599ae26d 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -96,12 +96,8 @@ export default (new Transformer({ // gather extra modules that should be added to the compilation process function resolveExtraSources(asset) { - const withParam = asset.query.get('with'); - if (withParam === null) { - return []; - } const dirname = path.dirname(asset.filePath); - return withParam.split(',').map(relPath => path.join(dirname, relPath)); + return asset.query.getAll('with').map(relPath => path.join(dirname, relPath)); } function elmBinaryPath() { From 3fcdd78d20607ebec88110f919d8b9df64ec771e Mon Sep 17 00:00:00 2001 From: ChristophP Date: Fri, 20 May 2022 23:17:15 +0200 Subject: [PATCH 06/25] add test for multiple elm modules --- packages/core/integration-tests/test/elm.js | 19 ++++++++ .../integration/elm-multiple-apps/elm.json | 24 ++++++++++ .../integration/elm-multiple-apps/index.js | 5 ++ .../elm-multiple-apps/package.json | 1 + .../elm-multiple-apps/src/AnotherModule.elm | 47 +++++++++++++++++++ .../elm-multiple-apps/src/Main.elm | 47 +++++++++++++++++++ .../src/YetAnotherModule.elm | 47 +++++++++++++++++++ .../integration/elm-multiple-apps/yarn.lock | 0 .../transformers/elm/src/ElmTransformer.js | 2 +- 9 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/elm.json create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/index.js create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/package.json create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/src/AnotherModule.elm create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/src/Main.elm create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/src/YetAnotherModule.elm create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/yarn.lock diff --git a/packages/core/integration-tests/test/elm.js b/packages/core/integration-tests/test/elm.js index 702be99b4f1..5b7be5ef337 100644 --- a/packages/core/integration-tests/test/elm.js +++ b/packages/core/integration-tests/test/elm.js @@ -133,4 +133,23 @@ describe('elm', function () { }, ); }); + + it('should produce extra Modules given in "with" query param', async function () { + const b = await bundle( + path.join(__dirname, '/integration/elm-multiple-apps/index.js'), + ); + + assertBundles(b, [ + { + type: 'js', + assets: ['Main.elm', 'index.js', 'esmodule-helpers.js'], + }, + ]); + + const output = await run(b); + const {Elm} = output(); + assert.equal(typeof Elm.Main.init, 'function'); + assert.equal(typeof Elm.AnotherModule.init, 'function'); + assert.equal(typeof Elm.YetAnotherModule.init, 'function'); + }); }); diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/elm.json b/packages/core/integration-tests/test/integration/elm-multiple-apps/elm.json new file mode 100644 index 00000000000..dea3450db11 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/elm.json @@ -0,0 +1,24 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/browser": "1.0.2", + "elm/core": "1.0.5", + "elm/html": "1.0.0" + }, + "indirect": { + "elm/json": "1.1.3", + "elm/time": "1.0.0", + "elm/url": "1.0.0", + "elm/virtual-dom": "1.0.2" + } + }, + "test-dependencies": { + "direct": {}, + "indirect": {} + } +} diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/index.js b/packages/core/integration-tests/test/integration/elm-multiple-apps/index.js new file mode 100644 index 00000000000..3efb4a455e9 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/index.js @@ -0,0 +1,5 @@ +import local from './src/Main.elm?with=AnotherModule.elm&with=YetAnotherModule.elm'; + +module.exports = function () { + return local; +}; diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/package.json b/packages/core/integration-tests/test/integration/elm-multiple-apps/package.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/package.json @@ -0,0 +1 @@ +{} diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/AnotherModule.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/AnotherModule.elm new file mode 100644 index 00000000000..518198adf32 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/AnotherModule.elm @@ -0,0 +1,47 @@ +module AnotherModule exposing (main) + +import Browser +import Html exposing (Html, button, div, text) +import Html.Events exposing (onClick) + + +type alias Model = + { count : Int } + + +initialModel : Model +initialModel = + { count = 0 } + + +type Msg + = Increment + | Decrement + + +update : Msg -> Model -> Model +update msg model = + case msg of + Increment -> + { model | count = model.count + 1 } + + Decrement -> + { model | count = model.count - 1 } + + +view : Model -> Html Msg +view model = + div [] + [ button [ onClick Increment ] [ text "+1" ] + , div [] [ text <| String.fromInt model.count ] + , button [ onClick Decrement ] [ text "-1" ] + ] + + +main : Program () Model Msg +main = + Browser.sandbox + { init = initialModel + , view = view + , update = update + } diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/Main.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/Main.elm new file mode 100644 index 00000000000..3c9a587a70d --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/Main.elm @@ -0,0 +1,47 @@ +module Main exposing (main) + +import Browser +import Html exposing (Html, button, div, text) +import Html.Events exposing (onClick) + + +type alias Model = + { count : Int } + + +initialModel : Model +initialModel = + { count = 0 } + + +type Msg + = Increment + | Decrement + + +update : Msg -> Model -> Model +update msg model = + case msg of + Increment -> + { model | count = model.count + 1 } + + Decrement -> + { model | count = model.count - 1 } + + +view : Model -> Html Msg +view model = + div [] + [ button [ onClick Increment ] [ text "+1" ] + , div [] [ text <| String.fromInt model.count ] + , button [ onClick Decrement ] [ text "-1" ] + ] + + +main : Program () Model Msg +main = + Browser.sandbox + { init = initialModel + , view = view + , update = update + } diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/YetAnotherModule.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/YetAnotherModule.elm new file mode 100644 index 00000000000..774bd046997 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/YetAnotherModule.elm @@ -0,0 +1,47 @@ +module YetAnotherModule exposing (main) + +import Browser +import Html exposing (Html, button, div, text) +import Html.Events exposing (onClick) + + +type alias Model = + { count : Int } + + +initialModel : Model +initialModel = + { count = 0 } + + +type Msg + = Increment + | Decrement + + +update : Msg -> Model -> Model +update msg model = + case msg of + Increment -> + { model | count = model.count + 1 } + + Decrement -> + { model | count = model.count - 1 } + + +view : Model -> Html Msg +view model = + div [] + [ button [ onClick Increment ] [ text "+1" ] + , div [] [ text <| String.fromInt model.count ] + , button [ onClick Decrement ] [ text "-1" ] + ] + + +main : Program () Model Msg +main = + Browser.sandbox + { init = initialModel + , view = view + , update = update + } diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/yarn.lock b/packages/core/integration-tests/test/integration/elm-multiple-apps/yarn.lock new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index c72599ae26d..809007bcbac 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -58,7 +58,7 @@ export default (new Transformer({ }); const sources = [asset.filePath, ...extraSources]; const dependencies = await Promise.all( - sources.map(elm.findAllDependencies), + sources.map(source => elm.findAllDependencies(source)), ); const uniqueDeps = new Set(dependencies.flat()); Array.from(uniqueDeps).forEach(filePath => { From baa5bc410809ed88d3ff124f3b53302cdf490c31 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 23 May 2022 10:27:28 -0400 Subject: [PATCH 07/25] Fix lint --- packages/transformers/elm/src/ElmTransformer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index 809007bcbac..b2ff8624621 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -50,7 +50,6 @@ export default (new Transformer({ }; asset.invalidateOnEnvChange('PARCEL_ELM_NO_DEBUG'); - const dirname = path.dirname(asset.filePath); const extraSources = resolveExtraSources(asset); extraSources.forEach(filePath => { From e7162240b60f72b280e96cea4ca4bb336252d718 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Sun, 29 May 2022 17:06:20 +0200 Subject: [PATCH 08/25] implement multi module elm compilation using a bit of package.json config --- .../transformers/elm/src/ElmTransformer.js | 76 +++++++++++++++++-- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index b2ff8624621..aeaa587cace 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -21,12 +21,13 @@ try { } export default (new Transformer({ - async loadConfig({config}) { + async loadConfig({config, options, logger}) { const elmConfig = await config.getConfig(['elm.json']); if (!elmConfig) { elmBinaryPath(); // Check if elm is even installed throw new ThrowableDiagnostic({ diagnostic: { + origin: '@parcel/elm-transformer', message: "The 'elm.json' file is missing.", hints: [ "Initialize your elm project by running 'elm init'", @@ -35,10 +36,36 @@ export default (new Transformer({ }, }); } - return elmConfig.contents; + + const packageJsonConfig = await config.getConfig(['package.json'], { + packageKey: '@parcel/transformer-elm', + }); + + const transformerConfig = packageJsonConfig?.contents ?? {extraSources: {}}; + if (transformerConfig) { + const isValidConfig = Object.values(transformerConfig.extraSources).every( + val => Array.isArray(val), + ); + if (!isValidConfig) { + throw new ThrowableDiagnostic({ + diagnostic: { + origin: '@parcel/elm-transformer', + message: 'The config is the package.json file is invalid', + hints: [ + '"extraSources" needs to be an object whose values are string-arrays."', + ], + }, + }); + } + } + + return { + elmJson: elmConfig.contents, + transformerConfig, + }; }, - async transform({asset, options}) { + async transform({asset, options, config, logger}) { const elmBinary = elmBinaryPath(); const compilerConfig = { spawn, @@ -50,7 +77,15 @@ export default (new Transformer({ }; asset.invalidateOnEnvChange('PARCEL_ELM_NO_DEBUG'); - const extraSources = resolveExtraSources(asset); + const extraSourcesConfig: {[string]: string[]} = + config.transformerConfig.extraSources; + + const extraSources = resolveExtraSources({ + filePath: asset.filePath, + projectRoot: options.projectRoot, + extraSourcesConfig, + logger, + }); extraSources.forEach(filePath => { asset.invalidateOnFileChange(filePath); @@ -94,9 +129,36 @@ export default (new Transformer({ }): Transformer); // gather extra modules that should be added to the compilation process -function resolveExtraSources(asset) { - const dirname = path.dirname(asset.filePath); - return asset.query.getAll('with').map(relPath => path.join(dirname, relPath)); +function resolveExtraSources({ + filePath, + projectRoot, + extraSourcesConfig, + logger, +}) { + const keyValuePair = Object.entries(extraSourcesConfig).find( + ([mainSrc]) => filePath === path.join(projectRoot, mainSrc), + ); + + if (Object.keys(extraSourcesConfig).length > 0 && !keyValuePair) { + logger.warn({ + message: 'Specified extraSources for Elm but none were found.', + hints: [ + 'Maybe check your extraSources configuration in your package json', + ], + }); + } + + const relativePaths = keyValuePair ? keyValuePair[1] : []; + + if (relativePaths.length > 0) { + logger.info({ + message: md`Compiling elm with additional sources: ${md.bold( + JSON.stringify(relativePaths), + )}`, + }); + } + + return relativePaths.map(relPath => path.join(projectRoot, relPath)); } function elmBinaryPath() { From 96f00dc380aa4a9352e3c2d529df050f025c540e Mon Sep 17 00:00:00 2001 From: ChristophP Date: Sun, 29 May 2022 17:12:45 +0200 Subject: [PATCH 09/25] fix linting --- packages/transformers/elm/src/ElmTransformer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index aeaa587cace..62c8c1fc5a3 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -21,7 +21,7 @@ try { } export default (new Transformer({ - async loadConfig({config, options, logger}) { + async loadConfig({config}) { const elmConfig = await config.getConfig(['elm.json']); if (!elmConfig) { elmBinaryPath(); // Check if elm is even installed From d59eb0f7e1aa034550a7fa0fa03bb0d036462743 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Sun, 29 May 2022 21:06:34 +0200 Subject: [PATCH 10/25] add tests for multi module compilation --- packages/core/integration-tests/test/elm.js | 36 ++++++++++++-- .../elm-multiple-apps-broken-config/elm.json | 24 ++++++++++ .../package.json | 7 +++ .../src/Main.elm | 7 +++ .../src/MainB.elm | 7 +++ .../src/MainC.elm | 7 +++ .../src/index.js | 5 ++ .../elm-multiple-apps-broken-config/yarn.lock | 0 .../integration/elm-multiple-apps/index.js | 5 -- .../elm-multiple-apps/package.json | 11 ++++- .../elm-multiple-apps/src/AnotherModule.elm | 47 ------------------- .../elm-multiple-apps/src/Main.elm | 44 +---------------- .../elm-multiple-apps/src/MainB.elm | 7 +++ .../elm-multiple-apps/src/MainC.elm | 7 +++ .../src/YetAnotherModule.elm | 47 ------------------- .../elm-multiple-apps/src/index.js | 5 ++ .../transformers/elm/src/ElmTransformer.js | 5 +- 17 files changed, 122 insertions(+), 149 deletions(-) create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/elm.json create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/package.json create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/Main.elm create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainB.elm create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainC.elm create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/index.js create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/yarn.lock delete mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/index.js delete mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/src/AnotherModule.elm create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/src/MainB.elm create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/src/MainC.elm delete mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/src/YetAnotherModule.elm create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/src/index.js diff --git a/packages/core/integration-tests/test/elm.js b/packages/core/integration-tests/test/elm.js index 5b7be5ef337..97362325101 100644 --- a/packages/core/integration-tests/test/elm.js +++ b/packages/core/integration-tests/test/elm.js @@ -134,22 +134,48 @@ describe('elm', function () { ); }); - it('should produce extra Modules given in "with" query param', async function () { + it('should produce extra Modules given extraSources in the package.json', async function () { const b = await bundle( - path.join(__dirname, '/integration/elm-multiple-apps/index.js'), + path.join(__dirname, '/integration/elm-multiple-apps/src/index.js'), ); assertBundles(b, [ { type: 'js', - assets: ['Main.elm', 'index.js', 'esmodule-helpers.js'], + assets: ['Main.elm', 'index.js'], }, ]); const output = await run(b); const {Elm} = output(); assert.equal(typeof Elm.Main.init, 'function'); - assert.equal(typeof Elm.AnotherModule.init, 'function'); - assert.equal(typeof Elm.YetAnotherModule.init, 'function'); + assert.equal(typeof Elm.MainB.init, 'function'); + assert.equal(typeof Elm.MainC.init, 'function'); + }); + + it('should error for a broken extraSources config in the package.json', async function () { + await assert.rejects( + () => + bundle( + path.join( + __dirname, + '/integration/elm-multiple-apps-broken-config/src/index.js', + ), + {mode: 'production'}, + ), + + { + name: 'BuildError', + diagnostics: [ + { + origin: '@parcel/elm-transformer', + message: 'The config in the package.json file is invalid', + hints: [ + '"extraSources" needs to be an object whose values are string-arrays."', + ], + }, + ], + }, + ); }); }); diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/elm.json b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/elm.json new file mode 100644 index 00000000000..dea3450db11 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/elm.json @@ -0,0 +1,24 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/browser": "1.0.2", + "elm/core": "1.0.5", + "elm/html": "1.0.0" + }, + "indirect": { + "elm/json": "1.1.3", + "elm/time": "1.0.0", + "elm/url": "1.0.0", + "elm/virtual-dom": "1.0.2" + } + }, + "test-dependencies": { + "direct": {}, + "indirect": {} + } +} diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/package.json b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/package.json new file mode 100644 index 00000000000..2438b63f82a --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/package.json @@ -0,0 +1,7 @@ +{ + "@parcel/transformer-elm": { + "extraSources": { + "./src/Main.elm": "This should be an array" + } + } +} diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/Main.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/Main.elm new file mode 100644 index 00000000000..67393aaa654 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/Main.elm @@ -0,0 +1,7 @@ +module Main exposing (main) + +import Html + + +main = + Html.text "Hello, world!" diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainB.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainB.elm new file mode 100644 index 00000000000..6fdc2c1116d --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainB.elm @@ -0,0 +1,7 @@ +module MainB exposing (main) + +import Html + + +main = + Html.text "Hello, world!" diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainC.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainC.elm new file mode 100644 index 00000000000..6e3d241ba64 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainC.elm @@ -0,0 +1,7 @@ +module MainC exposing (main) + +import Html + + +main = + Html.text "Hello, world!" diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/index.js b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/index.js new file mode 100644 index 00000000000..48cef8bb968 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/index.js @@ -0,0 +1,5 @@ +var local = require('./Main.elm'); + +module.exports = function () { + return local; +}; diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/yarn.lock b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/yarn.lock new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/index.js b/packages/core/integration-tests/test/integration/elm-multiple-apps/index.js deleted file mode 100644 index 3efb4a455e9..00000000000 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import local from './src/Main.elm?with=AnotherModule.elm&with=YetAnotherModule.elm'; - -module.exports = function () { - return local; -}; diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/package.json b/packages/core/integration-tests/test/integration/elm-multiple-apps/package.json index 0967ef424bc..2142bc875b3 100644 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps/package.json +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/package.json @@ -1 +1,10 @@ -{} +{ + "@parcel/transformer-elm": { + "extraSources": { + "./src/Main.elm": [ + "./src/MainB.elm", + "./src/MainC.elm" + ] + } + } +} diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/AnotherModule.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/AnotherModule.elm deleted file mode 100644 index 518198adf32..00000000000 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/AnotherModule.elm +++ /dev/null @@ -1,47 +0,0 @@ -module AnotherModule exposing (main) - -import Browser -import Html exposing (Html, button, div, text) -import Html.Events exposing (onClick) - - -type alias Model = - { count : Int } - - -initialModel : Model -initialModel = - { count = 0 } - - -type Msg - = Increment - | Decrement - - -update : Msg -> Model -> Model -update msg model = - case msg of - Increment -> - { model | count = model.count + 1 } - - Decrement -> - { model | count = model.count - 1 } - - -view : Model -> Html Msg -view model = - div [] - [ button [ onClick Increment ] [ text "+1" ] - , div [] [ text <| String.fromInt model.count ] - , button [ onClick Decrement ] [ text "-1" ] - ] - - -main : Program () Model Msg -main = - Browser.sandbox - { init = initialModel - , view = view - , update = update - } diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/Main.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/Main.elm index 3c9a587a70d..67393aaa654 100644 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/Main.elm +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/Main.elm @@ -1,47 +1,7 @@ module Main exposing (main) -import Browser -import Html exposing (Html, button, div, text) -import Html.Events exposing (onClick) +import Html -type alias Model = - { count : Int } - - -initialModel : Model -initialModel = - { count = 0 } - - -type Msg - = Increment - | Decrement - - -update : Msg -> Model -> Model -update msg model = - case msg of - Increment -> - { model | count = model.count + 1 } - - Decrement -> - { model | count = model.count - 1 } - - -view : Model -> Html Msg -view model = - div [] - [ button [ onClick Increment ] [ text "+1" ] - , div [] [ text <| String.fromInt model.count ] - , button [ onClick Decrement ] [ text "-1" ] - ] - - -main : Program () Model Msg main = - Browser.sandbox - { init = initialModel - , view = view - , update = update - } + Html.text "Hello, world!" diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/MainB.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/MainB.elm new file mode 100644 index 00000000000..6fdc2c1116d --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/MainB.elm @@ -0,0 +1,7 @@ +module MainB exposing (main) + +import Html + + +main = + Html.text "Hello, world!" diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/MainC.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/MainC.elm new file mode 100644 index 00000000000..6e3d241ba64 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/MainC.elm @@ -0,0 +1,7 @@ +module MainC exposing (main) + +import Html + + +main = + Html.text "Hello, world!" diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/YetAnotherModule.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/YetAnotherModule.elm deleted file mode 100644 index 774bd046997..00000000000 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/YetAnotherModule.elm +++ /dev/null @@ -1,47 +0,0 @@ -module YetAnotherModule exposing (main) - -import Browser -import Html exposing (Html, button, div, text) -import Html.Events exposing (onClick) - - -type alias Model = - { count : Int } - - -initialModel : Model -initialModel = - { count = 0 } - - -type Msg - = Increment - | Decrement - - -update : Msg -> Model -> Model -update msg model = - case msg of - Increment -> - { model | count = model.count + 1 } - - Decrement -> - { model | count = model.count - 1 } - - -view : Model -> Html Msg -view model = - div [] - [ button [ onClick Increment ] [ text "+1" ] - , div [] [ text <| String.fromInt model.count ] - , button [ onClick Decrement ] [ text "-1" ] - ] - - -main : Program () Model Msg -main = - Browser.sandbox - { init = initialModel - , view = view - , update = update - } diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/index.js b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/index.js new file mode 100644 index 00000000000..48cef8bb968 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/index.js @@ -0,0 +1,5 @@ +var local = require('./Main.elm'); + +module.exports = function () { + return local; +}; diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index 62c8c1fc5a3..2440f82f169 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -44,13 +44,14 @@ export default (new Transformer({ const transformerConfig = packageJsonConfig?.contents ?? {extraSources: {}}; if (transformerConfig) { const isValidConfig = Object.values(transformerConfig.extraSources).every( - val => Array.isArray(val), + val => + Array.isArray(val) && val.every(item => typeof item === 'string'), ); if (!isValidConfig) { throw new ThrowableDiagnostic({ diagnostic: { origin: '@parcel/elm-transformer', - message: 'The config is the package.json file is invalid', + message: 'The config in the package.json file is invalid', hints: [ '"extraSources" needs to be an object whose values are string-arrays."', ], From a2fe570140aa27524abe1fb39a3f87b6d0d067d3 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Sun, 29 May 2022 22:06:56 +0200 Subject: [PATCH 11/25] refactor elm transformer by extracting config stuff in separate file, fix flow errors --- .../transformers/elm/src/ElmTransformer.js | 92 ++---------------- packages/transformers/elm/src/loadConfig.js | 96 +++++++++++++++++++ 2 files changed, 105 insertions(+), 83 deletions(-) create mode 100644 packages/transformers/elm/src/loadConfig.js diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index 2440f82f169..654f80a33dc 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -1,17 +1,17 @@ // @flow strict-local import {Transformer} from '@parcel/plugin'; -import commandExists from 'command-exists'; import spawn from 'cross-spawn'; import path from 'path'; import {minify} from 'terser'; -import nullthrows from 'nullthrows'; import ThrowableDiagnostic, {md} from '@parcel/diagnostic'; // $FlowFixMe import elm from 'node-elm-compiler'; // $FlowFixMe import elmHMR from 'elm-hot'; +import {load, elmBinaryPath} from './loadConfig'; + let isWorker; try { let worker_threads = require('worker_threads'); @@ -21,49 +21,8 @@ try { } export default (new Transformer({ - async loadConfig({config}) { - const elmConfig = await config.getConfig(['elm.json']); - if (!elmConfig) { - elmBinaryPath(); // Check if elm is even installed - throw new ThrowableDiagnostic({ - diagnostic: { - origin: '@parcel/elm-transformer', - message: "The 'elm.json' file is missing.", - hints: [ - "Initialize your elm project by running 'elm init'", - "If you installed elm as project dependency then run 'yarn elm init' or 'npx elm init'", - ], - }, - }); - } - - const packageJsonConfig = await config.getConfig(['package.json'], { - packageKey: '@parcel/transformer-elm', - }); - - const transformerConfig = packageJsonConfig?.contents ?? {extraSources: {}}; - if (transformerConfig) { - const isValidConfig = Object.values(transformerConfig.extraSources).every( - val => - Array.isArray(val) && val.every(item => typeof item === 'string'), - ); - if (!isValidConfig) { - throw new ThrowableDiagnostic({ - diagnostic: { - origin: '@parcel/elm-transformer', - message: 'The config in the package.json file is invalid', - hints: [ - '"extraSources" needs to be an object whose values are string-arrays."', - ], - }, - }); - } - } - - return { - elmJson: elmConfig.contents, - transformerConfig, - }; + loadConfig({config}) { + return load({config}); }, async transform({asset, options, config, logger}) { @@ -136,11 +95,11 @@ function resolveExtraSources({ extraSourcesConfig, logger, }) { - const keyValuePair = Object.entries(extraSourcesConfig).find( - ([mainSrc]) => filePath === path.join(projectRoot, mainSrc), + const key = Object.keys(extraSourcesConfig).find( + mainSrc => filePath === path.join(projectRoot, mainSrc), ); - if (Object.keys(extraSourcesConfig).length > 0 && !keyValuePair) { + if (Object.keys(extraSourcesConfig).length > 0 && key === undefined) { logger.warn({ message: 'Specified extraSources for Elm but none were found.', hints: [ @@ -149,7 +108,8 @@ function resolveExtraSources({ }); } - const relativePaths = keyValuePair ? keyValuePair[1] : []; + const relativePaths: string[] = + key !== undefined ? extraSourcesConfig[key] : []; if (relativePaths.length > 0) { logger.info({ @@ -162,40 +122,6 @@ function resolveExtraSources({ return relativePaths.map(relPath => path.join(projectRoot, relPath)); } -function elmBinaryPath() { - let elmBinary = resolveLocalElmBinary(); - - if (elmBinary == null && !commandExists.sync('elm')) { - throw new ThrowableDiagnostic({ - diagnostic: { - message: "Can't find 'elm' binary.", - hints: [ - "You can add it as an dependency for your project by running 'yarn add -D elm' or 'npm add -D elm'", - 'If you want to install it globally then follow instructions on https://elm-lang.org/', - ], - origin: '@parcel/elm-transformer', - }, - }); - } - - return elmBinary; -} - -function resolveLocalElmBinary() { - try { - let result = require.resolve('elm/package.json'); - // $FlowFixMe - let pkg = require('elm/package.json'); - let bin = nullthrows(pkg.bin); - return path.join( - path.dirname(result), - typeof bin === 'string' ? bin : bin.elm, - ); - } catch (_) { - return null; - } -} - function compileToString(elm, elmBinary, sources, config) { return elm.compileToString(sources, { pathToElm: elmBinary, diff --git a/packages/transformers/elm/src/loadConfig.js b/packages/transformers/elm/src/loadConfig.js new file mode 100644 index 00000000000..a09d4dac042 --- /dev/null +++ b/packages/transformers/elm/src/loadConfig.js @@ -0,0 +1,96 @@ +// @flow strict-local + +import type {Config} from '@parcel/types'; +import path from 'path'; +import ThrowableDiagnostic from '@parcel/diagnostic'; +import commandExists from 'command-exists'; +import nullthrows from 'nullthrows'; + +type ConfigResult = {| + elmJson: boolean, + transformerConfig: {|extraSources: {[string]: string[]}|}, +|}; + +async function load({config}: {|config: Config|}): Promise { + const elmConfig = await config.getConfig(['elm.json']); + if (!elmConfig) { + elmBinaryPath(); // Check if elm is even installed + throw new ThrowableDiagnostic({ + diagnostic: { + origin: '@parcel/elm-transformer', + message: "The 'elm.json' file is missing.", + hints: [ + "Initialize your elm project by running 'elm init'", + "If you installed elm as project dependency then run 'yarn elm init' or 'npx elm init'", + ], + }, + }); + } + + const packageJsonConfig = await config.getConfig(['package.json'], { + packageKey: '@parcel/transformer-elm', + }); + + const transformerConfig = packageJsonConfig?.contents ?? {extraSources: {}}; + if (transformerConfig) { + const isValidConfig = + 'extraSources' in transformerConfig && + Object.values(transformerConfig.extraSources).every( + val => + Array.isArray(val) && val.every(item => typeof item === 'string'), + ); + if (!isValidConfig) { + throw new ThrowableDiagnostic({ + diagnostic: { + origin: '@parcel/elm-transformer', + message: 'The config in the package.json file is invalid', + hints: [ + '"extraSources" needs to be an object whose values are string-arrays."', + ], + }, + }); + } + } + + return { + elmJson: elmConfig.contents, + transformerConfig, + }; +} + +function elmBinaryPath(): ?string { + let elmBinary = resolveLocalElmBinary(); + + if (elmBinary == null && !commandExists.sync('elm')) { + throw new ThrowableDiagnostic({ + diagnostic: { + message: "Can't find 'elm' binary.", + hints: [ + "You can add it as an dependency for your project by running 'yarn add -D elm' or 'npm add -D elm'", + 'If you want to install it globally then follow instructions on https://elm-lang.org/', + ], + origin: '@parcel/elm-transformer', + }, + }); + } + + return elmBinary; +} + +function resolveLocalElmBinary() { + try { + let result = require.resolve('elm/package.json'); + // $FlowFixMe + let pkg = require('elm/package.json'); + let bin = nullthrows(pkg.bin); + return path.join( + path.dirname(result), + typeof bin === 'string' ? bin : bin.elm, + ); + } catch (_) { + return null; + } +} + +export {load, elmBinaryPath}; +export type {ConfigResult}; From 753bcf7db64ec4aec02ac0a8393d69eeb7f154e2 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Sun, 29 May 2022 23:02:33 +0200 Subject: [PATCH 12/25] ix elm integration tests --- packages/transformers/elm/src/loadConfig.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/transformers/elm/src/loadConfig.js b/packages/transformers/elm/src/loadConfig.js index a09d4dac042..72483eb6976 100644 --- a/packages/transformers/elm/src/loadConfig.js +++ b/packages/transformers/elm/src/loadConfig.js @@ -31,7 +31,12 @@ async function load({config}: {|config: Config|}): Promise { packageKey: '@parcel/transformer-elm', }); - const transformerConfig = packageJsonConfig?.contents ?? {extraSources: {}}; + const defaults = {extraSources: {}}; + const transformerConfig = { + ...defaults, + ...(packageJsonConfig?.contents ?? defaults), + }; + if (transformerConfig) { const isValidConfig = 'extraSources' in transformerConfig && From af093fbfa18498ddc37f303a622d11e7b53b1f04 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Sun, 5 Jun 2022 16:53:58 +0200 Subject: [PATCH 13/25] elm: revert multi-compilation to query param solution --- .../transformers/elm/src/ElmTransformer.js | 34 ++++--------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index 654f80a33dc..e47dac897b2 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -25,7 +25,7 @@ export default (new Transformer({ return load({config}); }, - async transform({asset, options, config, logger}) { + async transform({asset, options, logger}) { const elmBinary = elmBinaryPath(); const compilerConfig = { spawn, @@ -37,13 +37,9 @@ export default (new Transformer({ }; asset.invalidateOnEnvChange('PARCEL_ELM_NO_DEBUG'); - const extraSourcesConfig: {[string]: string[]} = - config.transformerConfig.extraSources; - const extraSources = resolveExtraSources({ - filePath: asset.filePath, + asset, projectRoot: options.projectRoot, - extraSourcesConfig, logger, }); @@ -89,27 +85,9 @@ export default (new Transformer({ }): Transformer); // gather extra modules that should be added to the compilation process -function resolveExtraSources({ - filePath, - projectRoot, - extraSourcesConfig, - logger, -}) { - const key = Object.keys(extraSourcesConfig).find( - mainSrc => filePath === path.join(projectRoot, mainSrc), - ); - - if (Object.keys(extraSourcesConfig).length > 0 && key === undefined) { - logger.warn({ - message: 'Specified extraSources for Elm but none were found.', - hints: [ - 'Maybe check your extraSources configuration in your package json', - ], - }); - } - - const relativePaths: string[] = - key !== undefined ? extraSourcesConfig[key] : []; +function resolveExtraSources({asset, projectRoot, logger}) { + const dirname = path.dirname(asset.filePath); + const relativePaths = asset.query.getAll('with'); if (relativePaths.length > 0) { logger.info({ @@ -119,7 +97,7 @@ function resolveExtraSources({ }); } - return relativePaths.map(relPath => path.join(projectRoot, relPath)); + return relativePaths.map(relPath => path.join(dirname, relPath)); } function compileToString(elm, elmBinary, sources, config) { From d8f043307559d41d0a0a65c2ec73a4c4f4aead58 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Sun, 5 Jun 2022 17:01:00 +0200 Subject: [PATCH 14/25] elm: remove unneeded package.json config --- packages/transformers/elm/src/loadConfig.js | 39 +-------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/packages/transformers/elm/src/loadConfig.js b/packages/transformers/elm/src/loadConfig.js index 72483eb6976..b924b189815 100644 --- a/packages/transformers/elm/src/loadConfig.js +++ b/packages/transformers/elm/src/loadConfig.js @@ -6,12 +6,7 @@ import ThrowableDiagnostic from '@parcel/diagnostic'; import commandExists from 'command-exists'; import nullthrows from 'nullthrows'; -type ConfigResult = {| - elmJson: boolean, - transformerConfig: {|extraSources: {[string]: string[]}|}, -|}; - -async function load({config}: {|config: Config|}): Promise { +async function load({config}) { const elmConfig = await config.getConfig(['elm.json']); if (!elmConfig) { elmBinaryPath(); // Check if elm is even installed @@ -27,39 +22,8 @@ async function load({config}: {|config: Config|}): Promise { }); } - const packageJsonConfig = await config.getConfig(['package.json'], { - packageKey: '@parcel/transformer-elm', - }); - - const defaults = {extraSources: {}}; - const transformerConfig = { - ...defaults, - ...(packageJsonConfig?.contents ?? defaults), - }; - - if (transformerConfig) { - const isValidConfig = - 'extraSources' in transformerConfig && - Object.values(transformerConfig.extraSources).every( - val => - Array.isArray(val) && val.every(item => typeof item === 'string'), - ); - if (!isValidConfig) { - throw new ThrowableDiagnostic({ - diagnostic: { - origin: '@parcel/elm-transformer', - message: 'The config in the package.json file is invalid', - hints: [ - '"extraSources" needs to be an object whose values are string-arrays."', - ], - }, - }); - } - } - return { elmJson: elmConfig.contents, - transformerConfig, }; } @@ -98,4 +62,3 @@ function resolveLocalElmBinary() { } export {load, elmBinaryPath}; -export type {ConfigResult}; From 746ca81f1e437763e8524d7a4e5f91a958a0ea32 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Sun, 5 Jun 2022 23:20:50 +0200 Subject: [PATCH 15/25] elm: implement query normalization to prevent unintentional asset duplication --- .../transformers/elm/src/ElmTransformer.js | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index e47dac897b2..cff5b25d98e 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -20,12 +20,43 @@ try { isWorker = false; } +function normalizeQuery(query) { + // Sort, normalize leading "./", etc. + const normalizedAndSortedEntries = Array.from(query.entries()) + .map(([key, value]) => + key === 'with' ? [key, path.normalize(value)] : [key, value], + ) + .sort(([key1, val1], [key2, val2]) => { + if (key1 < key2) return -1; + if (key1 > key2) return 1; + if (val1 < val2) return -1; + if (val1 > val2) return 1; + return 0; + }); + return new URLSearchParams(normalizedAndSortedEntries); +} + export default (new Transformer({ loadConfig({config}) { return load({config}); }, async transform({asset, options, logger}) { + const normalizedQuery = normalizeQuery(asset.query); + // if query is not normalized, create new virtual asset with normalized query + // to prevent unintended asset duplication + if (asset.query.toString() !== normalizedQuery.toString()) { + console.log('need to normalize!'); + console.log({ + old: asset.query.toString(), + new: normalizedQuery.toString(), + }); + const specifier = `./${path.basename(asset.filePath)}?${normalizedQuery}`; + asset.setCode(`export * from "${specifier}";`); + asset.type = 'js'; + return [asset]; + } + const elmBinary = elmBinaryPath(); const compilerConfig = { spawn, From f358a784bd393344a9bece572fda530ffc99326a Mon Sep 17 00:00:00 2001 From: ChristophP Date: Mon, 6 Jun 2022 11:05:08 +0200 Subject: [PATCH 16/25] elm: fix tests for multi module compilation (query string solution) --- packages/core/integration-tests/test/elm.js | 6 +++--- .../test/integration/elm-multiple-apps/src/index.js | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/core/integration-tests/test/elm.js b/packages/core/integration-tests/test/elm.js index 97362325101..825df45f511 100644 --- a/packages/core/integration-tests/test/elm.js +++ b/packages/core/integration-tests/test/elm.js @@ -134,7 +134,7 @@ describe('elm', function () { ); }); - it('should produce extra Modules given extraSources in the package.json', async function () { + it('should produce extra Modules given in "with" query param', async function () { const b = await bundle( path.join(__dirname, '/integration/elm-multiple-apps/src/index.js'), ); @@ -142,12 +142,12 @@ describe('elm', function () { assertBundles(b, [ { type: 'js', - assets: ['Main.elm', 'index.js'], + assets: ['Main.elm', 'index.js', 'esmodule-helpers.js'], }, ]); const output = await run(b); - const {Elm} = output(); + const Elm = output.default(); assert.equal(typeof Elm.Main.init, 'function'); assert.equal(typeof Elm.MainB.init, 'function'); assert.equal(typeof Elm.MainC.init, 'function'); diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/index.js b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/index.js index 48cef8bb968..289ca88f6c4 100644 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/index.js +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/index.js @@ -1,5 +1,5 @@ -var local = require('./Main.elm'); +import { Elm } from './Main.elm?with=MainB.elm&with=MainC.elm'; -module.exports = function () { - return local; -}; +export default function() { + return Elm; +} From a2a46653d7d7f35e0161c136e36c6bc2da1fdaba Mon Sep 17 00:00:00 2001 From: ChristophP Date: Mon, 6 Jun 2022 11:06:43 +0200 Subject: [PATCH 17/25] integration tests: remove test that used elm config in package.json to compile multiple entry points --- packages/core/integration-tests/test/elm.js | 26 ------------------- .../elm-multiple-apps-broken-config/elm.json | 24 ----------------- .../package.json | 7 ----- .../src/Main.elm | 7 ----- .../src/MainB.elm | 7 ----- .../src/MainC.elm | 7 ----- .../src/index.js | 5 ---- .../elm-multiple-apps-broken-config/yarn.lock | 0 8 files changed, 83 deletions(-) delete mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/elm.json delete mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/package.json delete mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/Main.elm delete mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainB.elm delete mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainC.elm delete mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/index.js delete mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/yarn.lock diff --git a/packages/core/integration-tests/test/elm.js b/packages/core/integration-tests/test/elm.js index 825df45f511..269f1fd27a1 100644 --- a/packages/core/integration-tests/test/elm.js +++ b/packages/core/integration-tests/test/elm.js @@ -152,30 +152,4 @@ describe('elm', function () { assert.equal(typeof Elm.MainB.init, 'function'); assert.equal(typeof Elm.MainC.init, 'function'); }); - - it('should error for a broken extraSources config in the package.json', async function () { - await assert.rejects( - () => - bundle( - path.join( - __dirname, - '/integration/elm-multiple-apps-broken-config/src/index.js', - ), - {mode: 'production'}, - ), - - { - name: 'BuildError', - diagnostics: [ - { - origin: '@parcel/elm-transformer', - message: 'The config in the package.json file is invalid', - hints: [ - '"extraSources" needs to be an object whose values are string-arrays."', - ], - }, - ], - }, - ); - }); }); diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/elm.json b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/elm.json deleted file mode 100644 index dea3450db11..00000000000 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/elm.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "application", - "source-directories": [ - "src" - ], - "elm-version": "0.19.1", - "dependencies": { - "direct": { - "elm/browser": "1.0.2", - "elm/core": "1.0.5", - "elm/html": "1.0.0" - }, - "indirect": { - "elm/json": "1.1.3", - "elm/time": "1.0.0", - "elm/url": "1.0.0", - "elm/virtual-dom": "1.0.2" - } - }, - "test-dependencies": { - "direct": {}, - "indirect": {} - } -} diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/package.json b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/package.json deleted file mode 100644 index 2438b63f82a..00000000000 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "@parcel/transformer-elm": { - "extraSources": { - "./src/Main.elm": "This should be an array" - } - } -} diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/Main.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/Main.elm deleted file mode 100644 index 67393aaa654..00000000000 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/Main.elm +++ /dev/null @@ -1,7 +0,0 @@ -module Main exposing (main) - -import Html - - -main = - Html.text "Hello, world!" diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainB.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainB.elm deleted file mode 100644 index 6fdc2c1116d..00000000000 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainB.elm +++ /dev/null @@ -1,7 +0,0 @@ -module MainB exposing (main) - -import Html - - -main = - Html.text "Hello, world!" diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainC.elm b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainC.elm deleted file mode 100644 index 6e3d241ba64..00000000000 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/MainC.elm +++ /dev/null @@ -1,7 +0,0 @@ -module MainC exposing (main) - -import Html - - -main = - Html.text "Hello, world!" diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/index.js b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/index.js deleted file mode 100644 index 48cef8bb968..00000000000 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/src/index.js +++ /dev/null @@ -1,5 +0,0 @@ -var local = require('./Main.elm'); - -module.exports = function () { - return local; -}; diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/yarn.lock b/packages/core/integration-tests/test/integration/elm-multiple-apps-broken-config/yarn.lock deleted file mode 100644 index e69de29bb2d..00000000000 From 9353f45a3c6c23b38356d8a73abf91f750bc1d85 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Mon, 6 Jun 2022 14:34:33 +0200 Subject: [PATCH 18/25] elm: try to write tests for asset deduplication --- packages/core/integration-tests/test/elm.js | 20 +++++++++++++++++++ .../elm-multiple-apps/src/deduplication.js | 6 ++++++ 2 files changed, 26 insertions(+) create mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/src/deduplication.js diff --git a/packages/core/integration-tests/test/elm.js b/packages/core/integration-tests/test/elm.js index 269f1fd27a1..5e19ce024f9 100644 --- a/packages/core/integration-tests/test/elm.js +++ b/packages/core/integration-tests/test/elm.js @@ -152,4 +152,24 @@ describe('elm', function () { assert.equal(typeof Elm.MainB.init, 'function'); assert.equal(typeof Elm.MainC.init, 'function'); }); + + it('should not duplicate assets for equivalent but different query strings', async function () { + const b = await bundle( + path.join( + __dirname, + '/integration/elm-multiple-apps/src/deduplication.js', + ), + ); + + assertBundles(b, [ + { + type: 'js', + assets: ['Main.elm', 'deduplication.js', 'esmodule-helpers.js'], + }, + ]); + + const output = await run(b); + const {Elm, Elm2} = output.default(); + assert.equal(Elm, Elm2); + }); }); diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/deduplication.js b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/deduplication.js new file mode 100644 index 00000000000..a3152dc64a4 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/deduplication.js @@ -0,0 +1,6 @@ +import { Elm } from './Main.elm?with=MainB.elm&with=MainC.elm'; +import { Elm as Elm2 } from './Main.elm?with=MainC.elm&with=MainB.elm'; + +export default function() { + return { Elm, Elm2 }; +} From 4625209e197b331a4cd1a1b20cc03ecbd5b542d9 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Tue, 14 Jun 2022 22:51:38 +0200 Subject: [PATCH 19/25] add fix for crash when the reported error is not a "compile-errors" type but "error" type --- .../transformers/elm/src/ElmTransformer.js | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index cff5b25d98e..78ae30e74e9 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -97,10 +97,18 @@ export default (new Transformer({ let compilerJson = e.message.split('\n')[1]; let compilerDiagnostics = JSON.parse(compilerJson); + if (compilerDiagnostics.type === 'compile-errors') { + throw new ThrowableDiagnostic({ + diagnostic: compilerDiagnostics.errors.flatMap( + elmCompileErrorToParcelDiagnostics, + ), + }); + } + + // compilerDiagnostics.type === "error" + // happens for example when compiled in prod mode with Debug.log in code throw new ThrowableDiagnostic({ - diagnostic: compilerDiagnostics.errors.flatMap( - elmErrorToParcelDiagnostics, - ), + diagnostic: formatElmError(compilerDiagnostics, ''), }); } @@ -188,22 +196,24 @@ function formatMessagePiece(piece) { return md`${piece}`; } -function elmErrorToParcelDiagnostics(error) { +function elmCompileErrorToParcelDiagnostics(error) { const relativePath = path.relative(process.cwd(), error.path); - return error.problems.map(problem => { - const padLength = 80 - 5 - problem.title.length - relativePath.length; - const dashes = '-'.repeat(padLength); - const message = [ - '', - `-- ${problem.title} ${dashes} ${relativePath}`, - '', - problem.message.map(formatMessagePiece).join(''), - ].join('\n'); - - return { - message, - origin: '@parcel/elm-transformer', - stack: '', // set stack to empty since it is not useful - }; - }); + return error.problems.map(formatElmError, relativePath); +} + +function formatElmError(problem, relativePath) { + const padLength = 80 - 5 - problem.title.length - relativePath.length; + const dashes = '-'.repeat(padLength); + const message = [ + '', + `-- ${problem.title} ${dashes} ${relativePath}`, + '', + problem.message.map(formatMessagePiece).join(''), + ].join('\n'); + + return { + message, + origin: '@parcel/elm-transformer', + stack: '', // set stack to empty since it is not useful + }; } From a24edcd69e4ac339c51a2992bec8d56576af590e Mon Sep 17 00:00:00 2001 From: ChristophP Date: Fri, 17 Jun 2022 11:33:10 +0200 Subject: [PATCH 20/25] elm: remove deduplication logic of query string It doesn't seem to work as intended --- packages/core/integration-tests/test/elm.js | 20 ------------ .../elm-multiple-apps/src/deduplication.js | 6 ---- .../transformers/elm/src/ElmTransformer.js | 31 ------------------- 3 files changed, 57 deletions(-) delete mode 100644 packages/core/integration-tests/test/integration/elm-multiple-apps/src/deduplication.js diff --git a/packages/core/integration-tests/test/elm.js b/packages/core/integration-tests/test/elm.js index 5e19ce024f9..269f1fd27a1 100644 --- a/packages/core/integration-tests/test/elm.js +++ b/packages/core/integration-tests/test/elm.js @@ -152,24 +152,4 @@ describe('elm', function () { assert.equal(typeof Elm.MainB.init, 'function'); assert.equal(typeof Elm.MainC.init, 'function'); }); - - it('should not duplicate assets for equivalent but different query strings', async function () { - const b = await bundle( - path.join( - __dirname, - '/integration/elm-multiple-apps/src/deduplication.js', - ), - ); - - assertBundles(b, [ - { - type: 'js', - assets: ['Main.elm', 'deduplication.js', 'esmodule-helpers.js'], - }, - ]); - - const output = await run(b); - const {Elm, Elm2} = output.default(); - assert.equal(Elm, Elm2); - }); }); diff --git a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/deduplication.js b/packages/core/integration-tests/test/integration/elm-multiple-apps/src/deduplication.js deleted file mode 100644 index a3152dc64a4..00000000000 --- a/packages/core/integration-tests/test/integration/elm-multiple-apps/src/deduplication.js +++ /dev/null @@ -1,6 +0,0 @@ -import { Elm } from './Main.elm?with=MainB.elm&with=MainC.elm'; -import { Elm as Elm2 } from './Main.elm?with=MainC.elm&with=MainB.elm'; - -export default function() { - return { Elm, Elm2 }; -} diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index 78ae30e74e9..0743b82754b 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -20,43 +20,12 @@ try { isWorker = false; } -function normalizeQuery(query) { - // Sort, normalize leading "./", etc. - const normalizedAndSortedEntries = Array.from(query.entries()) - .map(([key, value]) => - key === 'with' ? [key, path.normalize(value)] : [key, value], - ) - .sort(([key1, val1], [key2, val2]) => { - if (key1 < key2) return -1; - if (key1 > key2) return 1; - if (val1 < val2) return -1; - if (val1 > val2) return 1; - return 0; - }); - return new URLSearchParams(normalizedAndSortedEntries); -} - export default (new Transformer({ loadConfig({config}) { return load({config}); }, async transform({asset, options, logger}) { - const normalizedQuery = normalizeQuery(asset.query); - // if query is not normalized, create new virtual asset with normalized query - // to prevent unintended asset duplication - if (asset.query.toString() !== normalizedQuery.toString()) { - console.log('need to normalize!'); - console.log({ - old: asset.query.toString(), - new: normalizedQuery.toString(), - }); - const specifier = `./${path.basename(asset.filePath)}?${normalizedQuery}`; - asset.setCode(`export * from "${specifier}";`); - asset.type = 'js'; - return [asset]; - } - const elmBinary = elmBinaryPath(); const compilerConfig = { spawn, From 200b5ab11d4d31298b5a735d572ff365e867094c Mon Sep 17 00:00:00 2001 From: ChristophP Date: Fri, 17 Jun 2022 11:39:44 +0200 Subject: [PATCH 21/25] fix linting and formatting --- packages/transformers/elm/src/ElmTransformer.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index 0743b82754b..03121254aec 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -37,11 +37,7 @@ export default (new Transformer({ }; asset.invalidateOnEnvChange('PARCEL_ELM_NO_DEBUG'); - const extraSources = resolveExtraSources({ - asset, - projectRoot: options.projectRoot, - logger, - }); + const extraSources = resolveExtraSources({asset, logger}); extraSources.forEach(filePath => { asset.invalidateOnFileChange(filePath); @@ -93,7 +89,7 @@ export default (new Transformer({ }): Transformer); // gather extra modules that should be added to the compilation process -function resolveExtraSources({asset, projectRoot, logger}) { +function resolveExtraSources({asset, logger}) { const dirname = path.dirname(asset.filePath); const relativePaths = asset.query.getAll('with'); From 89e0fee9287aee4ae74a006cbf83d22799e0b128 Mon Sep 17 00:00:00 2001 From: ChristophP Date: Fri, 17 Jun 2022 11:40:04 +0200 Subject: [PATCH 22/25] elm: add flow type annotiation --- packages/transformers/elm/src/loadConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/transformers/elm/src/loadConfig.js b/packages/transformers/elm/src/loadConfig.js index b924b189815..16de5cdd7a9 100644 --- a/packages/transformers/elm/src/loadConfig.js +++ b/packages/transformers/elm/src/loadConfig.js @@ -6,7 +6,7 @@ import ThrowableDiagnostic from '@parcel/diagnostic'; import commandExists from 'command-exists'; import nullthrows from 'nullthrows'; -async function load({config}) { +async function load({config}: {|config: Config|}) { const elmConfig = await config.getConfig(['elm.json']); if (!elmConfig) { elmBinaryPath(); // Check if elm is even installed From b79182a3bde37eda8044976227277ece67bd3cdc Mon Sep 17 00:00:00 2001 From: ChristophP Date: Fri, 17 Jun 2022 11:57:25 +0200 Subject: [PATCH 23/25] elm: fix flow types --- packages/transformers/elm/src/loadConfig.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/transformers/elm/src/loadConfig.js b/packages/transformers/elm/src/loadConfig.js index 16de5cdd7a9..645ca00e81a 100644 --- a/packages/transformers/elm/src/loadConfig.js +++ b/packages/transformers/elm/src/loadConfig.js @@ -6,7 +6,7 @@ import ThrowableDiagnostic from '@parcel/diagnostic'; import commandExists from 'command-exists'; import nullthrows from 'nullthrows'; -async function load({config}: {|config: Config|}) { +async function load({config}: {|config: Config|}): Promise { const elmConfig = await config.getConfig(['elm.json']); if (!elmConfig) { elmBinaryPath(); // Check if elm is even installed @@ -22,9 +22,7 @@ async function load({config}: {|config: Config|}) { }); } - return { - elmJson: elmConfig.contents, - }; + return null; } function elmBinaryPath(): ?string { From a74be4bdeca8df395ab7cf70ed6b47d456f8ca4d Mon Sep 17 00:00:00 2001 From: ChristophP Date: Fri, 17 Jun 2022 12:38:38 +0200 Subject: [PATCH 24/25] elm: fix integration test --- packages/transformers/elm/src/ElmTransformer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/transformers/elm/src/ElmTransformer.js b/packages/transformers/elm/src/ElmTransformer.js index 03121254aec..22cdb72295e 100644 --- a/packages/transformers/elm/src/ElmTransformer.js +++ b/packages/transformers/elm/src/ElmTransformer.js @@ -163,7 +163,7 @@ function formatMessagePiece(piece) { function elmCompileErrorToParcelDiagnostics(error) { const relativePath = path.relative(process.cwd(), error.path); - return error.problems.map(formatElmError, relativePath); + return error.problems.map(problem => formatElmError(problem, relativePath)); } function formatElmError(problem, relativePath) { From 67a350438dde644c9b1154a652ecc96ed1e9d75e Mon Sep 17 00:00:00 2001 From: ChristophP Date: Sun, 31 Jul 2022 11:05:41 +0200 Subject: [PATCH 25/25] bump terser to 5.14.2 to fix issues around hanging production build --- packages/transformers/elm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/transformers/elm/package.json b/packages/transformers/elm/package.json index 568d723a1d2..1f64a620553 100644 --- a/packages/transformers/elm/package.json +++ b/packages/transformers/elm/package.json @@ -27,7 +27,7 @@ "elm-hot": "^1.1.5", "node-elm-compiler": "^5.0.5", "nullthrows": "^1.1.1", - "terser": "^5.2.1" + "terser": "^5.14.2" }, "peerDependencies": { "elm": "^0.19.1-5"