diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/cabal.project b/cabal.project new file mode 100644 index 0000000..ff32ffd --- /dev/null +++ b/cabal.project @@ -0,0 +1,3 @@ +packages: + . + diff --git a/euler.yaml b/euler.yaml deleted file mode 100644 index ce5859f..0000000 --- a/euler.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: haskell-sequelize -haskell-name: sequelize -allowed-paths: -- sequelize.cabal -- src -- test - -# Disabling tests as they use outdated beam-mysql -disable-tests: true -dependencies: - euler-build: - branch: master - revision: c6af205a7adb1b7abac18f06830f4ed196bfd6e4 - beam: - branch: master - revision: 372542ec6c49d18e8c1c4ef9da15ff0b97c07ed8 - beam-mysql: - branch: master - revision: 1371202ebc3ec7e9ef3e16d1e99f805596022217 diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..f428ad6 --- /dev/null +++ b/flake.lock @@ -0,0 +1,304 @@ +{ + "nodes": { + "beam": { + "inputs": { + "flake-parts": "flake-parts", + "haskell-flake": [ + "beam-mysql", + "haskell-flake" + ], + "nixpkgs": [ + "beam-mysql", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1693307537, + "narHash": "sha256-BIq3ZjZQWQ0w3zWA19zGBggiVVfnOzR5d4b7De0oVZY=", + "owner": "arjunkathuria", + "repo": "beam", + "rev": "06bcc50997fdcfb87125bed252e888e5dd1e6d9c", + "type": "github" + }, + "original": { + "owner": "arjunkathuria", + "ref": "GHC-927-Upgrade", + "repo": "beam", + "type": "github" + } + }, + "beam-mysql": { + "inputs": { + "beam": "beam", + "bytestring-lexing": "bytestring-lexing", + "flake-parts": "flake-parts_2", + "haskell-flake": [ + "haskell-flake" + ], + "mysql-haskell": "mysql-haskell", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1693308989, + "narHash": "sha256-3qyg/Uj3A+MTS494VH2lTBtOz9uptgm+V1M1bPFxTX0=", + "owner": "arjunkathuria", + "repo": "beam-mysql", + "rev": "2ef13d8ecdcd0959b8604b3106b2013baf2ad272", + "type": "github" + }, + "original": { + "owner": "arjunkathuria", + "ref": "GHC-927", + "repo": "beam-mysql", + "type": "github" + } + }, + "bytestring-lexing": { + "flake": false, + "locked": { + "lastModified": 1596188445, + "narHash": "sha256-n/5kFb5msE8NPQZf6bsm8MQh0RGDoOx6EJXoji6FPMs=", + "owner": "juspay", + "repo": "bytestring-lexing", + "rev": "0a46db1139011736687cb50bbd3877d223bcb737", + "type": "github" + }, + "original": { + "owner": "juspay", + "repo": "bytestring-lexing", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1690933134, + "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_2" + }, + "locked": { + "lastModified": 1690933134, + "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_3" + }, + "locked": { + "lastModified": 1690933134, + "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_4": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_4" + }, + "locked": { + "lastModified": 1690933134, + "narHash": "sha256-ab989mN63fQZBFrkk4Q8bYxQCktuHmBIBqUG1jl6/FQ=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "59cf3f1447cfc75087e7273b04b31e689a8599fb", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "haskell-flake": { + "locked": { + "lastModified": 1692741689, + "narHash": "sha256-CbNpheNJMTM9Wz5iTzdXmMtvfH9KvH/jNfv6N9roaqs=", + "owner": "srid", + "repo": "haskell-flake", + "rev": "c8622c8a259e18e0a1919462ce885380108a723c", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "haskell-flake", + "type": "github" + } + }, + "mysql-haskell": { + "inputs": { + "flake-parts": "flake-parts_3", + "haskell-flake": [ + "beam-mysql", + "haskell-flake" + ], + "nixpkgs": [ + "beam-mysql", + "nixpkgs" + ], + "word24": "word24" + }, + "locked": { + "lastModified": 1692868544, + "narHash": "sha256-UY9HRnqWXv5Ud6pfBa/fPNwjauDYpgzJoLcQb4NuH7I=", + "owner": "arjunkathuria", + "repo": "mysql-haskell", + "rev": "2f4861667d19e84474700f32922c97af94f5dfc4", + "type": "github" + }, + "original": { + "owner": "arjunkathuria", + "ref": "GHC-927", + "repo": "mysql-haskell", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1693355128, + "narHash": "sha256-+ZoAny3ZxLcfMaUoLVgL9Ywb/57wP+EtsdNGuXUJrwg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "a63a64b593dcf2fe05f7c5d666eb395950f36bc9", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "dir": "lib", + "lastModified": 1690881714, + "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9e1960bc196baf6881340d53dccb203a951745a2", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib_2": { + "locked": { + "dir": "lib", + "lastModified": 1690881714, + "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9e1960bc196baf6881340d53dccb203a951745a2", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib_3": { + "locked": { + "dir": "lib", + "lastModified": 1690881714, + "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9e1960bc196baf6881340d53dccb203a951745a2", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib_4": { + "locked": { + "dir": "lib", + "lastModified": 1690881714, + "narHash": "sha256-h/nXluEqdiQHs1oSgkOOWF+j8gcJMWhwnZ9PFabN6q0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9e1960bc196baf6881340d53dccb203a951745a2", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "beam-mysql": "beam-mysql", + "flake-parts": "flake-parts_4", + "haskell-flake": "haskell-flake", + "nixpkgs": "nixpkgs" + } + }, + "word24": { + "flake": false, + "locked": { + "lastModified": 1647587255, + "narHash": "sha256-S37S10sJ45BulvpqJzlhX/J4hY7cW5jLM9nP4xAftac=", + "owner": "winterland1989", + "repo": "word24", + "rev": "445f791e35ddc8098f05879dbcd07c41b115cb39", + "type": "github" + }, + "original": { + "owner": "winterland1989", + "repo": "word24", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..412b977 --- /dev/null +++ b/flake.nix @@ -0,0 +1,35 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-parts.url = "github:hercules-ci/flake-parts"; + haskell-flake.url = "github:srid/haskell-flake"; + + ## Use Juspay upstream after PR merged - https://github.com/juspay/beam-mysql/pull/40 + beam-mysql.url = "github:arjunkathuria/beam-mysql/GHC-927"; + beam-mysql.inputs.nixpkgs.follows = "nixpkgs"; + beam-mysql.inputs.haskell-flake.follows = "haskell-flake"; + }; + + outputs = inputs@{ self, nixpkgs, flake-parts, ... }: + flake-parts.lib.mkFlake { inherit inputs; } ({ withSystem, ... }: { + systems = nixpkgs.lib.systems.flakeExposed; + imports = [ + inputs.haskell-flake.flakeModule + ]; + perSystem = { self', pkgs, lib, config, ... }: { + haskellProjects.default = { + projectFlakeName = "sequelize"; + basePackages = pkgs.haskell.packages.ghc927; + imports = [ + inputs.beam-mysql.haskellFlakeProjectModules.output + ]; + settings = { + beam-postgres.check = false; + beam-mysql.jailbreak = true; + generic-lens.check = false; + }; + autoWire = [ "packages" "checks" "devShells" "apps"]; + }; + }; + }); +} diff --git a/sequelize.cabal b/sequelize.cabal index 5709818..3a02ff6 100644 --- a/sequelize.cabal +++ b/sequelize.cabal @@ -25,7 +25,34 @@ library Paths_sequelize hs-source-dirs: src - default-extensions: AllowAmbiguousTypes RankNTypes ScopedTypeVariables StandaloneDeriving EmptyDataDecls FlexibleContexts FlexibleInstances FunctionalDependencies KindSignatures TypeOperators MultiParamTypeClasses TypeFamilies OverloadedLabels OverloadedStrings DeriveFunctor DeriveGeneric DataKinds DerivingStrategies ConstraintKinds UndecidableInstances InstanceSigs BlockArguments LambdaCase EmptyDataDeriving TypeOperators ViewPatterns KindSignatures + default-extensions: + AllowAmbiguousTypes + RankNTypes + ScopedTypeVariables + StandaloneDeriving + EmptyDataDecls + FlexibleContexts + FlexibleInstances + FunctionalDependencies + KindSignatures + TypeOperators + MultiParamTypeClasses + TypeFamilies + OverloadedLabels + OverloadedStrings + DeriveFunctor + DeriveGeneric + DataKinds + DerivingStrategies + ConstraintKinds + UndecidableInstances + InstanceSigs + BlockArguments + LambdaCase + EmptyDataDeriving + TypeOperators + ViewPatterns + KindSignatures ghc-options: -Wall build-depends: aeson @@ -41,6 +68,7 @@ library , text , unordered-containers , vector + , ghc-prim default-language: Haskell2010 test-suite sequelize-test @@ -50,7 +78,34 @@ test-suite sequelize-test Paths_sequelize hs-source-dirs: test - default-extensions: AllowAmbiguousTypes RankNTypes ScopedTypeVariables StandaloneDeriving EmptyDataDecls FlexibleContexts FlexibleInstances FunctionalDependencies KindSignatures TypeOperators MultiParamTypeClasses TypeFamilies OverloadedLabels OverloadedStrings DeriveFunctor DeriveGeneric DataKinds DerivingStrategies ConstraintKinds UndecidableInstances InstanceSigs BlockArguments LambdaCase EmptyDataDeriving TypeOperators ViewPatterns KindSignatures + default-extensions: + AllowAmbiguousTypes + RankNTypes + ScopedTypeVariables + StandaloneDeriving + EmptyDataDecls + FlexibleContexts + FlexibleInstances + FunctionalDependencies + KindSignatures + TypeOperators + MultiParamTypeClasses + TypeFamilies + OverloadedLabels + OverloadedStrings + DeriveFunctor + DeriveGeneric + DataKinds + DerivingStrategies + ConstraintKinds + UndecidableInstances + InstanceSigs + BlockArguments + LambdaCase + EmptyDataDeriving + TypeOperators + ViewPatterns + KindSignatures ghc-options: -Wall -threaded -rtsopts -with-rtsopts=-N build-depends: aeson diff --git a/src/Sequelize.hs b/src/Sequelize.hs index f1525db..35b6924 100644 --- a/src/Sequelize.hs +++ b/src/Sequelize.hs @@ -68,6 +68,7 @@ import qualified Database.Beam.Query.Internal as B import qualified Database.Beam.Schema.Tables as B import GHC.Generics (Generic) import qualified GHC.Generics as G +import GHC.Types (Type) import GHC.TypeLits (Symbol) import Named ((:!), (:?), arg, argF) @@ -98,7 +99,7 @@ isClausesToWhere = fmap (\(IS c v) -> Is c (Eq v)) data IS be table where IS :: (ToJSON value, Ord value, EqValue be value, Show value) => Column table value -> value -> IS be table -data Clause be (table :: (* -> *) -> *) where +data Clause be (table :: (Type -> Type) -> Type) where And :: [Clause be table] -> Clause be table Or :: [Clause be table] -> Clause be table Is :: @@ -254,7 +255,7 @@ instance where getTableField = L.getField @name -class GModelToSets be (table :: (* -> *) -> *) g where +class GModelToSets be (table :: (Type -> Type) -> Type) g where gModelToSets :: g x -> [Set be table] instance @@ -355,8 +356,8 @@ applyOrderBy mbOrderBy_ x = case mbOrderBy_ of applyWhere :: (B.BeamSqlBackend be, B.Beamable table) => Maybe (Where be table) -> - (forall s. B.Q be db s (table (B.QExpr be s))) -> - (forall s. B.Q be db s (table (B.QExpr be s))) + (B.Q be db s (table (B.QExpr be s))) -> + (B.Q be db s (table (B.QExpr be s))) applyWhere mbWhere_ = maybe id (B.filter_' . whereQ) mbWhere_ ---------------------------------------------------------------------------- @@ -573,4 +574,4 @@ fromColumnar' :: B.Columnar' f value -> B.Columnar f value fromColumnar' (B.Columnar' x) = x retypeQOrd :: B.QOrd be s a -> B.QOrd be s b -retypeQOrd (B.QOrd x) = B.QOrd x \ No newline at end of file +retypeQOrd (B.QOrd x) = B.QOrd x diff --git a/src/Sequelize/Encode.hs b/src/Sequelize/Encode.hs index bb57939..0ae2160 100644 --- a/src/Sequelize/Encode.hs +++ b/src/Sequelize/Encode.hs @@ -8,7 +8,8 @@ module Sequelize.Encode where import qualified Data.Aeson as Aeson -import qualified Data.HashMap.Strict as HM +import qualified Data.Aeson.KeyMap as AKM +import qualified Data.Aeson.Key as AesonKey import Data.Kind () import Data.Text (Text) import qualified Database.Beam as B @@ -43,21 +44,21 @@ encodeClause dt w = Or cs -> foldOr cs Is column val -> foldIs column val foldAnd = \case - [] -> HM.empty + [] -> AKM.empty [x] -> foldWhere' x xs | Just maps <- mapM fromIs xs -> mconcat maps - | otherwise -> HM.singleton "$and" (Aeson.toJSON $ map foldWhere' xs) + | otherwise -> AKM.singleton "$and" (Aeson.toJSON $ map foldWhere' xs) foldOr = \case - [] -> HM.empty + [] -> AKM.empty [x] -> foldWhere' x - xs -> HM.singleton "$or" (Aeson.toJSON $ map foldWhere' xs) + xs -> AKM.singleton "$or" (Aeson.toJSON $ map foldWhere' xs) foldIs :: Aeson.ToJSON a => Column table value -> Term be a -> Aeson.Object foldIs column val = let key = B._fieldName . fromColumnar' . column . columnize $ B.dbTableSettings dt - in HM.singleton key $ encodeTerm val + in AKM.singleton (AesonKey.fromText key) $ encodeTerm val fromIs :: Clause be table -> Maybe Aeson.Object fromIs = \case Is column val -> Just (foldIs column val) @@ -97,7 +98,7 @@ encodeTerm = \case Not term -> single encodeTerm "$not" term array :: (a -> Aeson.Value) -> Text -> [a] -> Aeson.Value -array f k vs = Aeson.toJSON $ HM.singleton k $ map f vs +array f k vs = Aeson.toJSON $ AKM.singleton (AesonKey.fromText k) $ map f vs single :: (a -> Aeson.Value) -> Text -> a -> Aeson.Value -single f k v = Aeson.toJSON $ HM.singleton k $ f v \ No newline at end of file +single f k v = Aeson.toJSON $ AKM.singleton (AesonKey.fromText k) $ f v