Skip to content

Commit 76a5345

Browse files
Bundle code via esbuild after remapping imports
1 parent 7366787 commit 76a5345

File tree

4 files changed

+61
-29
lines changed

4 files changed

+61
-29
lines changed

client/src/Try/API.purs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module Try.API
66
, Suggestion(..)
77
, SuccessResult(..)
88
, FailedResult(..)
9+
, BundleResult
910
, CompileResult(..)
1011
, get
1112
, compile
@@ -69,24 +70,31 @@ type CompileWarning =
6970
}
7071

7172
type SuccessResult =
72-
{ js :: String
73+
{ unbundled :: String
74+
, bundled :: String
7375
, warnings :: Maybe (Array CompileWarning)
7476
}
7577

7678
type FailedResult =
7779
{ error :: CompileError
7880
}
7981

82+
type BundleResult =
83+
{ bundleFailed :: String
84+
}
85+
8086
-- | The result of calling the compile API.
8187
data CompileResult
8288
= CompileSuccess SuccessResult
8389
| CompileFailed FailedResult
90+
| BundleFailed BundleResult
8491

8592
-- | Parse the result from the compile API and verify it
8693
instance decodeJsonCompileResult :: DecodeJson CompileResult where
8794
decodeJson json =
8895
map CompileSuccess (decodeJson json)
8996
<|> map CompileFailed (decodeJson json)
97+
<|> map BundleFailed (decodeJson json)
9098

9199
get :: URL -> ExceptT String Aff String
92100
get url = ExceptT $ AX.get AXRF.string url >>= case _ of
@@ -102,8 +110,8 @@ compile :: forall m. MonadAff m => String -> String -> ExceptT String m (Either
102110
compile endpoint code = ExceptT $ liftAff $ AX.post AXRF.json (endpoint <> "/compile") requestBody >>= case _ of
103111
Left e ->
104112
pure $ Left $ printError e
105-
Right { status } | status >= StatusCode 400 ->
106-
pure $ Left $ "Received error status code: " <> show status
113+
Right { status, statusText } | status >= StatusCode 400 ->
114+
pure $ Left $ "Received error status code: " <> show status <> " | " <> statusText
107115
Right { body } ->
108116
pure $ Right $ decodeJson body
109117
where

client/src/Try/Container.purs

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,11 @@ import Ace (Annotation)
66
import Control.Monad.Except (runExceptT)
77
import Data.Array (fold)
88
import Data.Array as Array
9-
import Data.Either (Either(..), either)
9+
import Data.Either (Either(..))
1010
import Data.Foldable (for_, oneOf)
1111
import Data.FoldableWithIndex (foldMapWithIndex)
1212
import Data.Maybe (Maybe(..), fromMaybe, isNothing)
1313
import Data.Symbol (SProxy(..))
14-
import Data.String as String
15-
import Data.String (Pattern(..))
16-
import Data.String.Regex as Regex
17-
import Data.String.Regex.Flags as RegexFlags
1814
import Effect (Effect)
1915
import Effect.Aff (Aff, makeAff)
2016
import Effect.Aff as Aff
@@ -24,7 +20,6 @@ import Halogen as H
2420
import Halogen.HTML as HH
2521
import Halogen.HTML.Events as HE
2622
import Halogen.HTML.Properties as HP
27-
import Partial.Unsafe (unsafeCrashWith)
2823
import Try.API (CompileError(..), CompileResult(..), CompilerError, ErrorPosition)
2924
import Try.API as API
3025
import Try.Config as Config
@@ -168,6 +163,10 @@ component = H.mkComponent
168163
H.liftEffect $ error err
169164
H.modify_ _ { compiled = Just (Left err) }
170165

166+
Right (Right res@(BundleFailed _)) -> do
167+
H.liftEffect teardownIFrame
168+
H.modify_ _ { compiled = Just (Right res) }
169+
171170
Right (Right res@(CompileFailed { error })) -> do
172171
H.liftEffect teardownIFrame
173172
H.modify_ _ { compiled = Just (Right res) }
@@ -182,7 +181,7 @@ component = H.mkComponent
182181
_ <- H.query _editor unit $ H.tell $ Editor.AddMarker MarkerError pos
183182
pure unit
184183

185-
Right (Right res@(CompileSuccess { js, warnings })) -> do
184+
Right (Right res@(CompileSuccess { bundled, unbundled, warnings })) -> do
186185
{ settings } <- H.get
187186
if settings.showJs then
188187
H.liftEffect teardownIFrame
@@ -192,20 +191,7 @@ component = H.mkComponent
192191
_ <- H.query _editor unit $ H.tell $ Editor.SetAnnotations anns
193192
pure unit
194193
let
195-
importRegex :: Regex.Regex
196-
importRegex = either (\_ -> unsafeCrashWith "Invalid regex") identity
197-
$ Regex.regex """^import (.+) from "../([^"]+)";$""" RegexFlags.noFlags
198-
replacement = "import $1 from \"" <> Config.loaderUrl <> "/$2\";"
199-
codeFixImports = js
200-
# String.split (Pattern "\n")
201-
# map (Regex.replace importRegex replacement)
202-
finalCode = String.joinWith "\n" $ codeFixImports <>
203-
[ ""
204-
, ""
205-
, "main();" -- actually call the `main` function
206-
]
207-
208-
eventData = { code: finalCode }
194+
eventData = { code: bundled }
209195
H.liftEffect teardownIFrame
210196
H.liftAff $ makeAff \f -> do
211197
runEffectFn3 setupIFrame eventData (f (Right unit)) (f (Left $ Aff.error "Could not load iframe"))
@@ -396,14 +382,16 @@ component = H.mkComponent
396382
Left err ->
397383
renderPlaintext err
398384
Right res -> case res of
385+
BundleFailed { bundleFailed } -> do
386+
renderPlaintext bundleFailed
399387
CompileFailed { error } -> case error of
400388
OtherError err ->
401389
renderPlaintext err
402390
CompilerErrors errs ->
403391
HH.div_ $ renderCompilerErrors errs
404-
CompileSuccess { js } ->
392+
CompileSuccess { unbundled } ->
405393
whenElem state.settings.showJs \_ ->
406-
renderPlaintext js
394+
renderPlaintext unbundled
407395

408396
whenElem :: forall w i. Boolean -> (Unit -> HH.HTML w i) -> HH.HTML w i
409397
whenElem cond f = if cond then f unit else HH.text ""

server/Main.hs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
{-# LANGUAGE LambdaCase #-}
44
{-# LANGUAGE OverloadedStrings #-}
55
{-# LANGUAGE PatternGuards #-}
6+
{-# LANGUAGE FlexibleContexts #-}
67

78
module Main (main) where
89

@@ -28,6 +29,7 @@ import qualified Data.Map as M
2829
import Data.Text (Text)
2930
import qualified Data.Text as T
3031
import qualified Data.Text.Encoding as T
32+
import qualified Data.Text.Lazy.Encoding as TLE
3133
import Data.Time.Clock (UTCTime)
3234
import GHC.Generics (Generic)
3335
import qualified Language.PureScript as P
@@ -44,11 +46,15 @@ import qualified Language.PureScript.Make.Cache as Cache
4446
import qualified Language.PureScript.TypeChecker.TypeSearch as TS
4547
import qualified Network.Wai.Handler.Warp as Warp
4648
import System.Environment (getArgs)
47-
import System.Exit (exitFailure)
49+
import System.Exit (exitFailure, ExitCode (ExitSuccess))
4850
import System.FilePath.Glob (glob)
4951
import qualified System.IO as IO
5052
import Web.Scotty
5153
import qualified Web.Scotty as Scotty
54+
import Text.RE.TDFA.Text (ed, (?=~/), compileSearchReplace)
55+
import System.Process.Typed (readProcess, byteStringInput, byteStringOutput, setStdout, proc, setStdin)
56+
import Data.Text.Encoding (encodeUtf8)
57+
import Text.RE.TDFA (re, (*=~), matches)
5258

5359
type JS = Text
5460

@@ -159,8 +165,36 @@ server externs initNamesEnv initEnv port = do
159165
case response of
160166
Left err ->
161167
Scotty.json $ A.object [ "error" .= err ]
162-
Right (warnings, comp) ->
163-
Scotty.json $ A.object [ "js" .= comp, "warnings" .= warnings ]
168+
Right (warnings, comp) -> do
169+
regex <- compileSearchReplace "^import (.+) from \"../([^\"]+)\";$" "import $1 from \"./output/$2\";"
170+
let
171+
fixImports :: Text -> Text
172+
fixImports s = s ?=~/ regex
173+
callMainWrapper :: Text -> Text
174+
callMainWrapper s = s <> "\n\nmain();"
175+
codeWithImportsFixed = callMainWrapper $ T.unlines $ fixImports <$> T.lines comp
176+
esbuild =
177+
setStdin (byteStringInput $ BL.fromStrict $ T.encodeUtf8 codeWithImportsFixed)
178+
$ setStdout byteStringOutput
179+
$ proc "esbuild"
180+
[ "--bundle"
181+
, "--platform=browser"
182+
, "--format=esm"
183+
, "--external:big-integer"
184+
, "--external:decimal.js"
185+
, "--external:react"
186+
, "--external:react-dom"
187+
, "--external:react-dom/server"
188+
, "--external:uuid"
189+
]
190+
191+
(exitCode, out, err) <- readProcess esbuild
192+
case exitCode of
193+
ExitSuccess -> do
194+
let bundled = T.decodeUtf8 $ BL.toStrict out
195+
Scotty.json $ A.object [ "unbundled" .= comp, "bundled" .= bundled, "warnings" .= warnings ]
196+
_ -> do
197+
Scotty.json $ A.object [ "bundleFailed" .= T.decodeUtf8 (BL.toStrict err) ]
164198

165199
get "/search" $ do
166200
query <- param "q"

trypurescript.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ executable trypurescript
3131
http-types -any,
3232
transformers -any,
3333
mtl -any,
34+
regex -any,
3435
text -any,
3536
time -any,
37+
typed-process -any,
3638
warp -any
3739
hs-source-dirs: server
3840
main-is: Main.hs

0 commit comments

Comments
 (0)