packages feed

extism-manifest 0.3.0 → 1.0.0.0

raw patch · 4 files changed

+185/−163 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Extism.JSON: class Typeable a => Data a
+ Extism.JSON: class () => Typeable (a :: k)
+ Extism.JSON: instance GHC.Classes.Eq Extism.JSON.Base64
+ Extism.JSON: instance GHC.Classes.Eq a => GHC.Classes.Eq (Extism.JSON.Nullable a)
+ Extism.JSON: instance GHC.Show.Show Extism.JSON.Base64
+ Extism.JSON: instance GHC.Show.Show a => GHC.Show.Show (Extism.JSON.Nullable a)
+ Extism.Manifest: fromFile :: FilePath -> IO (Either String Manifest)
+ Extism.Manifest: fromString :: String -> Either String Manifest
+ Extism.Manifest: instance GHC.Classes.Eq Extism.Manifest.HTTPRequest
+ Extism.Manifest: instance GHC.Classes.Eq Extism.Manifest.Manifest
+ Extism.Manifest: instance GHC.Classes.Eq Extism.Manifest.Memory
+ Extism.Manifest: instance GHC.Classes.Eq Extism.Manifest.Wasm
+ Extism.Manifest: instance GHC.Classes.Eq Extism.Manifest.WasmData
+ Extism.Manifest: instance GHC.Classes.Eq Extism.Manifest.WasmFile
+ Extism.Manifest: instance GHC.Classes.Eq Extism.Manifest.WasmURL
+ Extism.Manifest: instance GHC.Show.Show Extism.Manifest.HTTPRequest
+ Extism.Manifest: instance GHC.Show.Show Extism.Manifest.Manifest
+ Extism.Manifest: instance GHC.Show.Show Extism.Manifest.Memory
+ Extism.Manifest: instance GHC.Show.Show Extism.Manifest.Wasm
+ Extism.Manifest: instance GHC.Show.Show Extism.Manifest.WasmData
+ Extism.Manifest: instance GHC.Show.Show Extism.Manifest.WasmFile
+ Extism.Manifest: instance GHC.Show.Show Extism.Manifest.WasmURL
+ Extism.Manifest: toFile :: FilePath -> Manifest -> IO ()
+ Extism.Manifest: withMaxPages :: Manifest -> Int -> Manifest
- Extism.Manifest: toString :: JSON a => a -> String
+ Extism.Manifest: toString :: Manifest -> String

Files

CHANGELOG.md view
@@ -1,5 +1,5 @@ # Revision history for extism-manifest -## 0.1.0.0 -- YYYY-mm-dd+## 1.0.0.0 -- 2024-01-08 -* First version. Released on an unsuspecting world.+* Extism 1.0 compatible release
Extism/JSON.hs view
@@ -1,31 +1,45 @@-module Extism.JSON (-  module Extism.JSON,-  module Text.JSON-) where+module Extism.JSON+  ( module Extism.JSON,+    Data,+    Typeable,+  )+where -import Text.JSON import qualified Data.ByteString as B-import Data.ByteString.Internal (c2w, w2c) import qualified Data.ByteString.Base64 as B64 import qualified Data.ByteString.Char8 as BS (unpack)+import Data.ByteString.Internal (c2w, w2c)+import Text.JSON+import Text.JSON.Generic -data Nullable a = Null | NotNull a+data Nullable a = Null | NotNull a deriving (Eq, Show)  makeArray x = JSArray [showJSON a | a <- x]+ isNull JSNull = True isNull _ = False+ filterNulls obj = [(a, b) | (a, b) <- obj, not (isNull b)]+ object x = makeObj $ filterNulls x+ objectWithNulls = makeObj+ nonNull = NotNull+ null' = Null+ (.=) a b = (a, showJSON b)+ toNullable (Just x) = NotNull x toNullable Nothing = Null+ fromNullable (NotNull x) = Just x fromNullable Null = Nothing+ fromNotNull (NotNull x) = x fromNotNull Null = error "Value is Null"+ mapNullable f Null = Null mapNullable f (NotNull x) = NotNull (f x) @@ -34,27 +48,27 @@     Ok x -> NotNull x     Error _ -> Null (.?) _ _ = Null+ (.??) a k = toNullable $ lookup k a -find :: JSON a => String -> JSValue -> Nullable a+find :: (JSON a) => String -> JSValue -> Nullable a find k obj = obj .? k -update :: JSON a => String -> a -> JSValue -> JSValue+update :: (JSON a) => String -> a -> JSValue -> JSValue update k v (JSObject obj) = object $ fromJSObject obj ++ [k .= v] -instance JSON a => JSON (Nullable a) where+instance (JSON a) => JSON (Nullable a) where   showJSON (NotNull x) = showJSON x   showJSON Null = JSNull   readJSON JSNull = Ok Null   readJSON x = readJSON x --newtype Base64 = Base64 B.ByteString+newtype Base64 = Base64 B.ByteString deriving (Eq, Show)  instance JSON Base64 where   showJSON (Base64 bs) = showJSON (BS.unpack $ B64.encode bs)   readJSON (JSString s) =-    let toByteString x = B.pack (Prelude.map c2w x) in-    case B64.decode (toByteString (fromJSString s)) of-    Left msg -> Error msg-    Right d -> Ok (Base64 d)+    let toByteString x = B.pack (Prelude.map c2w x)+     in case B64.decode (toByteString (fromJSString s)) of+          Left msg -> Error msg+          Right d -> Ok (Base64 d)
Extism/Manifest.hs view
@@ -1,133 +1,127 @@ module Extism.Manifest where -import Extism.JSON import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BS (unpack)+import Extism.JSON+import Text.JSON+import Text.JSON.Generic  -- | Memory options newtype Memory = Memory-  {-    memoryMaxPages :: Nullable Int+  { memoryMaxPages :: Nullable Int   }+  deriving (Eq, Show)  instance JSON Memory where   showJSON (Memory max) =-    object [-      "max_pages" .= max-    ]+    object+      [ "max_pages" .= max+      ]   readJSON obj =-    let max = obj .? "max_pages" in-    Ok (Memory max)+    let max = obj .? "max_pages"+     in Ok (Memory max)  -- | HTTP request data HTTPRequest = HTTPRequest-  {-    url :: String-  , headers :: Nullable [(String, String)]-  , method :: Nullable String+  { url :: String,+    headers :: Nullable [(String, String)],+    method :: Nullable String   }+  deriving (Eq, Show)  makeKV x =   object [(k, showJSON v) | (k, v) <- x]  requestObj (HTTPRequest url headers method) =-  [-    "url" .= url,+  [ "url" .= url,     "headers" .= mapNullable makeKV headers,     "method" .= method   ]  instance JSON HTTPRequest where-  showJSON req =  object $ requestObj req+  showJSON req = object $ requestObj req   readJSON x =-    let url = x .? "url" in-    let headers =  x .? "headers" in-    let method =  x .? "method" in-    case url of-      Null -> Error "Missing 'url' field"-      NotNull url -> Ok (HTTPRequest url headers method)-+    let url = x .? "url"+     in let headers = x .? "headers"+         in let method = x .? "method"+             in case url of+                  Null -> Error "Missing 'url' field"+                  NotNull url -> Ok (HTTPRequest url headers method)  -- | WASM from file data WasmFile = WasmFile-  {-    filePath :: String-  , fileName :: Nullable String-  , fileHash :: Nullable String+  { filePath :: String,+    fileName :: Nullable String,+    fileHash :: Nullable String   }+  deriving (Eq, Show)  instance JSON WasmFile where   showJSON (WasmFile path name hash) =-    object [-      "path" .= path,-      "name" .= name,-      "hash" .= hash-    ]+    object+      [ "path" .= path,+        "name" .= name,+        "hash" .= hash+      ]   readJSON x =-    let path = x .? "url" in-    let name = x .? "name" in-    let hash = x .? "hash" in-    case path of-      Null -> Error "Missing 'path' field"-      NotNull path -> Ok (WasmFile path name hash)--+    let path = x .? "url"+     in let name = x .? "name"+         in let hash = x .? "hash"+             in case path of+                  Null -> Error "Missing 'path' field"+                  NotNull path -> Ok (WasmFile path name hash)  -- | WASM from raw bytes data WasmData = WasmData-  {-    dataBytes :: Base64-  , dataName :: Nullable String-  , dataHash :: Nullable String+  { dataBytes :: Base64,+    dataName :: Nullable String,+    dataHash :: Nullable String   }---+  deriving (Eq, Show)  instance JSON WasmData where   showJSON (WasmData bytes name hash) =-    object [-      "data" .= bytes,-      "name" .= name,-      "hash" .= hash-    ]+    object+      [ "data" .= bytes,+        "name" .= name,+        "hash" .= hash+      ]   readJSON x =-    let d = x .? "data" in-    let name = x .? "name" in-    let hash = x .? "hash" in-    case d of-      Null -> Error "Missing 'path' field"-      NotNull d ->-        case readJSON d of-          Error msg -> Error msg-          Ok d' -> Ok (WasmData d' name hash)-+    let d = x .? "data"+     in let name = x .? "name"+         in let hash = x .? "hash"+             in case d of+                  Null -> Error "Missing 'path' field"+                  NotNull d ->+                    case readJSON d of+                      Error msg -> Error msg+                      Ok d' -> Ok (WasmData d' name hash)  -- | WASM from a URL data WasmURL = WasmURL-  {-    req :: HTTPRequest-  , urlName :: Nullable String-  , urlHash :: Nullable String+  { req :: HTTPRequest,+    urlName :: Nullable String,+    urlHash :: Nullable String   }-+  deriving (Eq, Show)  instance JSON WasmURL where   showJSON (WasmURL req name hash) =-    object (-      "name" .= name :-      "hash" .= hash :-      requestObj req)+    object+      ( "name" .= name+          : "hash" .= hash+          : requestObj req+      )   readJSON x =-    let req = x .? "req" in-    let name = x .? "name" in-    let hash = x .? "hash" in-    case fromNullable req of-      Nothing -> Error "Missing 'req' field"-      Just req -> Ok (WasmURL req name hash)+    let req = x .? "req"+     in let name = x .? "name"+         in let hash = x .? "hash"+             in case fromNullable req of+                  Nothing -> Error "Missing 'req' field"+                  Just req -> Ok (WasmURL req name hash)  -- | Specifies where to get WASM module data-data Wasm = File WasmFile | Data WasmData | URL WasmURL+data Wasm = File WasmFile | Data WasmData | URL WasmURL deriving (Eq, Show)  instance JSON Wasm where   showJSON x =@@ -136,112 +130,126 @@       Data d -> showJSON d       URL u -> showJSON u   readJSON x =-    let file = (readJSON x :: Result WasmFile) in-    case file of-      Ok x -> Ok (File x)-      Error _ ->-        let data' = (readJSON x :: Result WasmData) in-        case data' of-        Ok x -> Ok (Data x)-        Error _ ->-          let url = (readJSON x :: Result WasmURL) in-          case url of-          Ok x -> Ok (URL x)-          Error _ -> Error "JSON does not match any of the Wasm types"+    let file = (readJSON x :: Result WasmFile)+     in case file of+          Ok x -> Ok (File x)+          Error _ ->+            let data' = (readJSON x :: Result WasmData)+             in case data' of+                  Ok x -> Ok (Data x)+                  Error _ ->+                    let url = (readJSON x :: Result WasmURL)+                     in case url of+                          Ok x -> Ok (URL x)+                          Error _ -> Error "JSON does not match any of the Wasm types"  wasmFile :: String -> Wasm wasmFile path =-  File WasmFile { filePath = path, fileName = null', fileHash = null'}+  File WasmFile {filePath = path, fileName = null', fileHash = null'}  wasmURL :: String -> String -> Wasm wasmURL method url =-  let r = HTTPRequest { url = url, headers = null', method = nonNull method } in-  URL WasmURL { req = r, urlName = null', urlHash = null' }+  let r = HTTPRequest {url = url, headers = null', method = nonNull method}+   in URL WasmURL {req = r, urlName = null', urlHash = null'}  wasmData :: B.ByteString -> Wasm wasmData d =-  Data WasmData { dataBytes = Base64 d, dataName = null', dataHash = null' }+  Data WasmData {dataBytes = Base64 d, dataName = null', dataHash = null'}  withName :: Wasm -> String -> Wasm-withName (Data d) name = Data d { dataName = nonNull name }-withName (URL url) name =  URL url { urlName = nonNull name }-withName (File f) name = File  f { fileName = nonNull name }-+withName (Data d) name = Data d {dataName = nonNull name}+withName (URL url) name = URL url {urlName = nonNull name}+withName (File f) name = File f {fileName = nonNull name}  withHash :: Wasm -> String -> Wasm-withHash (Data d) hash = Data d { dataHash = nonNull hash }-withHash (URL url) hash =  URL url { urlHash = nonNull hash }-withHash (File f) hash = File  f { fileHash = nonNull hash }+withHash (Data d) hash = Data d {dataHash = nonNull hash}+withHash (URL url) hash = URL url {urlHash = nonNull hash}+withHash (File f) hash = File f {fileHash = nonNull hash}  -- | The 'Manifest' type is used to provide WASM data and configuration to the -- | Extism runtime data Manifest = Manifest-  {-    wasm :: [Wasm]-  , memory :: Nullable Memory-  , config :: Nullable [(String, String)]-  , allowedHosts :: Nullable [String]-  , allowedPaths :: Nullable [(String, String)]-  , timeout :: Nullable Int+  { wasm :: [Wasm],+    memory :: Nullable Memory,+    config :: Nullable [(String, String)],+    allowedHosts :: Nullable [String],+    allowedPaths :: Nullable [(String, String)],+    timeout :: Nullable Int   }-+  deriving (Eq, Show)  instance JSON Manifest where   showJSON (Manifest wasm memory config hosts paths timeout) =-    let w = makeArray wasm in-    object [-      "wasm" .= w,-      "memory" .= memory,-      "config" .= mapNullable makeKV config,-      "allowed_hosts" .= hosts,-      "allowed_paths" .= mapNullable makeKV paths,-      "timeout_ms" .= timeout-    ]+    let w = makeArray wasm+     in object+          [ "wasm" .= w,+            "memory" .= memory,+            "config" .= mapNullable makeKV config,+            "allowed_hosts" .= hosts,+            "allowed_paths" .= mapNullable makeKV paths,+            "timeout_ms" .= timeout+          ]   readJSON x =-    let wasm = x .? "wasm" in-    let memory = x .? "memory" in-    let config = x .? "config" in-    let hosts = x .? "allowed_hosts" in-    let paths = x .? "allowed_paths" in-    let timeout = x .? "timeout_ms" in-    case fromNullable wasm of-      Nothing -> Error "Missing 'wasm' field"-      Just wasm -> Ok (Manifest wasm memory config hosts paths timeout)+    let wasm = x .? "wasm"+     in let memory = x .? "memory"+         in let config = x .? "config"+             in let hosts = x .? "allowed_hosts"+                 in let paths = x .? "allowed_paths"+                     in let timeout = x .? "timeout_ms"+                         in case fromNullable wasm of+                              Nothing -> Error "Missing 'wasm' field"+                              Just wasm -> Ok (Manifest wasm memory config hosts paths timeout)  -- | Create a new 'Manifest' from a list of 'Wasm' manifest :: [Wasm] -> Manifest manifest wasm =-  Manifest {-    wasm = wasm,-    memory = null',-    config = null',-    allowedHosts = null',-    allowedPaths = null',-    timeout = null'-  }+  Manifest+    { wasm = wasm,+      memory = null',+      config = null',+      allowedHosts = null',+      allowedPaths = null',+      timeout = null'+    }  -- | Update the config values withConfig :: Manifest -> [(String, String)] -> Manifest withConfig m config =-  m { config = nonNull config }-+  m {config = nonNull config}  -- | Update allowed hosts for `extism_http_request` withHosts :: Manifest -> [String] -> Manifest withHosts m hosts =-  m { allowedHosts = nonNull hosts }-+  m {allowedHosts = nonNull hosts}  -- | Update allowed paths withPaths :: Manifest -> [(String, String)] -> Manifest withPaths m p =-  m { allowedPaths = nonNull p }+  m {allowedPaths = nonNull p}  -- | Update plugin timeout (in milliseconds) withTimeout :: Manifest -> Int -> Manifest withTimeout m t =-  m { timeout = nonNull t }+  m {timeout = nonNull t} -toString :: (JSON a) => a -> String-toString v =-  encode (showJSON v)+-- | Set memory.max_pages+withMaxPages :: Manifest -> Int -> Manifest+withMaxPages m pages =+  m {memory = NotNull $ Memory (NotNull pages)}++fromString :: String -> Either String Manifest+fromString s = do+  let x = decode s+  resultToEither x++fromFile :: FilePath -> IO (Either String Manifest)+fromFile path = do+  s <- readFile path+  return $ fromString s++toString :: Manifest -> String+toString = encode++toFile :: FilePath -> Manifest -> IO ()+toFile path m = do+  writeFile path (toString m)
extism-manifest.cabal view
@@ -1,10 +1,10 @@ cabal-version:      3.0 name:               extism-manifest-version:            0.3.0+version:            1.0.0.0 license:            BSD-3-Clause maintainer:         oss@extism.org author:             Extism authors-bug-reports:        https://github.com/extism/extism+bug-reports:        https://github.com/extism/haskell-sdk synopsis:           Extism manifest bindings description:        Bindings to Extism WebAssembly manifest category:           Plugins, WebAssembly