aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/PursLoader/Loader.purs
blob: 0cd077d143d49ef712fd6c0f8d8f1b5e9300b7ca (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
module PursLoader.Loader
  ( Effects()
  , loader
  , loaderFn
  ) where

import Prelude (Unit(), ($), (>>=), (<$>), (<*>), (<<<), (++), bind, const)

import Control.Bind (join)
import Control.Monad.Eff (Eff())
import Control.Monad.Eff.Exception (Error(), error)

import Data.Array ((!!))
import Data.Function (Fn2(), mkFn2)
import Data.Maybe (Maybe(..), maybe)
import Data.Either (either)
import Data.Foreign (Foreign())
import Data.Foreign.Class (read)
import Data.Foreign.Null (runNull)
import Data.String.Regex (Regex(), match, noFlags, regex)

import Unsafe.Coerce (unsafeCoerce)

import PursLoader.LoaderRef
  ( LoaderRef()
  , Loader()
  , async
  , cacheable
  , query
  , clearDependencies
  , addDependency
  , resourcePath
  )

import PursLoader.LoaderUtil (parseQuery)
import PursLoader.Options (runOptions)
import PursLoader.Path (dirname, relative)

type Effects eff = (loader :: Loader | eff)

type PurescriptWebpackPluginContext eff = { compile :: (Foreign -> Eff (Effects eff) Unit) -> Eff (Effects eff) Unit }

loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit
loader ref source = do
  callback <- async ref

  cacheable ref

  let parsed = parseQuery $ query ref

      options = either (const Nothing) (Just <<< runOptions) (read parsed)

      moduleName = join $ match moduleRegex source >>= \as -> as !! 1

      resourceDir = dirname (resourcePath ref)

      modulePath = (\opts -> relative resourceDir opts.pscBundle) <$> options

      result = (\path name -> "module.exports = require('" ++ path ++ "')['" ++ name ++ "'];") <$> modulePath <*> moduleName

  clearDependencies ref

  addDependency ref (resourcePath ref)

  pluginContext.compile (\err -> maybe (callback (Just $ error "Failed to run loader") "")
                                       (callback (compileError err)) result)
  where
  moduleRegex :: Regex
  moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true }

  pluginContext :: PurescriptWebpackPluginContext eff
  pluginContext = (unsafeCoerce ref).purescriptWebpackPluginContext

  compileError :: Foreign -> Maybe Error
  compileError value = either (const $ Just (error "Failed to compile")) ((<$>) error) (runNull <$> read value)

loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit)
loaderFn = mkFn2 loader