From 5c0477cc4811d8637c5910fad91bc83bc3291b43 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 25 Feb 2025 17:11:56 -0500 Subject: [PATCH 01/36] ensure obelisk-asset-th-generate makes name based on source static dir --- lib/asset/manifest/src-bin/static-th.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/asset/manifest/src-bin/static-th.hs b/lib/asset/manifest/src-bin/static-th.hs index e04f1284b..1163b6c49 100644 --- a/lib/asset/manifest/src-bin/static-th.hs +++ b/lib/asset/manifest/src-bin/static-th.hs @@ -33,7 +33,7 @@ main = do , "static, staticFilePath :: FilePath -> Q Exp" , "#ifdef OBELISK_ASSET_PASSTHRU" , "static = staticAssetRaw" - , "staticFilePath = staticAssetFilePathRaw \"static.out\"" + , "staticFilePath = staticAssetFilePathRaw \"" <> (takeFileName root) <>".out\"" , "#else" , "static = staticAssetHashed " <> show root , "staticFilePath = staticAssetFilePath " <> show root From 5554cdd3f58e43b2fae18f63da621d25d6684072 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 25 Feb 2025 17:13:55 -0500 Subject: [PATCH 02/36] make static.out a String constant --- lib/command/src/Obelisk/Command/Project.hs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/command/src/Obelisk/Command/Project.hs b/lib/command/src/Obelisk/Command/Project.hs index 24ece8fc7..21b367152 100644 --- a/lib/command/src/Obelisk/Command/Project.hs +++ b/lib/command/src/Obelisk/Command/Project.hs @@ -76,6 +76,9 @@ import Obelisk.Command.Utils (nixBuildExePath, nixExePath, toNixPath, cp, nixShe --TODO: Make this module resilient to random exceptions + +static_Out = "static.out" + --TODO: Don't hardcode this -- | Source for the Obelisk project obeliskSource :: ThunkSource @@ -413,12 +416,12 @@ findProjectAssets root = do _ <- buildStaticFilesDerivationAndSymlink (readProcessAndLogStderr Debug) root - pure (AssetSource_Derivation, T.pack $ root "static.out") + pure (AssetSource_Derivation, T.pack $ root static_Out) else fmap (AssetSource_Files,) $ do path <- readProcessAndLogStderr Debug $ setCwd (Just root) $ proc nixExePath ["eval", "-f", ".", "passthru.staticFilesImpure", "--raw"] _ <- readProcessAndLogStderr Debug $ setCwd (Just root) $ - proc lnPath ["-sfT", T.unpack path, "./static.out"] + proc lnPath ["-sfT", T.unpack path, static_Out] pure path -- | Get the nix store path to the generated static asset manifest module (e.g., "obelisk-generated-static") @@ -477,7 +480,7 @@ watchStaticFilesDerivation root = do $ liftIO . runObelisk ob . putLog Debug - . ("Regenerating static.out due to file changes: "<>) + . (("Regenerating " <> T.pack static_Out <> " due to file changes: ") <>) . T.intercalate ", " . Set.toList . Set.fromList @@ -491,7 +494,7 @@ watchStaticFilesDerivation root = do buildStaticCatchErrors >>= \case Nothing -> pure () Just n -> do - putLog Notice $ "Static assets built and symlinked to static.out" + putLog Notice $ "Static assets built and symlinked to " <> T.pack static_Out putLog Debug $ "Generated static asset nix path: " <> n pure never where @@ -523,7 +526,7 @@ buildStaticFilesDerivationAndSymlink f root = f $ setCwd (Just root) $ ProcessSpec { _processSpec_createProcess = Proc.proc nixBuildExePath - [ "-o", "static.out" + [ "-o", (last $ splitPath root) <> ".out" --static_Out , "-E", "(import ./. {}).passthru.staticFilesImpure" ] , _processSpec_overrideEnv = Nothing From 589f62d5c1bc67dbf6d878241e3e40ba9ab8b854 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 25 Feb 2025 20:39:34 -0500 Subject: [PATCH 03/36] findProjectAssets returns Map of isDrv by path --- lib/command/src/Obelisk/Command/Project.hs | 44 +++++++++++----------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/lib/command/src/Obelisk/Command/Project.hs b/lib/command/src/Obelisk/Command/Project.hs index 21b367152..cdb2fdc80 100644 --- a/lib/command/src/Obelisk/Command/Project.hs +++ b/lib/command/src/Obelisk/Command/Project.hs @@ -42,7 +42,7 @@ import qualified Data.ByteString.Lazy as BSL import Data.Default (def) import qualified Data.Foldable as F (toList) import Data.Function ((&), on) -import Data.Map (Map) +import qualified Data.Map as Map (Map, toList, fromList) import qualified Data.Set as Set import Data.Text (Text) import qualified Data.Text as T @@ -343,7 +343,7 @@ mkObNixShellProc => FilePath -- ^ Path to project root -> Bool -- ^ Should this be a pure shell? -> Bool -- ^ Should we chdir to the package root in the shell? - -> Map Text FilePath -- ^ Package names mapped to their paths + -> Map.Map Text FilePath -- ^ Package names mapped to their paths -> String -- ^ Shell attribute to use (e.g. @"ghc"@, @"ghcjs"@, etc.) -> Maybe String -- ^ If 'Just' run the given command; otherwise just open the interactive shell -> m ProcessSpec @@ -367,7 +367,7 @@ nixShellWithoutPkgs => FilePath -- ^ Path to project root -> Bool -- ^ Should this be a pure shell? -> Bool -- ^ Should we chdir to the package root in the shell? - -> Map Text FilePath -- ^ Package names mapped to their paths + -> Map.Map Text FilePath -- ^ Package names mapped to their paths -> String -- ^ Shell attribute to use (e.g. @"ghc"@, @"ghcjs"@, etc.) -> Maybe String -- ^ If 'Just' run the given command; otherwise just open the interactive shell -> m () @@ -398,31 +398,33 @@ describeImpureAssetSource src path = case src of -- | Determine where the static files of a project are and whether they're plain files or a derivation. -- If they are a derivation, that derivation will be built. -findProjectAssets :: MonadObelisk m => FilePath -> m (AssetSource, Text) +findProjectAssets :: MonadObelisk m => FilePath -> m (Map.Map Text AssetSource) --(AssetSource, Text) findProjectAssets root = do isDerivation <- readProcessAndLogStderr Debug $ setCwd (Just root) $ proc nixExePath [ "eval" , "--impure" , "--expr" - , "(let a = import ./. {}; in toString (a.reflex.nixpkgs.lib.isDerivation a.passthru.staticFilesImpure))" - , "--raw" - -- `--raw` is not available with old nix-instantiate. It drops quotation - -- marks and trailing newline, so is very convenient for shelling out. + , "(let a = import ./. {}; in builtins.mapAttrs (name: value: toString (a.reflex.nixpkgs.lib.isDerivation value) ) a.passthru.staticFilesImpure)" + , "--json" ] - -- Check whether the impure static files are a derivation (and so must be built) - if isDerivation == "1" - then do - _ <- buildStaticFilesDerivationAndSymlink - (readProcessAndLogStderr Debug) - root - pure (AssetSource_Derivation, T.pack $ root static_Out) - else fmap (AssetSource_Files,) $ do - path <- readProcessAndLogStderr Debug $ setCwd (Just root) $ - proc nixExePath ["eval", "-f", ".", "passthru.staticFilesImpure", "--raw"] - _ <- readProcessAndLogStderr Debug $ setCwd (Just root) $ - proc lnPath ["-sfT", T.unpack path, static_Out] - pure path + case Json.eitherDecode . BSL.fromStrict . encodeUtf8 $ isDerivation of + Left _ -> undefined -- what does this mean? + Right (areDrvs :: Map.Map Text Text) -> do + let asList = Map.toList areDrvs + fmap Map.fromList $ forM asList $ \(key, isDrv) -> do + if isDerivation == "1" + then do + _ <- buildStaticFilesDerivationAndSymlink + (readProcessAndLogStderr Debug) + root + pure (T.pack $ root static_Out, AssetSource_Derivation) + else fmap (,AssetSource_Files) $ do + path <- readProcessAndLogStderr Debug $ setCwd (Just root) $ + proc nixExePath ["eval", "-f", ".", "passthru.staticFilesImpure.", T.unpack key, "--raw"] + _ <- readProcessAndLogStderr Debug $ setCwd (Just root) $ + proc lnPath ["-sfT", T.unpack path, static_Out] + pure path -- | Get the nix store path to the generated static asset manifest module (e.g., "obelisk-generated-static") getHaskellManifestProjectPath :: MonadObelisk m => FilePath -> m Text From a4d20ebaac6696b6b366ef7955e042ee6159df5e Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Wed, 26 Feb 2025 21:37:55 -0500 Subject: [PATCH 04/36] add way to recover packageName arg of processAssets --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 29fd2126f..cd74b5a76 100644 --- a/default.nix +++ b/default.nix @@ -77,7 +77,7 @@ in rec { touch "$out" mkdir -p "$symlinked" ${exe} "$src" "$haskellManifest" ${packageName} ${moduleName} "$symlinked" - ''; + '' // {inherit packageName;}; compressedJs = frontend: optimizationLevel: externs: pkgs.runCommand "compressedJs" {} '' set -euo pipefail From e58a489f5907807a45362dd53d601789f0643e0c Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Wed, 26 Feb 2025 21:40:15 -0500 Subject: [PATCH 05/36] make staticFilesImpure and processedStatic attr sets of each static dir --- default.nix | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/default.nix b/default.nix index cd74b5a76..d055a00d8 100644 --- a/default.nix +++ b/default.nix @@ -270,20 +270,34 @@ in rec { inherit args; userSettings = { inherit android ios packages overrides tools shellToolOverrides withHoogle externjs __closureCompilerOptimizationLevel __withGhcide __deprecated; - staticFiles = if staticFiles == null then self.base + /static else staticFiles; + staticFiles = + if staticFiles == null + then { static = { path = self.base + /static; isDrv = false; drvArgs = null; moduleName = "Obelisk.Generated.Static"; }; } + else staticFiles; }; frontendName = "frontend"; backendName = "backend"; commonName = "common"; - staticName = "obelisk-generated-static"; - staticFilesImpure = let fs = self.userSettings.staticFiles; in if lib.isDerivation fs then fs else toString fs; - processedStatic = processAssets { - src = self.userSettings.staticFiles; - exe = if lib.attrByPath ["userSettings" "__deprecated" "useObeliskAssetManifestGenerate"] false self - then builtins.trace "obelisk-asset-manifest-generate is deprecated. Use obelisk-asset-th-generate instead." "obelisk-asset-manifest-generate" - else "obelisk-asset-th-generate"; - }; - # The packages whose names and roles are defined by this package + #staticName = "obelisk-generated-static"; + staticFilesImpure = + let fs = self.userSettings.staticFiles; + in lib.mapAttrs (_: staticArgs: + if staticArgs.isDrv + then { path = staticArgs.path; src = import staticArgs.src staticArgs.drvArgs; } + else { path = staticArgs.path; src = toString staticArgs.path; } + ) fs; + processedStatic = + let processAssets' = { path, drvArgs, isDrv, packageName ? "obelisk-generated-static", moduleName ? "Obelisk.Generated.Static" }@staticDrvArgs: processAssets { + src = if isDrv then (import path drvArgs) else path; + packageName = packageName; + moduleName = moduleName; + #moduleName + exe = if lib.attrByPath ["userSettings" "__deprecated" "useObeliskAssetManifestGenerate"] false self + then builtins.trace "obelisk-asset-manifest-generate is deprecated. Use obelisk-asset-th-generate instead." "obelisk-asset-manifest-generate" + else "obelisk-asset-th-generate"; + }; + in + lib.mapAttrs (name: staticArgs: processAssets' (staticArgs // { packageName = name; } )) self.userSettings.staticFiles; predefinedPackages = lib.filterAttrs (_: x: x != null) { ${self.frontendName} = nullIfAbsent (self.base + "/frontend"); ${self.commonName} = nullIfAbsent (self.base + "/common"); @@ -291,10 +305,12 @@ in rec { }; shellPackages = {}; combinedPackages = self.predefinedPackages // self.userSettings.packages // self.shellPackages; - projectOverrides = self': super': { - ${self.staticName} = haskellLib.dontHaddock (self'.callCabal2nix self.staticName self.processedStatic.haskellManifest {}); + projectOverrides = self': super': ({ ${self.backendName} = haskellLib.addBuildDepend super'.${self.backendName} self'.obelisk-run; - }; + } // ( + # unique name | <<- unique packageName <<- unique module name, in order to depend on all of them together in one pkgset + lib.mapAttrs (pkgName: assets: self'.callCabal2nix pkgName assets.haskellManifest {}) self.processedStatic + )); totalOverrides = lib.composeExtensions self.projectOverrides self.userSettings.overrides; privateConfigDirs = ["config/backend"]; injectableConfig = builtins.filterSource (path: _: From 63efb3a39a5a03e1494163b7d3fb48b812af5832 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Thu, 27 Feb 2025 20:42:14 -0500 Subject: [PATCH 06/36] use path attr instead of src --- default.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/default.nix b/default.nix index d055a00d8..fe5b97429 100644 --- a/default.nix +++ b/default.nix @@ -282,8 +282,9 @@ in rec { staticFilesImpure = let fs = self.userSettings.staticFiles; in lib.mapAttrs (_: staticArgs: + # path attr just allows us to watch for file changes if staticArgs.isDrv - then { path = staticArgs.path; src = import staticArgs.src staticArgs.drvArgs; } + then { path = staticArgs.path; src = import staticArgs.path staticArgs.drvArgs; } else { path = staticArgs.path; src = toString staticArgs.path; } ) fs; processedStatic = @@ -298,6 +299,12 @@ in rec { }; in lib.mapAttrs (name: staticArgs: processAssets' (staticArgs // { packageName = name; } )) self.userSettings.staticFiles; + # lib.mapAttrs (_: staticArgs: + # if staticArgs.isDrv + # then processAssets' (import staticArgs.path staticArgs.args) + # else processAssets' staticArgs.path + # ) self.userSettings.staticFiles; + # The packages whose names and roles are defined by this package predefinedPackages = lib.filterAttrs (_: x: x != null) { ${self.frontendName} = nullIfAbsent (self.base + "/frontend"); ${self.commonName} = nullIfAbsent (self.base + "/common"); From 0f328772a00bcb078b39fa0e3dc33ac52ef54645 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Thu, 27 Feb 2025 20:50:45 -0500 Subject: [PATCH 07/36] findProjectAssets returns StaticInfos --- lib/command/src/Obelisk/Command/Project.hs | 66 +++++++++++++++------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/lib/command/src/Obelisk/Command/Project.hs b/lib/command/src/Obelisk/Command/Project.hs index cdb2fdc80..dd3511751 100644 --- a/lib/command/src/Obelisk/Command/Project.hs +++ b/lib/command/src/Obelisk/Command/Project.hs @@ -22,8 +22,9 @@ module Obelisk.Command.Project , withProjectRoot , bashEscape , shEscape - , getHaskellManifestProjectPath + , getStaticHaskellManifestProjectPaths , AssetSource(..) + , StaticInfo(..) , describeImpureAssetSource , watchStaticFilesDerivation ) where @@ -44,6 +45,7 @@ import qualified Data.Foldable as F (toList) import Data.Function ((&), on) import qualified Data.Map as Map (Map, toList, fromList) import qualified Data.Set as Set +import qualified Data.List as List import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8, encodeUtf8) @@ -77,7 +79,13 @@ import Obelisk.Command.Utils (nixBuildExePath, nixExePath, toNixPath, cp, nixShe --TODO: Make this module resilient to random exceptions -static_Out = "static.out" +static_out :: FilePath +static_out = "static.out" + +-- | Common constant used for symlinked static drv +dotOut :: FilePath +dotOut = ".dot" + --TODO: Don't hardcode this -- | Source for the Obelisk project @@ -390,6 +398,23 @@ data AssetSource = AssetSource_Derivation | AssetSource_Files deriving (Eq) +data StaticInfo = StaticInfo + { _staticInfo_name :: T.Text + , _staticInfo_assetSource :: AssetSource + , _staticInfo_path :: FilePath + } + +instance Json.FromJSON StaticInfo where + parseJSON = Json.withObject "StaticInfo" $ \o -> do + name <- o Json..: "staticName" + drvBool <- o Json..: "isDrv" + path <- o Json..: "staticPath" + return $ StaticInfo + { _staticInfo_name = name + , _staticInfo_assetSource = if drvBool then AssetSource_Derivation else AssetSource_Files + , _staticInfo_path = last $ splitDirectories path + } + -- | Some log messages to make it easier to tell where static files are coming from describeImpureAssetSource :: AssetSource -> Text -> Text describeImpureAssetSource src path = case src of @@ -398,42 +423,41 @@ describeImpureAssetSource src path = case src of -- | Determine where the static files of a project are and whether they're plain files or a derivation. -- If they are a derivation, that derivation will be built. -findProjectAssets :: MonadObelisk m => FilePath -> m (Map.Map Text AssetSource) --(AssetSource, Text) +findProjectAssets :: MonadObelisk m => FilePath -> m [StaticInfo] findProjectAssets root = do isDerivation <- readProcessAndLogStderr Debug $ setCwd (Just root) $ proc nixExePath [ "eval" , "--impure" , "--expr" - , "(let a = import ./. {}; in builtins.mapAttrs (name: value: toString (a.reflex.nixpkgs.lib.isDerivation value) ) a.passthru.staticFilesImpure)" + , "(let a = import ./. {}; in builtins.attrValues (builtins.mapAttrs (n: value: {staticName=n;isDrv = a.reflex.nixpkgs.lib.isDerivation value.src; staticPath = value.path;} ) a.passthru.staticFilesImpure))" , "--json" ] case Json.eitherDecode . BSL.fromStrict . encodeUtf8 $ isDerivation of - Left _ -> undefined -- what does this mean? - Right (areDrvs :: Map.Map Text Text) -> do - let asList = Map.toList areDrvs - fmap Map.fromList $ forM asList $ \(key, isDrv) -> do - if isDerivation == "1" + Left _ -> throwError "Unable to get StaticInfo" + Right (statics :: [StaticInfo]) -> do + -- Build symlink path at .out + forM_ statics $ \staticInfo -> do + if _staticInfo_assetSource staticInfo == AssetSource_Derivation then do - _ <- buildStaticFilesDerivationAndSymlink + void $ buildStaticFilesDerivationAndSymlink (readProcessAndLogStderr Debug) root - pure (T.pack $ root static_Out, AssetSource_Derivation) - else fmap (,AssetSource_Files) $ do - path <- readProcessAndLogStderr Debug $ setCwd (Just root) $ - proc nixExePath ["eval", "-f", ".", "passthru.staticFilesImpure.", T.unpack key, "--raw"] - _ <- readProcessAndLogStderr Debug $ setCwd (Just root) $ - proc lnPath ["-sfT", T.unpack path, static_Out] - pure path + (_staticInfo_name staticInfo) + else do + void $ readProcessAndLogStderr Debug $ setCwd (Just root) $ + proc lnPath ["-sfT", (_staticInfo_path staticInfo), T.unpack (_staticInfo_name staticInfo) <> dotOut] + pure statics -- | Get the nix store path to the generated static asset manifest module (e.g., "obelisk-generated-static") -getHaskellManifestProjectPath :: MonadObelisk m => FilePath -> m Text -getHaskellManifestProjectPath root = fmap T.strip $ readProcessAndLogStderr Debug $ setCwd (Just root) $ - proc nixBuildExePath +getStaticHaskellManifestProjectPaths :: MonadObelisk m => FilePath -> m [Text] +getStaticHaskellManifestProjectPaths root = do + stdout <- readProcessAndLogStderr Debug $ setCwd (Just root) $ proc nixBuildExePath [ "--no-out-link" , "-E" - , "(let a = import ./. {}; in a.passthru.processedStatic.haskellManifest)" + , "(let a = import ./. {}; in builtins.mapAttrs (_: x: x.haskellManifest) d.passthru.processedStatic)" ] + pure $ T.strip <$> T.lines stdout -- | Watch the common, backend, frontend, and static directories for file -- changes and check whether those file changes cause changes in the static From bbe9bcc713f2d1817f8ffa4ee4801f6b238b0af8 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Thu, 27 Feb 2025 20:51:47 -0500 Subject: [PATCH 08/36] watch multiple static dirs for file changes --- lib/command/src/Obelisk/Command/Project.hs | 41 +++++++++++++--------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/lib/command/src/Obelisk/Command/Project.hs b/lib/command/src/Obelisk/Command/Project.hs index dd3511751..0a99018fe 100644 --- a/lib/command/src/Obelisk/Command/Project.hs +++ b/lib/command/src/Obelisk/Command/Project.hs @@ -465,8 +465,11 @@ getStaticHaskellManifestProjectPaths root = do watchStaticFilesDerivation :: (MonadIO m, MonadObelisk m) => FilePath + -- ^ root folder + -> [StaticInfo] + -- ^ which static folder are we watching -> m () -watchStaticFilesDerivation root = do +watchStaticFilesDerivation root statics = do ob <- getObelisk liftIO $ runHeadlessApp $ do pb <- getPostBuild @@ -496,17 +499,18 @@ watchStaticFilesDerivation root = do else WatchModeOS } watch' pkg = fmap (:[]) <$> watchDirectoryTree cfg (root pkg <$ pb) (filterEvents . eventPath) + -- TODO: similar to previous todo, we should check if frontend and backend depend on this particular static package + -- eg. if this static package is only needed by backend rebuild <- batchOccurrences 0.25 =<< mergeWith (<>) <$> mapM watch' - [ "frontend" + ([ "frontend" , "backend" , "common" - , "static" - ] + ] <> (_staticInfo_path <$> statics)) performEvent_ $ liftIO . runObelisk ob . putLog Debug - . (("Regenerating " <> T.pack static_Out <> " due to file changes: ") <>) + . (("Regenerating static due to file changes: ") <>) . T.intercalate ", " . Set.toList . Set.fromList @@ -517,43 +521,48 @@ watchStaticFilesDerivation root = do void $ flip throttleBatchWithLag rebuild $ \e -> performEvent $ ffor e $ \_ -> liftIO $ runObelisk ob $ do putLog Notice "Static assets being built..." - buildStaticCatchErrors >>= \case + sequenceA <$> traverse buildStaticCatchErrors (_staticInfo_name <$> statics) >>= \case Nothing -> pure () - Just n -> do - putLog Notice $ "Static assets built and symlinked to " <> T.pack static_Out - putLog Debug $ "Generated static asset nix path: " <> n + Just ns -> forM_ ns $ \n -> do + putLog Notice $ "Static assets built and symlinked to " + <> (maybe "static.out" ((<>) ".out" . _staticInfo_name) $ (List.find ((== drvNameFromPath n) . _staticInfo_name) statics)) + putLog Debug $ "Generated static asset nix path: " <> T.pack n pure never where + drvNameFromPath = T.pack . drop 1 . dropWhile (/= '-') . last . splitDirectories handleBuildFailure :: MonadObelisk m => (ExitCode, String, String) - -> m (Maybe Text) + -> m (Maybe FilePath) handleBuildFailure (ex, out, err) = case ex of ExitSuccess -> let out' = T.strip $ T.pack out - in pure $ if T.null out' then Nothing else Just out' + in pure $ if T.null out' then Nothing else Just $ T.unpack out' _ -> do putLog Error $ ("Static assets build failed: " <>) $ T.unlines $ reverse $ take 20 $ reverse $ T.lines $ T.pack err pure Nothing - buildStaticCatchErrors :: MonadObelisk m => m (Maybe Text) - buildStaticCatchErrors = handleBuildFailure =<< + --buildStaticsCatchErrors staticAttrs = traverse buildStaticCatchErrors staticAttrs + buildStaticCatchErrors :: MonadObelisk m => Text -> m (Maybe FilePath) + buildStaticCatchErrors staticA = handleBuildFailure =<< buildStaticFilesDerivationAndSymlink readCreateProcessWithExitCode root + staticA buildStaticFilesDerivationAndSymlink :: MonadObelisk m => (ProcessSpec -> m a) -> FilePath + -> Text -> m a -buildStaticFilesDerivationAndSymlink f root = f $ +buildStaticFilesDerivationAndSymlink f root staticName = f $ setCwd (Just root) $ ProcessSpec { _processSpec_createProcess = Proc.proc nixBuildExePath - [ "-o", (last $ splitPath root) <> ".out" --static_Out - , "-E", "(import ./. {}).passthru.staticFilesImpure" + [ "-o", T.unpack staticName <> dotOut + , "-E", "(import ./. {}).passthru.staticFilesImpure." <> T.unpack staticName <> ".src" ] , _processSpec_overrideEnv = Nothing } From 080b7db5e5ada73dbf315508a5b00959ff25fed8 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Mon, 3 Mar 2025 12:03:33 -0500 Subject: [PATCH 09/36] update obelisk-asset-th-generate to differentiate filepaths by static attribute name --- lib/asset/manifest/src-bin/static-th.hs | 10 +++--- lib/asset/manifest/src/Obelisk/Asset/TH.hs | 36 +++++++++++++--------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/lib/asset/manifest/src-bin/static-th.hs b/lib/asset/manifest/src-bin/static-th.hs index 1163b6c49..95bd245b1 100644 --- a/lib/asset/manifest/src-bin/static-th.hs +++ b/lib/asset/manifest/src-bin/static-th.hs @@ -8,7 +8,7 @@ import System.FilePath main :: IO () main = do --TODO: Usage - [root, haskellTarget, packageName, moduleName, fileTarget] <- getArgs + [root, haskellTarget, packageName, moduleName, fileTarget, staticAttrName] <- getArgs paths <- gatherHashedPaths root writeCabalProject haskellTarget $ SimplePkg { _simplePkg_name = T.pack packageName @@ -32,11 +32,11 @@ main = do , "" , "static, staticFilePath :: FilePath -> Q Exp" , "#ifdef OBELISK_ASSET_PASSTHRU" - , "static = staticAssetRaw" - , "staticFilePath = staticAssetFilePathRaw \"" <> (takeFileName root) <>".out\"" + , "static = staticAssetRaw" <> " " <> show staticAttrName + , "staticFilePath = staticAssetFilePathRaw \"static.out\"" <> " " <> show staticAttrName , "#else" - , "static = staticAssetHashed " <> show root - , "staticFilePath = staticAssetFilePath " <> show root + , "static = staticAssetHashed " <> show root <> " " <> show staticAttrName + , "staticFilePath = staticAssetFilePath " <> show root <> " " <> show staticAttrName , "#endif" ] } diff --git a/lib/asset/manifest/src/Obelisk/Asset/TH.hs b/lib/asset/manifest/src/Obelisk/Asset/TH.hs index 9de64a3b2..c48a76aef 100644 --- a/lib/asset/manifest/src/Obelisk/Asset/TH.hs +++ b/lib/asset/manifest/src/Obelisk/Asset/TH.hs @@ -41,12 +41,14 @@ staticOutPath = "static.out" -- -- If the filepath can not be found in the static output directory, -- this will throw a compile-time error. -staticAssetRaw :: FilePath -> Q Exp -staticAssetRaw = staticAssetWorker staticPrefix staticOutPath +staticAssetRaw :: FilePath -> FilePath -> Q Exp +staticAssetRaw staticName fp = staticAssetWorker staticPrefix staticOutPath staticName fp -staticAssetHashed :: FilePath -> FilePath -> Q Exp -staticAssetHashed root fp = do - LitE . StringL . (staticPrefix ) <$> hashedAssetFilePath root fp +-- | Generate URL to reference handler which will serve this asset path +-- | where "/static" route maps to the base directory static.assets +staticAssetHashed :: FilePath -> FilePath -> FilePath -> Q Exp +staticAssetHashed root staticPkgName fp = do + LitE . StringL . (\p -> staticPrefix staticPkgName p) <$> hashedAssetFilePath root fp -- | Embed a filepath via template haskell. Differently to 'staticAssetRaw' -- this points to a local filepath instead of an URL during deployment. @@ -57,13 +59,16 @@ staticAssetFilePathRaw :: FilePath -- ^ Add this prefix directory to the embedded filepath @fp@. -> FilePath + -- ^ Static Project specific prefix to avoid collisions + -> FilePath -- ^ Filepath you want to embed. -> Q Exp -staticAssetFilePathRaw root = staticAssetWorker root staticOutPath +staticAssetFilePathRaw root staticName = staticAssetWorker root staticOutPath staticName -staticAssetFilePath :: FilePath -> FilePath -> Q Exp -staticAssetFilePath root relativePath = do - let fullPath = root relativePath +-- | Return the real location of 'relativePath' +staticAssetFilePath :: FilePath -> FilePath -> FilePath -> Q Exp +staticAssetFilePath root staticPkgName relativePath = do + let fullPath = root staticPkgName relativePath qAddDependentFile fullPath pure $ LitE $ StringL fullPath @@ -77,13 +82,16 @@ staticAssetWorker :: FilePath -- ^ Add this prefix directory to the embedded filepath @fp@. -> FilePath - -- ^ Directory to which the filepath must have been copied. + -- ^ Base Directory to which the filepath must have been copied. + -- If @fp@ does not exist within this directory, this function will fail. + -> FilePath + -- ^ Static Project Directory to which the filepath must have been copied. -- If @fp@ does not exist within this directory, this function will fail. -> FilePath -- ^ Filepath you want to embed. -> Q Exp -staticAssetWorker root staticOut fp = do - exists <- runIO $ doesFileExist $ staticOut fp +staticAssetWorker root staticOut staticName fp = do + exists <- runIO $ doesFileExist $ staticOut staticName fp when (not exists) $ - fail $ "The file " <> fp <> " was not found in " <> staticOut - return $ LitE $ StringL $ root fp + fail $ "The file " <> fp <> " was not found in " <> staticOut staticName + return $ LitE $ StringL $ root staticName fp From e00a236ba7673355e4cb58cec9d21c9cb74b9ced Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Mon, 3 Mar 2025 12:05:22 -0500 Subject: [PATCH 10/36] staticFiles. -> processAssets staticName arg --- default.nix | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/default.nix b/default.nix index fe5b97429..f245fd3e4 100644 --- a/default.nix +++ b/default.nix @@ -68,16 +68,24 @@ in rec { ''; nullIfAbsent = p: if lib.pathExists p then p else null; #TODO: Avoid copying files within the nix store. Right now, obelisk-asset-manifest-generate copies files into a big blob so that the android/ios static assets can be imported from there; instead, we should get everything lined up right before turning it into an APK, so that copies, if necessary, only exist temporarily. - processAssets = { src, packageName ? "obelisk-generated-static", moduleName ? "Obelisk.Generated.Static", exe ? "obelisk-asset-th-generate" }: pkgs.runCommand "asset-manifest" { - inherit src; - outputs = [ "out" "haskellManifest" "symlinked" ]; - nativeBuildInputs = [ ghcObelisk.obelisk-asset-manifest ]; - } '' - set -euo pipefail - touch "$out" - mkdir -p "$symlinked" - ${exe} "$src" "$haskellManifest" ${packageName} ${moduleName} "$symlinked" - '' // {inherit packageName;}; + processAssets = + { src + , packageName ? "obelisk-generated-static" + , moduleName ? "Obelisk.Generated.Static" + #, staticFunctionName ? packageName + , staticPath ? "static" + , staticName ? "static" + , exe ? "obelisk-asset-th-generate" + }: pkgs.runCommand "asset-manifest" { + inherit src; + outputs = [ "out" "haskellManifest" "symlinked" ]; + nativeBuildInputs = [ ghcObelisk.obelisk-asset-manifest ]; + } '' + set -euo pipefail + touch "$out" + mkdir -p "$symlinked" + ${exe} "$src" "$haskellManifest" ${packageName} ${moduleName} "$symlinked" ${staticName} + '' // {inherit packageName;}; compressedJs = frontend: optimizationLevel: externs: pkgs.runCommand "compressedJs" {} '' set -euo pipefail @@ -288,8 +296,9 @@ in rec { else { path = staticArgs.path; src = toString staticArgs.path; } ) fs; processedStatic = - let processAssets' = { path, drvArgs, isDrv, packageName ? "obelisk-generated-static", moduleName ? "Obelisk.Generated.Static" }@staticDrvArgs: processAssets { + let processAssets' = { path, drvArgs, isDrv, staticName, packageName ? "obelisk-generated-static", moduleName ? "Obelisk.Generated.Static" }@staticDrvArgs: processAssets { src = if isDrv then (import path drvArgs) else path; + staticName = staticName; packageName = packageName; moduleName = moduleName; #moduleName @@ -298,7 +307,7 @@ in rec { else "obelisk-asset-th-generate"; }; in - lib.mapAttrs (name: staticArgs: processAssets' (staticArgs // { packageName = name; } )) self.userSettings.staticFiles; + lib.mapAttrs (name: staticArgs: processAssets' (staticArgs // { packageName = name; staticName = name;} )) self.userSettings.staticFiles; # lib.mapAttrs (_: staticArgs: # if staticArgs.isDrv # then processAssets' (import staticArgs.path staticArgs.args) From f1daba5e4efdbb4720e173ea650b151c35828dd5 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Mon, 3 Mar 2025 12:20:17 -0500 Subject: [PATCH 11/36] creation of symlinks for multiple statics at static.out/ --- lib/command/src/Obelisk/Command/Project.hs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/command/src/Obelisk/Command/Project.hs b/lib/command/src/Obelisk/Command/Project.hs index 0a99018fe..5eff6eb47 100644 --- a/lib/command/src/Obelisk/Command/Project.hs +++ b/lib/command/src/Obelisk/Command/Project.hs @@ -79,12 +79,12 @@ import Obelisk.Command.Utils (nixBuildExePath, nixExePath, toNixPath, cp, nixShe --TODO: Make this module resilient to random exceptions -static_out :: FilePath -static_out = "static.out" +staticOut :: FilePath +staticOut = "static.out" -- | Common constant used for symlinked static drv dotOut :: FilePath -dotOut = ".dot" +dotOut = ".out" --TODO: Don't hardcode this @@ -412,9 +412,9 @@ instance Json.FromJSON StaticInfo where return $ StaticInfo { _staticInfo_name = name , _staticInfo_assetSource = if drvBool then AssetSource_Derivation else AssetSource_Files - , _staticInfo_path = last $ splitDirectories path + , _staticInfo_path = path } - + -- | Some log messages to make it easier to tell where static files are coming from describeImpureAssetSource :: AssetSource -> Text -> Text describeImpureAssetSource src path = case src of @@ -434,9 +434,10 @@ findProjectAssets root = do , "--json" ] case Json.eitherDecode . BSL.fromStrict . encodeUtf8 $ isDerivation of - Left _ -> throwError "Unable to get StaticInfo" + Left _ -> fail "Unable to get StaticInfo" Right (statics :: [StaticInfo]) -> do - -- Build symlink path at .out + liftIO $ createDirectoryIfMissing False staticOut + -- Build symlink path at static.out/ forM_ statics $ \staticInfo -> do if _staticInfo_assetSource staticInfo == AssetSource_Derivation then do @@ -446,7 +447,7 @@ findProjectAssets root = do (_staticInfo_name staticInfo) else do void $ readProcessAndLogStderr Debug $ setCwd (Just root) $ - proc lnPath ["-sfT", (_staticInfo_path staticInfo), T.unpack (_staticInfo_name staticInfo) <> dotOut] + proc lnPath ["-sfT", (_staticInfo_path staticInfo), staticOut T.unpack (_staticInfo_name staticInfo)] pure statics -- | Get the nix store path to the generated static asset manifest module (e.g., "obelisk-generated-static") @@ -561,7 +562,7 @@ buildStaticFilesDerivationAndSymlink f root staticName = f $ setCwd (Just root) $ ProcessSpec { _processSpec_createProcess = Proc.proc nixBuildExePath - [ "-o", T.unpack staticName <> dotOut + [ "-o", staticOut T.unpack staticName , "-E", "(import ./. {}).passthru.staticFilesImpure." <> T.unpack staticName <> ".src" ] , _processSpec_overrideEnv = Nothing From 4cdf89ec9ab79415041e14c141c3b8c89bb0910e Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Mon, 3 Mar 2025 12:44:16 -0500 Subject: [PATCH 12/36] update command to deal with multiple static directories + static.out as constant --- lib/command/src/Obelisk/Command/Project.hs | 1 + lib/command/src/Obelisk/Command/Run.hs | 26 +++++++++++----------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/command/src/Obelisk/Command/Project.hs b/lib/command/src/Obelisk/Command/Project.hs index 5eff6eb47..02c60f160 100644 --- a/lib/command/src/Obelisk/Command/Project.hs +++ b/lib/command/src/Obelisk/Command/Project.hs @@ -27,6 +27,7 @@ module Obelisk.Command.Project , StaticInfo(..) , describeImpureAssetSource , watchStaticFilesDerivation + , staticOut ) where import Control.Concurrent.MVar (MVar, newMVar, withMVarMasked) diff --git a/lib/command/src/Obelisk/Command/Run.hs b/lib/command/src/Obelisk/Command/Run.hs index 4204e0cbe..8b72e42ad 100644 --- a/lib/command/src/Obelisk/Command/Run.hs +++ b/lib/command/src/Obelisk/Command/Run.hs @@ -17,7 +17,7 @@ import Control.Arrow ((&&&)) import Control.Exception (Exception, bracket) import Control.Lens (ifor, (.~), (&), view) import Control.Concurrent (forkIO) -import Control.Monad (filterM, void) +import Control.Monad (filterM, forM, void) import Control.Monad.Except (runExceptT, throwError) import Control.Monad.IO.Class (liftIO) import Control.Monad.Reader (MonadIO) @@ -168,8 +168,8 @@ profile profileBasePattern rtsFlags = withProjectRoot "." $ \root -> do , _target_attr = Just "__unstable__.profiledObRun" , _target_expr = Nothing } - (assetType, assets) <- findProjectAssets root - putLog Debug $ describeImpureAssetSource assetType assets + staticInfos <- findProjectAssets root + forM staticInfos $ \info -> putLog Debug $ describeImpureAssetSource (_staticInfo_assetSource info) (T.pack $ _staticInfo_path info) time <- liftIO getCurrentTime let profileBaseName = formatTime defaultTimeLocale profileBasePattern time liftIO $ createDirectoryIfMissing True $ takeDirectory $ root profileBaseName @@ -177,7 +177,7 @@ profile profileBasePattern rtsFlags = withProjectRoot "." $ \root -> do freePort <- getFreePort runProcess_ $ setCwd (Just root) $ setDelegateCtlc True $ proc (outPath "bin" "ob-run") $ [ show freePort - , T.unpack assets + , staticOut , profileBaseName , "+RTS" , "-po" <> profileBaseName @@ -197,23 +197,23 @@ run -> m () run certDir portOverride root interpretPaths = do pkgs <- getParsedLocalPkgs root interpretPaths - (assetType, assets) <- findProjectAssets root - manifestPkg <- parsePackagesOrFail . (:[]) . T.unpack =<< getHaskellManifestProjectPath root - putLog Debug $ describeImpureAssetSource assetType assets - case assetType of - AssetSource_Derivation -> do + staticInfos <- findProjectAssets root + manifestPkgs <- parsePackagesOrFail . fmap T.unpack =<< getStaticHaskellManifestProjectPaths root + forM staticInfos $ \info -> putLog Debug $ describeImpureAssetSource (_staticInfo_assetSource info) (T.pack $ _staticInfo_path info) + case filter ((==AssetSource_Derivation) . _staticInfo_assetSource) staticInfos of + [] -> pure () + paths@(_:_) -> do ob <- getObelisk putLog Debug "Starting static file derivation watcher..." - void $ liftIO $ forkIO $ runObelisk ob $ watchStaticFilesDerivation root - _ -> pure () - ghciArgs <- getGhciSessionSettings (pkgs <> manifestPkg) root + void $ liftIO $ forkIO $ runObelisk ob $ watchStaticFilesDerivation root paths + ghciArgs <- getGhciSessionSettings (pkgs <> manifestPkgs) root freePort <- getFreePort withGhciScriptArgs [] pkgs $ \dotGhciArgs -> do runGhcid root True (ghciArgs <> dotGhciArgs) pkgs $ Just $ unwords [ "Obelisk.Run.run (Obelisk.Run.defaultRunApp" , "Backend.backend" , "Frontend.frontend" - , "(Obelisk.Run.runServeAsset " ++ show assets ++ ")" + , "(Obelisk.Run.runServeAsset " ++ (show $ root staticOut) ++ ")" , ") { Obelisk.Run._runApp_backendPort =", show freePort , ", Obelisk.Run._runApp_forceFrontendPort =", show portOverride , ", Obelisk.Run._runApp_tlsCertDirectory =", show certDir From 87aefe56695d27a110a65bb1fbe9a05e713a1b22 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Mon, 3 Mar 2025 13:30:47 -0500 Subject: [PATCH 13/36] update symlinking on serverExe for multiple statics --- default.nix | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/default.nix b/default.nix index f245fd3e4..1e502911d 100644 --- a/default.nix +++ b/default.nix @@ -221,12 +221,16 @@ in rec { exeBackend = if profiling then backend else haskellLib.justStaticExecutables backend; exeFrontend = compressedJs frontend optimizationLevel externjs; exeFrontendAssets = mkAssets exeFrontend; - exeAssets = mkAssets assets; + exeAssets = lib.mapAttrs (n: args: mkAssets (if args.isDrv then (import args.path args.drvArgs) else args.path)) assets; in pkgs.runCommand "serverExe" {} '' mkdir $out set -eux ln -s '${exeBackend}'/bin/* $out/ - ln -s '${exeAssets}' $out/static.assets + mkdir $out/static.assets + ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: assets: '' + ln -s '${assets}' $out/static.assets/${name} + '') exeAssets)} + for d in '${exeFrontendAssets}'/*/; do ln -s "$d" "$out"/"$(basename "$d").assets" done @@ -296,23 +300,17 @@ in rec { else { path = staticArgs.path; src = toString staticArgs.path; } ) fs; processedStatic = - let processAssets' = { path, drvArgs, isDrv, staticName, packageName ? "obelisk-generated-static", moduleName ? "Obelisk.Generated.Static" }@staticDrvArgs: processAssets { + let processAssets' = { path, drvArgs, isDrv, staticName, packageName, moduleName ? "Obelisk.Generated.Static" }@staticDrvArgs: processAssets { src = if isDrv then (import path drvArgs) else path; staticName = staticName; packageName = packageName; moduleName = moduleName; - #moduleName exe = if lib.attrByPath ["userSettings" "__deprecated" "useObeliskAssetManifestGenerate"] false self then builtins.trace "obelisk-asset-manifest-generate is deprecated. Use obelisk-asset-th-generate instead." "obelisk-asset-manifest-generate" else "obelisk-asset-th-generate"; }; in lib.mapAttrs (name: staticArgs: processAssets' (staticArgs // { packageName = name; staticName = name;} )) self.userSettings.staticFiles; - # lib.mapAttrs (_: staticArgs: - # if staticArgs.isDrv - # then processAssets' (import staticArgs.path staticArgs.args) - # else processAssets' staticArgs.path - # ) self.userSettings.staticFiles; # The packages whose names and roles are defined by this package predefinedPackages = lib.filterAttrs (_: x: x != null) { ${self.frontendName} = nullIfAbsent (self.base + "/frontend"); From 31c82d161e25fe78ed61a32eaf3b3a444ce9c64d Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 4 Mar 2025 12:44:43 -0500 Subject: [PATCH 14/36] fix nix eval typo --- lib/command/src/Obelisk/Command/Project.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/command/src/Obelisk/Command/Project.hs b/lib/command/src/Obelisk/Command/Project.hs index 02c60f160..f2eb7d3e5 100644 --- a/lib/command/src/Obelisk/Command/Project.hs +++ b/lib/command/src/Obelisk/Command/Project.hs @@ -457,7 +457,7 @@ getStaticHaskellManifestProjectPaths root = do stdout <- readProcessAndLogStderr Debug $ setCwd (Just root) $ proc nixBuildExePath [ "--no-out-link" , "-E" - , "(let a = import ./. {}; in builtins.mapAttrs (_: x: x.haskellManifest) d.passthru.processedStatic)" + , "(let a = import ./. {}; in builtins.mapAttrs (_: x: x.haskellManifest) a.passthru.processedStatic)" ] pure $ T.strip <$> T.lines stdout From dcfac93dd25683c2201edf5740eecb06f52076c6 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 4 Mar 2025 12:52:08 -0500 Subject: [PATCH 15/36] update skeleton/default.nix for explicit static --- skeleton/default.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/skeleton/default.nix b/skeleton/default.nix index adc19fea3..569f817e3 100644 --- a/skeleton/default.nix +++ b/skeleton/default.nix @@ -16,6 +16,14 @@ }: with obelisk; project ./. ({ ... }: { + staticFiles = { + obelisk-generated-static = { + path = ./static; + isDrv = false; + drvArgs = null; + moduleName = "Obelisk.Generated.Static"; + }; + }; android.applicationId = "systems.obsidian.obelisk.examples.minimal"; android.displayName = "Obelisk Minimal Example"; ios.bundleIdentifier = "systems.obsidian.obelisk.examples.minimal"; From ed485a4e8627c518cc282ef877ff57e63c8a1113 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 4 Mar 2025 17:01:01 -0500 Subject: [PATCH 16/36] dont use static pkg name in \!OBELISK_ASSET_PASSTHRU --- lib/asset/manifest/src-bin/static-th.hs | 2 +- lib/asset/manifest/src/Obelisk/Asset/TH.hs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/asset/manifest/src-bin/static-th.hs b/lib/asset/manifest/src-bin/static-th.hs index 95bd245b1..f6b2372b5 100644 --- a/lib/asset/manifest/src-bin/static-th.hs +++ b/lib/asset/manifest/src-bin/static-th.hs @@ -36,7 +36,7 @@ main = do , "staticFilePath = staticAssetFilePathRaw \"static.out\"" <> " " <> show staticAttrName , "#else" , "static = staticAssetHashed " <> show root <> " " <> show staticAttrName - , "staticFilePath = staticAssetFilePath " <> show root <> " " <> show staticAttrName + , "staticFilePath = staticAssetFilePath " <> show root , "#endif" ] } diff --git a/lib/asset/manifest/src/Obelisk/Asset/TH.hs b/lib/asset/manifest/src/Obelisk/Asset/TH.hs index c48a76aef..faaeeb9ca 100644 --- a/lib/asset/manifest/src/Obelisk/Asset/TH.hs +++ b/lib/asset/manifest/src/Obelisk/Asset/TH.hs @@ -66,9 +66,9 @@ staticAssetFilePathRaw staticAssetFilePathRaw root staticName = staticAssetWorker root staticOutPath staticName -- | Return the real location of 'relativePath' -staticAssetFilePath :: FilePath -> FilePath -> FilePath -> Q Exp -staticAssetFilePath root staticPkgName relativePath = do - let fullPath = root staticPkgName relativePath +staticAssetFilePath :: FilePath -> FilePath -> Q Exp +staticAssetFilePath root relativePath = do + let fullPath = root relativePath qAddDependentFile fullPath pure $ LitE $ StringL fullPath From d235e52e09916331ed1bc21ade8e7814323d1017 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 11 Mar 2025 20:14:50 -0400 Subject: [PATCH 17/36] temporarily set attr of android for testing --- default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/default.nix b/default.nix index 1e502911d..e994f3709 100644 --- a/default.nix +++ b/default.nix @@ -333,10 +333,10 @@ in rec { __androidWithConfig = configPath: { ${if self.userSettings.android == null then null else self.frontendName} = { executableName = "frontend"; - ${if builtins.pathExists self.userSettings.staticFiles then "assets" else null} = + "assets" = #${if builtins.pathExists self.userSettings.staticFiles.staticAssets then "assets" else null} = nixpkgs.obeliskExecutableConfig.platforms.android.inject (self.injectableConfig configPath) - self.processedStatic.symlinked; + self.processedStatic.staticAssets.symlinked; } // self.userSettings.android; }; __iosWithConfig = configPath: { From 81ff52f673121c1048bf8732d80a584c1246a1b2 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Wed, 12 Mar 2025 00:34:43 -0400 Subject: [PATCH 18/36] temp fix to use staticAssets name, statically --- lib/executable-config/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/executable-config/default.nix b/lib/executable-config/default.nix index c6425e106..9b3b30495 100644 --- a/lib/executable-config/default.nix +++ b/lib/executable-config/default.nix @@ -11,7 +11,8 @@ let injectConfig = config: assets: runCommand "inject-config" {} ('' set -x mkdir -p $out - cp --no-preserve=mode -Lr "${assets}" $out/static + mkdir -p $out/static + cp --no-preserve=mode -Lr "${assets}" $out/static/staticAssets chmod +w "$out" '' + lib.optionalString (!(builtins.isNull config)) '' if ! mkdir $out/config; then From f062eaf77858e74a222ec68cab46231dfc6ce4f2 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Mon, 17 Mar 2025 23:16:48 -0400 Subject: [PATCH 19/36] Allow 3rd party cookies on android --- dep/reflex-platform/github.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dep/reflex-platform/github.json b/dep/reflex-platform/github.json index e03dc5192..8d41b09cf 100644 --- a/dep/reflex-platform/github.json +++ b/dep/reflex-platform/github.json @@ -1,8 +1,8 @@ { - "owner": "reflex-frp", + "owner": "Ace-Interview-Prep", "repo": "reflex-platform", - "branch": "release/1.2.0.0", + "branch": "gs/android-cookies", "private": false, - "rev": "f231e2425ac92339b8491cdd970930d63d9ad1ad", - "sha256": "0b042x423p04shhidni08f47ydgpfj0rpqhb0m6gj2lg8b3s9l8k" + "rev": "35abfe8401eb3badfd521da8b9c49a29da0de97b", + "sha256": "1gfsm3p5k8h1c741a1gz34vxwxs20ww0jl8xhi8qrbrw31zvc3k8" } From 6edfa9f2d0e9b64086000b399c0ec4b02777ae6b Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 23 Sep 2025 19:46:57 -0400 Subject: [PATCH 20/36] Show route encoder error --- lib/frontend/src/Obelisk/Frontend.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/frontend/src/Obelisk/Frontend.hs b/lib/frontend/src/Obelisk/Frontend.hs index 01b5920ed..d6ed1102c 100644 --- a/lib/frontend/src/Obelisk/Frontend.hs +++ b/lib/frontend/src/Obelisk/Frontend.hs @@ -193,7 +193,7 @@ runFrontendWithConfigsAndCurrentRoute runFrontendWithConfigsAndCurrentRoute mode configs validFullEncoder frontend = do let ve = validFullEncoder . hoistParse errorLeft (reviewEncoder (rPrism $ _FullRoute_Frontend . _ObeliskRoute_App)) errorLeft = \case - Left _ -> error "runFrontend: Unexpected non-app ObeliskRoute reached the frontend. This shouldn't happen." + Left e -> error $ "runFrontend: Unexpected non-app ObeliskRoute reached the frontend. This shouldn't happen. with route" <> (show e) Right x -> Identity x w :: ( RawDocument (DomBuilderSpace (HydrationDomBuilderT s DomTimeline m)) ~ DOM.Document , Ref (Performable m) ~ Ref IO From ba1c889a7944b26277404bebab944d218944a95c Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Fri, 26 Sep 2025 20:31:21 -0400 Subject: [PATCH 21/36] render route on encoder error + start at Login --- dep/reflex-platform/github.json | 4 ++-- lib/frontend/src/Obelisk/Frontend.hs | 25 +++++++++++++++++++------ lib/route/src/Obelisk/Route.hs | 11 ++++++++++- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/dep/reflex-platform/github.json b/dep/reflex-platform/github.json index 8d41b09cf..b9d544b04 100644 --- a/dep/reflex-platform/github.json +++ b/dep/reflex-platform/github.json @@ -3,6 +3,6 @@ "repo": "reflex-platform", "branch": "gs/android-cookies", "private": false, - "rev": "35abfe8401eb3badfd521da8b9c49a29da0de97b", - "sha256": "1gfsm3p5k8h1c741a1gz34vxwxs20ww0jl8xhi8qrbrw31zvc3k8" + "rev": "d686df957502c76b472e1b58092aab59dfcaf5bb", + "sha256": "0q9qbkizi1ps9qppiyyqbdn6iiisnpl65fbmdy5h588k1p331a2k" } diff --git a/lib/frontend/src/Obelisk/Frontend.hs b/lib/frontend/src/Obelisk/Frontend.hs index d6ed1102c..2a132709c 100644 --- a/lib/frontend/src/Obelisk/Frontend.hs +++ b/lib/frontend/src/Obelisk/Frontend.hs @@ -25,7 +25,6 @@ module Obelisk.Frontend , module Obelisk.Frontend.Cookie ) where - #ifdef __GLASGOW_HASKELL__ #if __GLASGOW_HASKELL__ < 810 import Data.Monoid ((<>)) @@ -50,6 +49,7 @@ import Data.ByteString (ByteString) import Data.Foldable (for_) import Data.Map (Map) import Data.Maybe (catMaybes) +import qualified Data.Text as T import Data.Text (Text) import qualified GHCJS.DOM as DOM import qualified GHCJS.DOM.Types as DOM @@ -140,7 +140,7 @@ setInitialRoute useHash = do initialUri <- getLocationUri initialLocation history <- DOM.getHistory window DOM.replaceState history jsNull ("" :: Text) $ Just $ - show $ setAdaptedUriPath useHash "/" initialUri + show $ setAdaptedUriPath useHash "/login" initialUri data FrontendMode = FrontendMode { _frontendMode_hydrate :: Bool @@ -185,16 +185,29 @@ runFrontend validFullEncoder frontend = do runFrontendWithConfigsAndCurrentRoute :: forall backendRoute frontendRoute +-- . (GShow backendRoute, GShow frontendRoute) . FrontendMode -> Map Text ByteString -> Encoder Identity Identity (R (FullRoute backendRoute frontendRoute)) PageName -> Frontend (R frontendRoute) -> JSM () runFrontendWithConfigsAndCurrentRoute mode configs validFullEncoder frontend = do - let ve = validFullEncoder . hoistParse errorLeft (reviewEncoder (rPrism $ _FullRoute_Frontend . _ObeliskRoute_App)) - errorLeft = \case - Left e -> error $ "runFrontend: Unexpected non-app ObeliskRoute reached the frontend. This shouldn't happen. with route" <> (show e) - Right x -> Identity x + let ---ve :: _ + ve = validFullEncoder . hoistParse errorLeft (reviewEncoder' (rPrism $ _FullRoute_Frontend . _ObeliskRoute_App)) + errorLeft + :: forall t. + Either (R (FullRoute backendRoute frontendRoute)) t + -> Identity t + errorLeft = + Identity . either + (\e -> error $ + "runFrontend: Unexpected non-app ObeliskRoute reached the frontend. " + <> "This shouldn't happen. with route " + <> T.unpack (renderObeliskRoute validFullEncoder e)) + Prelude.id + -- errorLeft = \case + -- Left (e) -> error $ "runFrontend: Unexpected non-app ObeliskRoute reached the frontend. This shouldn't happen. with route" <> (T.unpack $ renderObeliskRoute validFullEncoder e) + -- Right x -> Identity x w :: ( RawDocument (DomBuilderSpace (HydrationDomBuilderT s DomTimeline m)) ~ DOM.Document , Ref (Performable m) ~ Ref IO , Ref m ~ Ref IO diff --git a/lib/route/src/Obelisk/Route.hs b/lib/route/src/Obelisk/Route.hs index 6f6f6e8b4..2f59e2c69 100644 --- a/lib/route/src/Obelisk/Route.hs +++ b/lib/route/src/Obelisk/Route.hs @@ -110,6 +110,7 @@ module Obelisk.Route , shadowEncoder , prismEncoder , reviewEncoder + , reviewEncoder' , obeliskRouteEncoder , obeliskRouteSegment , pageNameEncoder @@ -925,7 +926,15 @@ reviewEncoder p = unsafeMkEncoder $ EncoderImpl { _encoderImpl_encode = review p , _encoderImpl_decode = \r -> case r ^? p of Just a -> pure a - Nothing -> throwError "reviewEncoder: value is not present in the prism" + Nothing -> throwError $ "reviewEncoder: value is not present in the prism: " + } + +reviewEncoder' :: (Applicative check, MonadError b parse) => Prism' b a -> Encoder check parse a b +reviewEncoder' p = unsafeMkEncoder $ EncoderImpl + { _encoderImpl_encode = review p + , _encoderImpl_decode = \(r) -> case r ^? p of + Just a -> pure a + Nothing -> throwError r--- $ "reviewEncoder: value is not present in the prism: " } -- | A URL path and query string, in which trailing slashes don't matter in the path From 9540968f088d6e2d469631ca288911b010afa48b Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Sun, 28 Sep 2025 17:28:13 -0400 Subject: [PATCH 22/36] Update reflex-platform: use buildIcons --- dep/reflex-platform/github.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dep/reflex-platform/github.json b/dep/reflex-platform/github.json index b9d544b04..cf164ae70 100644 --- a/dep/reflex-platform/github.json +++ b/dep/reflex-platform/github.json @@ -3,6 +3,6 @@ "repo": "reflex-platform", "branch": "gs/android-cookies", "private": false, - "rev": "d686df957502c76b472e1b58092aab59dfcaf5bb", - "sha256": "0q9qbkizi1ps9qppiyyqbdn6iiisnpl65fbmdy5h588k1p331a2k" + "rev": "3def6633078988e91e1922b6b06b0ec374b2fa3c", + "sha256": "1w8578nmrahy5ixcpcczxalxffx93bc7impw6pwp408fy48lddd0" } From 9be402f00288cd4d149813df13b2c92ef3b7fcae Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 30 Sep 2025 22:39:07 -0400 Subject: [PATCH 23/36] update NA --- dep/reflex-platform/github.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dep/reflex-platform/github.json b/dep/reflex-platform/github.json index cf164ae70..a03cb858b 100644 --- a/dep/reflex-platform/github.json +++ b/dep/reflex-platform/github.json @@ -1,8 +1,8 @@ { "owner": "Ace-Interview-Prep", "repo": "reflex-platform", - "branch": "gs/android-cookies", + "branch": "gs/optimize-android-builds", "private": false, - "rev": "3def6633078988e91e1922b6b06b0ec374b2fa3c", - "sha256": "1w8578nmrahy5ixcpcczxalxffx93bc7impw6pwp408fy48lddd0" + "rev": "20e758f07f9476acb288e940be74deec8d3b3ea1", + "sha256": "1q6p49qap518w9rmpmwd5iad43lcsqnk30h18r1rhppmn8x4ffbb" } From 47a54815dcadb1ace8a9acb308cb2ef9b8fc178e Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 30 Sep 2025 23:38:03 -0400 Subject: [PATCH 24/36] SQUASH: add plan for strip llvm --- dep/reflex-platform/github.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dep/reflex-platform/github.json b/dep/reflex-platform/github.json index cf164ae70..dcc049009 100644 --- a/dep/reflex-platform/github.json +++ b/dep/reflex-platform/github.json @@ -3,6 +3,6 @@ "repo": "reflex-platform", "branch": "gs/android-cookies", "private": false, - "rev": "3def6633078988e91e1922b6b06b0ec374b2fa3c", - "sha256": "1w8578nmrahy5ixcpcczxalxffx93bc7impw6pwp408fy48lddd0" + "rev": "2fa6625994c948f754d025bddab9c4c30911d9f8", + "sha256": "05mncplwlbwwh5msnfw024axymmiblkazqn3jak7rilzqlqnl83v" } From 29fb2728bf1635bd8ddbd06678363c947f3f98d3 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Thu, 2 Oct 2025 09:56:17 -0400 Subject: [PATCH 25/36] Update reflex-platform : optimized android builds --- dep/reflex-platform/github.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dep/reflex-platform/github.json b/dep/reflex-platform/github.json index 8163c54dc..decccd51b 100644 --- a/dep/reflex-platform/github.json +++ b/dep/reflex-platform/github.json @@ -3,6 +3,6 @@ "repo": "reflex-platform", "branch": "gs/optimize-android-builds", "private": false, - "rev": "2fa6625994c948f754d025bddab9c4c30911d9f8", - "sha256": "05mncplwlbwwh5msnfw024axymmiblkazqn3jak7rilzqlqnl83v" + "rev": "1b3cc0805eff4d1e48771c4254801dd8b9f8d8b1", + "sha256": "03jj8jnigw2bkkj8gsw664nag8gs1n7wm45pj51scw9a0qzvmabz" } From d30188b5d3806906e54830976937a09ff4ba301a Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Thu, 2 Oct 2025 09:58:47 -0400 Subject: [PATCH 26/36] filter out non-hashed staticAssets to massively reduce .aab size --- lib/executable-config/default.nix | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/executable-config/default.nix b/lib/executable-config/default.nix index 9b3b30495..1787a237c 100644 --- a/lib/executable-config/default.nix +++ b/lib/executable-config/default.nix @@ -13,6 +13,19 @@ let mkdir -p $out mkdir -p $out/static cp --no-preserve=mode -Lr "${assets}" $out/static/staticAssets + assets_root="$out/static/staticAssets" + + # Walk recursively, look for hashed files, remove the plain originals + find "$assets_root" -type f -regextype posix-extended -regex '.*/[A-Za-z0-9]{16,}-[^/]+$' | while read -r hashed; do + dir=$(dirname "$hashed") + base=$(basename "$hashed") + orig="''${base#*-}" + orig_path="$dir/$orig" + if [ -f "$orig_path" ]; then + echo "Removing duplicate original: $orig_path" + rm -f -- "$orig_path" + fi + done chmod +w "$out" '' + lib.optionalString (!(builtins.isNull config)) '' if ! mkdir $out/config; then From 3dba9f2a2c141d4f20d136e5e833956fd58a7666 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Fri, 3 Oct 2025 20:17:43 -0400 Subject: [PATCH 27/36] + injectMany for use with android inject configs --- default.nix | 43 +++++++++++++++--------- lib/executable-config/default.nix | 54 +++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 17 deletions(-) diff --git a/default.nix b/default.nix index e994f3709..9a1e0bf89 100644 --- a/default.nix +++ b/default.nix @@ -74,7 +74,7 @@ in rec { , moduleName ? "Obelisk.Generated.Static" #, staticFunctionName ? packageName , staticPath ? "static" - , staticName ? "static" + , staticName ? "static" , exe ? "obelisk-asset-th-generate" }: pkgs.runCommand "asset-manifest" { inherit src; @@ -300,17 +300,30 @@ in rec { else { path = staticArgs.path; src = toString staticArgs.path; } ) fs; processedStatic = - let processAssets' = { path, drvArgs, isDrv, staticName, packageName, moduleName ? "Obelisk.Generated.Static" }@staticDrvArgs: processAssets { - src = if isDrv then (import path drvArgs) else path; - staticName = staticName; - packageName = packageName; - moduleName = moduleName; - exe = if lib.attrByPath ["userSettings" "__deprecated" "useObeliskAssetManifestGenerate"] false self - then builtins.trace "obelisk-asset-manifest-generate is deprecated. Use obelisk-asset-th-generate instead." "obelisk-asset-manifest-generate" - else "obelisk-asset-th-generate"; - }; + let processAssets' = + { path + , drvArgs + , isDrv + , staticName + , packageName + , moduleName ? "Obelisk.Generated.Static" + , mobile ? true + }@staticDrvArgs: processAssets { + src = if isDrv then (import path drvArgs) else path; + staticName = staticName; + packageName = packageName; + moduleName = moduleName; + exe = if lib.attrByPath ["userSettings" "__deprecated" "useObeliskAssetManifestGenerate"] false self + then builtins.trace "obelisk-asset-manifest-generate is deprecated. Use obelisk-asset-th-generate instead." "obelisk-asset-manifest-generate" + else "obelisk-asset-th-generate"; + } // { inherit mobile; }; in - lib.mapAttrs (name: staticArgs: processAssets' (staticArgs // { packageName = name; staticName = name;} )) self.userSettings.staticFiles; + lib.mapAttrs + (name: staticArgs: processAssets' + (staticArgs + // { packageName = name; staticName = name; } + )) + self.userSettings.staticFiles; # The packages whose names and roles are defined by this package predefinedPackages = lib.filterAttrs (_: x: x != null) { ${self.frontendName} = nullIfAbsent (self.base + "/frontend"); @@ -319,10 +332,10 @@ in rec { }; shellPackages = {}; combinedPackages = self.predefinedPackages // self.userSettings.packages // self.shellPackages; - projectOverrides = self': super': ({ + projectOverrides = self': super': ({ ${self.backendName} = haskellLib.addBuildDepend super'.${self.backendName} self'.obelisk-run; } // ( - # unique name | <<- unique packageName <<- unique module name, in order to depend on all of them together in one pkgset + # unique name | <<- unique packageName <<- unique module name, in order to depend on all of them together in one pkgset lib.mapAttrs (pkgName: assets: self'.callCabal2nix pkgName assets.haskellManifest {}) self.processedStatic )); totalOverrides = lib.composeExtensions self.projectOverrides self.userSettings.overrides; @@ -334,9 +347,9 @@ in rec { ${if self.userSettings.android == null then null else self.frontendName} = { executableName = "frontend"; "assets" = #${if builtins.pathExists self.userSettings.staticFiles.staticAssets then "assets" else null} = - nixpkgs.obeliskExecutableConfig.platforms.android.inject + nixpkgs.obeliskExecutableConfig.platforms.android.injectMany (self.injectableConfig configPath) - self.processedStatic.staticAssets.symlinked; + (lib.filterAttrs (name: static: static.mobile) self.processedStatic); #.staticAssets.symlinked; } // self.userSettings.android; }; __iosWithConfig = configPath: { diff --git a/lib/executable-config/default.nix b/lib/executable-config/default.nix index 1787a237c..b73e8a04b 100644 --- a/lib/executable-config/default.nix +++ b/lib/executable-config/default.nix @@ -8,13 +8,62 @@ }: let + setup = '' + set -x + mkdir -p $out + mkdir -p $out/static + ''; + createConfig = config: lib.optionalString (!(builtins.isNull config)) '' + if ! mkdir $out/config; then + 2>&1 echo config directory already exists or could not be created + exit 1 + fi + cp -a "${config}"/* "$out/config" + # Needed for android deployments + find "$out/config" -type f -printf '%P\0' > "$out/config.files" + ''; + # Walk recursively, look for hashed files, remove the plain originals + removeNonHashed = '' + assets_root="$out/static/" + find "$assets_root" -type f -regextype posix-extended -regex '.*/[A-Za-z0-9]{16,}-[^/]+$' | while read -r hashed; do + dir=$(dirname "$hashed") + base=$(basename "$hashed") + orig="''${base#*-}" + orig_path="$dir/$orig" + if [ -f "$orig_path" ]; then + echo "Removing duplicate original: $orig_path" + rm -f -- "$orig_path" + fi + done + ''; + mkStaticDir = name: assets: '' + cp --no-preserve=mode -Lr "${assets}" $out/static/${name} + ''; + #mkStaticDirs = + injectMany = config: processedStatic: + let staticDirs = lib.mapAttrsToList (name: assetDrv: mkStaticDir name assetDrv.symlinked) processedStatic; + in + runCommand "inject-config" {} ( + '''' + + setup + + (lib.concatStrings staticDirs) + + removeNonHashed + + createConfig config + + '''' + ); + + + #lib.mapAttrs (name: assetDrv: mkStaticDir ) processedStatic + + #map (injectConfig config) assetsMany injectConfig = config: assets: runCommand "inject-config" {} ('' set -x mkdir -p $out mkdir -p $out/static cp --no-preserve=mode -Lr "${assets}" $out/static/staticAssets - assets_root="$out/static/staticAssets" + chmod +w "$out" + assets_root="$out/static/staticAssets" # Walk recursively, look for hashed files, remove the plain originals find "$assets_root" -type f -regextype posix-extended -regex '.*/[A-Za-z0-9]{16,}-[^/]+$' | while read -r hashed; do dir=$(dirname "$hashed") @@ -26,7 +75,7 @@ let rm -f -- "$orig_path" fi done - chmod +w "$out" + '' + lib.optionalString (!(builtins.isNull config)) '' if ! mkdir $out/config; then 2>&1 echo config directory already exists or could not be created @@ -57,6 +106,7 @@ in platforms = { android = { # Inject the given config directory into an android assets folder + injectMany = injectMany; inject = injectConfig; }; ios = { From 88a471ecd62dcbeb427322bc4c70da377a436b5c Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Sun, 5 Oct 2025 14:58:00 -0400 Subject: [PATCH 28/36] undo reflex-platform optimizations --- dep/reflex-platform/github.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dep/reflex-platform/github.json b/dep/reflex-platform/github.json index decccd51b..20eae31f4 100644 --- a/dep/reflex-platform/github.json +++ b/dep/reflex-platform/github.json @@ -3,6 +3,6 @@ "repo": "reflex-platform", "branch": "gs/optimize-android-builds", "private": false, - "rev": "1b3cc0805eff4d1e48771c4254801dd8b9f8d8b1", - "sha256": "03jj8jnigw2bkkj8gsw664nag8gs1n7wm45pj51scw9a0qzvmabz" + "rev": "1413a628bdc402ea7e8cac4b028f33c5f3237f2a", + "sha256": "02qhsz5q9rz5fwhl0pcr3i86nm1284zzysgz02m7b8nq8gvs2ai8" } From 90a4ff1cdd1d346624b2b1886647e51b88727710 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Sun, 5 Oct 2025 18:23:25 -0400 Subject: [PATCH 29/36] use injectMany on ios --- default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/default.nix b/default.nix index 9a1e0bf89..b3f5cb84b 100644 --- a/default.nix +++ b/default.nix @@ -356,9 +356,9 @@ in rec { ${if self.userSettings.ios == null then null else self.frontendName} = { executableName = "frontend"; ${if builtins.pathExists self.userSettings.staticFiles then "staticSrc" else null} = - nixpkgs.obeliskExecutableConfig.platforms.ios.inject + nixpkgs.obeliskExecutableConfig.platforms.ios.injectMany (self.injectableConfig configPath) - self.processedStatic.symlinked; + (lib.filterAttrs (name: static: static.mobile) self.processedStatic); } // self.userSettings.ios; }; From b78c6a15381b4e05e60923c4d8f382945e85f24e Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Sun, 5 Oct 2025 18:36:19 -0400 Subject: [PATCH 30/36] use injectMany on ios --- lib/executable-config/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/executable-config/default.nix b/lib/executable-config/default.nix index b73e8a04b..d6856bd4d 100644 --- a/lib/executable-config/default.nix +++ b/lib/executable-config/default.nix @@ -111,6 +111,7 @@ in }; ios = { # Inject the given config directory into an iOS app + injectMany = injectMany; inject = injectConfig; }; web = { From dab138d976f0ebe34eb206aa358bde9797d1be29 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Sun, 5 Oct 2025 18:46:35 -0400 Subject: [PATCH 31/36] use injectMany on ios --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index b3f5cb84b..af56b9f3e 100644 --- a/default.nix +++ b/default.nix @@ -355,7 +355,7 @@ in rec { __iosWithConfig = configPath: { ${if self.userSettings.ios == null then null else self.frontendName} = { executableName = "frontend"; - ${if builtins.pathExists self.userSettings.staticFiles then "staticSrc" else null} = + "assets" = nixpkgs.obeliskExecutableConfig.platforms.ios.injectMany (self.injectableConfig configPath) (lib.filterAttrs (name: static: static.mobile) self.processedStatic); From 75bb39e184991ddd72e30989fc7aaa39ccf67d4d Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Sun, 5 Oct 2025 19:21:48 -0400 Subject: [PATCH 32/36] correct attribute of ios options --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index af56b9f3e..32555d9fe 100644 --- a/default.nix +++ b/default.nix @@ -355,7 +355,7 @@ in rec { __iosWithConfig = configPath: { ${if self.userSettings.ios == null then null else self.frontendName} = { executableName = "frontend"; - "assets" = + "staticSrc" = nixpkgs.obeliskExecutableConfig.platforms.ios.injectMany (self.injectableConfig configPath) (lib.filterAttrs (name: static: static.mobile) self.processedStatic); From 67401246edf2a714f7f7bab89ceaa0bb637b8e7d Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Mon, 13 Oct 2025 18:12:30 -0400 Subject: [PATCH 33/36] add page size arg (const set to 16384) to sed of ghc-options in impl.nix, buildable --- dep/reflex-platform/github.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dep/reflex-platform/github.json b/dep/reflex-platform/github.json index 20eae31f4..18843cbf0 100644 --- a/dep/reflex-platform/github.json +++ b/dep/reflex-platform/github.json @@ -3,6 +3,6 @@ "repo": "reflex-platform", "branch": "gs/optimize-android-builds", "private": false, - "rev": "1413a628bdc402ea7e8cac4b028f33c5f3237f2a", - "sha256": "02qhsz5q9rz5fwhl0pcr3i86nm1284zzysgz02m7b8nq8gvs2ai8" + "rev": "f5d9d5df8def01e8887e33f7f52687a0b558dc60", + "sha256": "1q7g0wss8bm667bd3kqzzbski40ffx2kd4rpzfzlsnwhzsih3mf5" } From bb1f18c44ef0df400e18970eb1e804aac850905f Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 21 Oct 2025 23:41:30 -0400 Subject: [PATCH 34/36] add alexfmpe's libffi override to reflex-platform/default.nix --- dep/reflex-platform/github.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dep/reflex-platform/github.json b/dep/reflex-platform/github.json index 18843cbf0..6fff0e511 100644 --- a/dep/reflex-platform/github.json +++ b/dep/reflex-platform/github.json @@ -3,6 +3,6 @@ "repo": "reflex-platform", "branch": "gs/optimize-android-builds", "private": false, - "rev": "f5d9d5df8def01e8887e33f7f52687a0b558dc60", - "sha256": "1q7g0wss8bm667bd3kqzzbski40ffx2kd4rpzfzlsnwhzsih3mf5" + "rev": "ec391db332f6533dae6fa9c209891c5880ad7743", + "sha256": "1rim6qvnlwq4k34lbk3w73zfghfdlzh7jwh5lylsk4rr16yz2af2" } From 507c61dde698930caa9c6f82953a2bd4bbdbbc21 Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 23 Dec 2025 13:58:46 -0500 Subject: [PATCH 35/36] use PackageImports to disambiguate TemplateHaskell --- lib/asset/manifest/src-bin/static-th.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/asset/manifest/src-bin/static-th.hs b/lib/asset/manifest/src-bin/static-th.hs index f6b2372b5..e7cf038d3 100644 --- a/lib/asset/manifest/src-bin/static-th.hs +++ b/lib/asset/manifest/src-bin/static-th.hs @@ -20,6 +20,7 @@ main = do ] , _simplePkg_moduleContents = T.pack $ unlines [ "{-# Language CPP #-}" + , "{-# Language PackageImports #-}" , "{-|" , " Description:" , " Automatically generated module that provides the 'static' TH function" @@ -27,7 +28,7 @@ main = do , "-}" , "module " <> moduleName <> " ( static, staticFilePath ) where" , "" - , "import Obelisk.Asset.TH" + , "import \"template-haskell\" Obelisk.Asset.TH" , "import Language.Haskell.TH" , "" , "static, staticFilePath :: FilePath -> Q Exp" From b02db4318a73fe99d1f774d431d14baa2b565c4b Mon Sep 17 00:00:00 2001 From: lazyLambda Date: Tue, 23 Dec 2025 14:05:17 -0500 Subject: [PATCH 36/36] use PackageImports to disambiguate TemplateHaskell --- lib/asset/manifest/src-bin/static-th.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/asset/manifest/src-bin/static-th.hs b/lib/asset/manifest/src-bin/static-th.hs index e7cf038d3..bfcc548e8 100644 --- a/lib/asset/manifest/src-bin/static-th.hs +++ b/lib/asset/manifest/src-bin/static-th.hs @@ -28,8 +28,8 @@ main = do , "-}" , "module " <> moduleName <> " ( static, staticFilePath ) where" , "" - , "import \"template-haskell\" Obelisk.Asset.TH" - , "import Language.Haskell.TH" + , "import Obelisk.Asset.TH" + , "import \"template-haskell\" Language.Haskell.TH" , "" , "static, staticFilePath :: FilePath -> Q Exp" , "#ifdef OBELISK_ASSET_PASSTHRU"