Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
43f9b29
New injections for forked elm packages
lydell Aug 10, 2025
99c307e
Remove lamdera/containers injection
lydell Aug 10, 2025
329e5aa
Add Browser.Navigation.Key support for serialization and migration li…
lydell Aug 10, 2025
2434d1c
Make Browser.Navigation.Key work
lydell Aug 10, 2025
a41a5e6
Make the <pre> go away in `lamdera live`
lydell Aug 23, 2025
da2f7ad
As far as I understand, the code is correct, remove @TODO
lydell Aug 23, 2025
a0e1a5a
Merge branch 'lamdera-next' into lydell-upgrade-native
lydell Nov 17, 2025
147a7c0
First step towards switcheroo
lydell Dec 20, 2025
aee782d
We have to use ~/.elm/0.19.2/ for IDE support
lydell Dec 20, 2025
d634ef8
Wire in maps of package replacements
lydell Dec 20, 2025
2fd94a7
Add package replacement submodules
lydell Dec 20, 2025
6b1b76a
Add TODO comments
lydell Dec 20, 2025
e27b140
First step towards TemplateHaskell via ChatGPT
lydell Dec 21, 2025
f4406bb
No need to have separate maps for Elm and Kernel
lydell Dec 21, 2025
827678f
Parse module names
lydell Dec 22, 2025
5c66e78
Add new files to elm.cabal
lydell Dec 22, 2025
0d03884
Merge branch 'lamdera-next' into lydell-upgrade-native
lydell Dec 23, 2025
ebe8647
Update lydell/core commit
lydell Dec 23, 2025
56f6e67
First test with real replacements seems to work!
lydell Dec 23, 2025
9336eeb
Ugly code for generating the versions map
lydell Dec 23, 2025
ab308f4
Validate versions
lydell Dec 23, 2025
68d539c
Start cleaning code
lydell Dec 23, 2025
34fde80
errorHandler has moved to lydell/core#lamdera
lydell Dec 25, 2025
957e27e
Generate a versions comment
lydell Dec 25, 2025
5ad59b1
More cleanups
lydell Dec 25, 2025
865d276
Sort for stability
lydell Dec 26, 2025
570198c
Qualify imports
lydell Dec 26, 2025
12edf6b
Remove unused language extension
lydell Dec 26, 2025
c0291ba
Revert "Make Browser.Navigation.Key work"
lydell Dec 27, 2025
9ab60d4
Revert "Add Browser.Navigation.Key support for serialization and migr…
lydell Dec 27, 2025
507e65d
Remove trailing whitespace
lydell Dec 27, 2025
ea9bdf8
Update lydell/browser commit
lydell Dec 27, 2025
a46e267
Cache bust and docs
lydell Dec 27, 2025
dd91a62
Finish cleaning up Template Haskell code
lydell Dec 27, 2025
51cb67b
Restore Test.hs
lydell Dec 27, 2025
10426fa
Add missing language extension
lydell Dec 27, 2025
3a94bf2
Make sure `lamdera init` uses compatible versions
lydell Dec 29, 2025
b605d2e
Remove the word “default” from virtualDom variables
lydell Dec 29, 2025
301971c
Update lydell/virtual-dom commit
lydell Dec 29, 2025
494c2f7
Update lydell/browser commit
lydell Dec 29, 2025
d8edf90
Fix spurious plus sign in lock.txt
lydell Dec 29, 2025
cfaeda0
init does not need to know which packages to supply another version for
lydell Dec 29, 2025
328ffdf
Handle init virtual-dom version in a simpler way
lydell Dec 29, 2025
0df4105
Make it more clear that elm/virtual-dom is an indirect constraint, no…
lydell Dec 29, 2025
f442869
Merge branch 'lamdera-next' into lydell-upgrade-native
lydell Dec 31, 2025
b2f4502
Use Data.FileEmbed.bsToExp for embedding files
lydell Jan 1, 2026
c1cdf7b
This makes the REPL work again at least
lydell Jan 1, 2026
2443b54
Use Lamdera.replaceInFile instead of Perl (and use variables for file…
lydell Jan 2, 2026
487e6fa
Update extra/dist/repl-worker.js
lydell Jan 2, 2026
abd76b4
`lamdera make` HTML generation needs data-elm too
lydell Jan 2, 2026
095173c
First step towards hot reloading
lydell Jan 2, 2026
0153bf4
Only do hot reloads in freeze mode
lydell Jan 2, 2026
0ff0258
Refresh if BackendModel changed
lydell Jan 2, 2026
237627f
Refresh if FrontendModel changed
lydell Jan 2, 2026
1280ca2
OMG WE HAVE HOT RELOADING NOW
lydell Jan 2, 2026
d9e0237
Make the "FrontendModel changed!" message go away after seen
lydell Jan 2, 2026
d25dc1c
Remove outdated TODO comment
lydell Jan 2, 2026
1184ee1
const instead of var
lydell Jan 2, 2026
4120a93
Update extra/readme.md
lydell Jan 2, 2026
554e6c0
Refer to github.com/lamdera/elm-* repos
lydell Jan 2, 2026
bfce918
Update branch names in .gitmodules
lydell Jan 2, 2026
393b0f1
Fix current vs initial model in `_Lamdera_inject`
lydell Jan 3, 2026
369cacb
Update to latest elm-core commit
lydell Jan 3, 2026
c83e76d
Fix error when hot reloading with no backend model (not leader)
lydell Jan 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,19 @@
[submodule "vendor/elm-format"]
path = vendor/elm-format
url = git@github.com:lamdera/elm-format.git
[submodule "extra/package-replacements/elm/virtual-dom"]
path = extra/package-replacements/elm/virtual-dom
url = git@github.com:lamdera/elm-virtual-dom.git
branch = lamdera
[submodule "extra/package-replacements/elm/browser"]
path = extra/package-replacements/elm/browser
url = git@github.com:lamdera/elm-browser.git
branch = lamdera
[submodule "extra/package-replacements/elm/html"]
path = extra/package-replacements/elm/html
url = git@github.com:lamdera/elm-html.git
branch = lamdera
[submodule "extra/package-replacements/elm/core"]
path = extra/package-replacements/elm/core
url = git@github.com:lamdera/elm-core.git
branch = lamdera
8 changes: 6 additions & 2 deletions builder/src/Elm/Details.hs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ import qualified Stuff
import qualified Lamdera
import Lamdera ((&))
import qualified Lamdera.Extensions
import qualified Lamdera.PackageReplacements
import qualified Lamdera.Version

-- DETAILS

Expand Down Expand Up @@ -405,7 +407,7 @@ verifyDep (Env key _ _ cache manager _ _) depsMVar solution pkg details@(Solver.
then
do Reporting.report key Reporting.DCached
maybeCache <- File.readBinary (Stuff.package cache pkg vsn </> "artifacts.dat")
& Lamdera.alternativeImplementation (File.readBinary (Stuff.package cache pkg vsn </> "artifacts.x.dat"))
& Lamdera.alternativeImplementation (File.readBinary (Stuff.package cache pkg vsn </> Lamdera.Version.artifacts))
case maybeCache of
Nothing ->
build key cache depsMVar pkg details fingerprint Set.empty
Expand Down Expand Up @@ -500,7 +502,7 @@ build key cache depsMVar pkg (Solver.Details vsn _) f fs =
Just results ->
let
path = Stuff.package cache pkg vsn </> "artifacts.dat"
& Lamdera.alternativeImplementation (Stuff.package cache pkg vsn </> "artifacts.x.dat")
& Lamdera.alternativeImplementation (Stuff.package cache pkg vsn </> Lamdera.Version.artifacts)
ifaces = gatherInterfaces exposedDict results
objects = gatherObjects results
artifacts = Artifacts ifaces objects
Expand Down Expand Up @@ -622,6 +624,7 @@ crawlModule foreignDeps mvar pkg src docsStatus name =
crawlFile :: Map.Map ModuleName.Raw ForeignInterface -> MVar StatusDict -> Pkg.Name -> FilePath -> DocsStatus -> ModuleName.Raw -> FilePath -> IO (Maybe Status)
crawlFile foreignDeps mvar pkg src docsStatus expectedName path =
do bytes <- File.readUtf8 path
& Lamdera.alternativeImplementationPassthrough (Lamdera.PackageReplacements.getReplacement pkg expectedName)
case Parse.fromByteString (Parse.Package pkg) bytes of
Right modul@(Src.Module (Just (A.At _ actualName)) _ _ imports _ _ _ _ _) | expectedName == actualName ->
do deps <- crawlImports foreignDeps mvar pkg src imports
Expand Down Expand Up @@ -649,6 +652,7 @@ crawlKernel foreignDeps mvar pkg src name =
if exists
then
do bytes <- File.readUtf8 path
& Lamdera.alternativeImplementationPassthrough (Lamdera.PackageReplacements.getReplacement pkg name)
case Kernel.fromByteString pkg (Map.mapMaybe getDepHome foreignDeps) bytes of
Nothing ->
return Nothing
Expand Down
2 changes: 1 addition & 1 deletion builder/src/Elm/Outline.hs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ read root shouldCheckLamdera =
do maybeDups <- detectDuplicates root (NE.toList srcDirs)
case maybeDups of
Nothing ->
Lamdera.alternativeImplementationPassthrough (Lamdera.Checks.runChecks root shouldCheckLamdera direct) $
Lamdera.alternativeImplementationPassthrough (Lamdera.Checks.runChecks root shouldCheckLamdera direct indirect) $
return $ Right outline

Just (canonicalDir, (dir1,dir2)) ->
Expand Down
22 changes: 22 additions & 0 deletions builder/src/Reporting/Exit.hs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import qualified Reporting.Render.Code as Code
import Lamdera
import qualified Lamdera.Error
import qualified Elm.Constraint as Con
import qualified Lamdera.Version

-- RENDERERS

Expand Down Expand Up @@ -961,6 +962,8 @@ data Outline
| OutlineNoAppCore
| OutlineNoAppJson
| OutlineLamderaMissingDeps
| OutlineLamderaReplacementPackageVersionTooLow Pkg.Name V.Version V.Version
| OutlineLamderaReplacementPackageVersionTooHigh Pkg.Name V.Version V.Version


data OutlineProblem
Expand Down Expand Up @@ -1061,6 +1064,25 @@ toOutlineReport problem =
, D.reflow "Note: if you're trying to run a normal Elm app, use the elm binary instead."
]

OutlineLamderaReplacementPackageVersionTooLow name replacedVersion elmJsonVersion ->
Help.report "UNSUPPORTED VERSION" (Just "elm.json")
("This version of the Lamdera compiler supports the following range for \"" <> Pkg.toChars name <> "\":")
[ D.indent 4 $ D.green $ "\"" <> D.fromVersion (Lamdera.Version.resetPatch replacedVersion) <> " <= v <= " <> D.fromVersion replacedVersion <> "\""
, D.reflow "But your elm.json contains:"
, D.indent 4 $ D.red $ "\"" <> D.fromPackage name <> "\": \"" <> D.fromVersion elmJsonVersion <> "\""
, D.reflow "You need to update that package!"
]

OutlineLamderaReplacementPackageVersionTooHigh name replacedVersion elmJsonVersion ->
Help.report "UNSUPPORTED VERSION" (Just "elm.json")
("This version of the Lamdera compiler supports the following range for \"" <> Pkg.toChars name <> "\":")
[ D.indent 4 $ D.green $ "\"" <> D.fromVersion (Lamdera.Version.resetPatch replacedVersion) <> " <= v <= " <> D.fromVersion replacedVersion <> "\""
, D.reflow "But your elm.json contains:"
, D.indent 4 $ D.red $ "\"" <> D.fromPackage name <> "\": \"" <> D.fromVersion elmJsonVersion <> "\""
, D.reflow "You need to update the Lamdera compiler. And if there is no later version, ask the Lamdera community to release a new version!"
, D.reflow "You can also downgrade that package for now."
]


toOutlineProblemReport :: FilePath -> Code.Source -> Json.Context -> A.Region -> OutlineProblem -> Help.Report
toOutlineProblemReport path source _ region problem =
Expand Down
2 changes: 2 additions & 0 deletions builder/src/Stuff.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ import qualified Elm.Version as V

import Lamdera ((&))
import qualified Lamdera
import qualified Lamdera.Version

-- PATHS


stuff :: FilePath -> FilePath
stuff root =
root </> "elm-stuff" </> compilerVersion
& Lamdera.alternativeImplementation (root </> "elm-stuff" </> Lamdera.Version.medium)


details :: FilePath -> FilePath
Expand Down
1 change: 1 addition & 0 deletions compiler/src/Elm/Package.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module Elm.Package
, lamderaContainers
, time
, bytes
, toName
)
where

Expand Down
6 changes: 4 additions & 2 deletions compiler/src/Generate/Html.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ sandwich root moduleName javascript =

<body>

<pre id="elm"></pre>
<pre data-elm id="elm"></pre>

<script>
try {
Expand Down Expand Up @@ -84,11 +84,13 @@ sandwich_ root moduleName javascript =

<body>

<pre id="elm"></pre>
<pre data-elm id="elm"></pre>

<script>
try {
// lamdera-elm-js-start
|] <> javascript <> [r|
// lamdera-elm-js-end
|] <> Lamdera.Live.lamderaLiveSrc <> Lamdera.UiSourceMap.src <> [r|
setupApp("|] <> name <> [r|", "elm")
}
Expand Down
1 change: 1 addition & 0 deletions compiler/src/Generate/JavaScript.hs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ generate mode (Opt.GlobalGraph graph_ _) mains =
graph = Lamdera.Injection.graphModifications mode mains graph_
state = Map.foldrWithKey (addMain mode graph) emptyState mains
in
Lamdera.Injection.versionsComment <>
"(function(scope){\n'use strict';"
<> Functions.functions
-- <> perfNote mode -- @NOTE given user never manages JS generation in Lamdera, hide the perf note
Expand Down
2 changes: 2 additions & 0 deletions elm.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ Executable lamdera
Lamdera.Make
Lamdera.Nitpick.DebugLog
Lamdera.Offline
Lamdera.PackageReplacements
Lamdera.PackageReplacementsTH
Lamdera.PostCompile
Lamdera.Project
Lamdera.Relative
Expand Down
3 changes: 1 addition & 2 deletions extra/Lamdera/CLI/Reset.hs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ run () () = do
progress $ "Removing artifacts in " <> elmHome
let packageDir = elmHome </> Lamdera.Version.elm </> "packages"
onlyWhen_ (doesDirectoryExist packageDir) $ do
callCommand $ "find " <> packageDir <> " | grep artifacts.dat | xargs rm -r"
callCommand $ "find " <> packageDir <> " | grep artifacts.x.dat | xargs rm -r"
callCommand $ "find " <> packageDir <> " | grep 'artifacts.*\\.dat' | xargs rm -r"
else do
nukeDir elmHome

Expand Down
67 changes: 57 additions & 10 deletions extra/Lamdera/Checks.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,26 @@ import Lamdera
import Lamdera.Progress
import qualified Lamdera.Init
import qualified Ext.Common
import qualified Lamdera.PackageReplacements as PackageReplacements
import Data.Foldable (traverse_)


runChecks :: FilePath -> Bool -> Map.Map Pkg.Name V.Version -> IO (Either Exit.Outline outline) -> IO (Either Exit.Outline outline)
runChecks root shouldCheckLamdera direct default_ = do
runChecks :: FilePath -> Bool -> Map.Map Pkg.Name V.Version -> Map.Map Pkg.Name V.Version -> IO (Either Exit.Outline outline) -> IO (Either Exit.Outline outline)
runChecks root shouldCheckLamdera direct indirect default_ = do
-- atomicPutStrLn $ "runchecks but with " <> show shouldCheckLamdera
if Map.member Pkg.lamderaCore direct
then do
onlyWhen shouldCheckLamdera (Lamdera.Checks.runChecks_ root)
default_
else
if shouldCheckLamdera
then return $ Left Exit.OutlineLamderaMissingDeps
else default_
case checkPackageReplacementsVersions (Map.union direct indirect) of
Left err ->
return $ Left err

Right () ->
if Map.member Pkg.lamderaCore direct
then do
onlyWhen shouldCheckLamdera (Lamdera.Checks.runChecks_ root)
default_
else
if shouldCheckLamdera
then return $ Left Exit.OutlineLamderaMissingDeps
else default_


runChecks_ :: FilePath -> IO ()
Expand Down Expand Up @@ -144,3 +151,43 @@ checkMsgHasTypes typeNames = do
results = fmap (\search -> T.isInfixOf ("type " <> search) source) typeNames

pure $ Prelude.all ((==) True) results

checkPackageReplacementsVersions :: Map.Map Pkg.Name V.Version -> Either Exit.Outline ()
checkPackageReplacementsVersions allDeps =
traverse_ (checkPackageReplacementVersion allDeps) (Map.toList PackageReplacements.versions)

checkPackageReplacementVersion :: Map.Map Pkg.Name V.Version -> ( Pkg.Name, ( V.Version, String ) ) -> Either Exit.Outline ()
checkPackageReplacementVersion allDeps ( name, ( replacedVersion@(V.Version replacedMajor replacedMinor replacedPatch), _ ) ) =
case Map.lookup name allDeps of
Nothing ->
Right ()

Just elmJsonVersion@(V.Version elmJsonMajor elmJsonMinor elmJsonPatch) ->
-- 🤷 This can’t happen. Only 1.x versions exists of all elm/* packages we replace. But we code it to be a hard error.
if elmJsonMajor < replacedMajor then
Left (Exit.OutlineLamderaReplacementPackageVersionTooLow name replacedVersion elmJsonVersion)

-- ❌ It’s very unlikely that Evan will suddenly release 2.x of some package. But if that happens, this should be a hard error.
else if elmJsonMajor > replacedMajor then
Left (Exit.OutlineLamderaReplacementPackageVersionTooHigh name replacedVersion elmJsonVersion)

-- 🤷 This can’t happen. Only 1.0.x versions exists of all elm/* packages we replace. But we code it to be a hard error.
else if elmJsonMinor < replacedMinor then
Left (Exit.OutlineLamderaReplacementPackageVersionTooLow name replacedVersion elmJsonVersion)

-- ❌ It’s unlikely that Evan will suddenly release 1.1.x of some package. But if that happens, this should be a hard error.
else if elmJsonMinor > replacedMinor then
Left (Exit.OutlineLamderaReplacementPackageVersionTooHigh name replacedVersion elmJsonVersion)

-- ✅ This is very likely to happen. Lots of people probably have "elm/virtual-dom": "1.0.3" in their elm.json, and haven’t bothered updating to the more recent 1.0.4 version. If we made this a hard error, it would be annoying for lots of people. It’s better to simply allow the fork patch version to be greater than specified.
else if elmJsonPatch < replacedPatch then
Right ()

-- 🚨 This is somewhat likely. As mentioned, elm/virtual-dom 1.0.4 was released, and a little bit later 1.0.5 was released with a security fix. If a user tries to put "elm/virtual-dom": "1.0.5" in their elm.json, I should be a hard error, informing them that you can’t go above 1.0.4 with this release of the Lamdera compiler. (Silently using 1.0.4 anyway would be misleading, leading to a false sense of security.) They need to wait for a new Lamdera compiler version that has pulled in the security fix. (This is an example – the Lamdera compiler did support the latest version (1.0.5) at the time of writing.)
else if elmJsonPatch > replacedPatch then
Left (Exit.OutlineLamderaReplacementPackageVersionTooHigh name replacedVersion elmJsonVersion)

-- The version matches exactly.
else
Right ()

Loading