From 7c93340dda97b42586f930b6a31ceda991d34337 Mon Sep 17 00:00:00 2001 From: Mihovil Ilakovac Date: Wed, 31 Jan 2024 11:38:52 +0100 Subject: [PATCH] Implement wasp/client/crud API (#1700) --- .../templates/sdk/{ => client}/crud/_crud.ts | 1 + .../templates/sdk/client/crud/index.ts | 4 ++ .../data/Generator/templates/sdk/package.json | 4 +- .../.wasp/out/sdk/wasp/package.json | 4 +- .../examples/todo-typescript/src/MainPage.tsx | 2 +- .../todo-typescript/src/Todo.test.tsx | 2 +- waspc/src/Wasp/Generator/SdkGenerator.hs | 2 + .../Generator/SdkGenerator/Client/CrudG.hs | 51 +++++++++++++++++++ .../src/Wasp/Generator/SdkGenerator/CrudG.hs | 30 +---------- .../Wasp/Generator/ServerGenerator/CrudG.hs | 4 +- waspc/waspc.cabal | 1 + 11 files changed, 68 insertions(+), 37 deletions(-) rename waspc/data/Generator/templates/sdk/{ => client}/crud/_crud.ts (99%) create mode 100644 waspc/data/Generator/templates/sdk/client/crud/index.ts create mode 100644 waspc/src/Wasp/Generator/SdkGenerator/Client/CrudG.hs diff --git a/waspc/data/Generator/templates/sdk/crud/_crud.ts b/waspc/data/Generator/templates/sdk/client/crud/_crud.ts similarity index 99% rename from waspc/data/Generator/templates/sdk/crud/_crud.ts rename to waspc/data/Generator/templates/sdk/client/crud/_crud.ts index 24a14bd26f..0516373384 100644 --- a/waspc/data/Generator/templates/sdk/crud/_crud.ts +++ b/waspc/data/Generator/templates/sdk/client/crud/_crud.ts @@ -96,4 +96,5 @@ function createCrud() { } } +// PUBLIC API export const {= name =} = createCrud(); diff --git a/waspc/data/Generator/templates/sdk/client/crud/index.ts b/waspc/data/Generator/templates/sdk/client/crud/index.ts new file mode 100644 index 0000000000..851b9823de --- /dev/null +++ b/waspc/data/Generator/templates/sdk/client/crud/index.ts @@ -0,0 +1,4 @@ +{{={= =}=}} +{=# cruds =} + export { {= name =} } from './{= name =}'; +{=/ cruds =} diff --git a/waspc/data/Generator/templates/sdk/package.json b/waspc/data/Generator/templates/sdk/package.json index 92c05b42fc..e698999273 100644 --- a/waspc/data/Generator/templates/sdk/package.json +++ b/waspc/data/Generator/templates/sdk/package.json @@ -78,7 +78,6 @@ "./test": "./dist/test/index.js", {=! Used by our code, uncodumented (but accessible) for users. =} "./test/*": "./dist/test/*.js", - "./crud/*": "./dist/crud/*.js", {=! Used by our code, uncodumented (but accessible) for users. =} "./server/crud/*": "./dist/server/crud/*", "./email": "./dist/email/index.js", @@ -118,7 +117,8 @@ "./auth": "./dist/auth/index.js", "./client/auth": "./dist/client/auth/index.js", "./server/auth": "./dist/server/auth/index.js", - "./server/crud": "./dist/server/crud/index.js" + "./server/crud": "./dist/server/crud/index.js", + "./client/crud": "./dist/client/crud/index.js" }, {=! TypeScript doesn't care about the redirects we define above in "exports" field; those diff --git a/waspc/examples/todo-typescript/.wasp/out/sdk/wasp/package.json b/waspc/examples/todo-typescript/.wasp/out/sdk/wasp/package.json index 9455246888..5471c7a681 100644 --- a/waspc/examples/todo-typescript/.wasp/out/sdk/wasp/package.json +++ b/waspc/examples/todo-typescript/.wasp/out/sdk/wasp/package.json @@ -44,7 +44,6 @@ "./dbSeed/types": "./dist/dbSeed/types.js", "./test": "./dist/test/index.js", "./test/*": "./dist/test/*.js", - "./crud/*": "./dist/crud/*.js", "./server/crud/*": "./dist/server/crud/*", "./email": "./dist/email/index.js", "./email/core/types": "./dist/email/core/types.js", @@ -64,7 +63,8 @@ "./auth": "./dist/auth/index.js", "./client/auth": "./dist/client/auth/index.js", "./server/auth": "./dist/server/auth/index.js", - "./server/crud": "./dist/server/crud/index.js" + "./server/crud": "./dist/server/crud/index.js", + "./client/crud": "./dist/client/crud/index.js" }, "typesVersions": { "*": { diff --git a/waspc/examples/todo-typescript/src/MainPage.tsx b/waspc/examples/todo-typescript/src/MainPage.tsx index cc400853bd..cb34521acd 100644 --- a/waspc/examples/todo-typescript/src/MainPage.tsx +++ b/waspc/examples/todo-typescript/src/MainPage.tsx @@ -12,7 +12,7 @@ import waspLogo from './waspLogo.png' import type { Task } from 'wasp/entities' import { AuthUser, getFirstProviderUserId } from 'wasp/auth' import { Link } from 'react-router-dom' -import { Tasks } from 'wasp/crud/Tasks' +import { Tasks } from 'wasp/client/crud' // import login from 'wasp/auth/login' // import signup from 'wasp/auth/signup' import { Todo } from './Todo' diff --git a/waspc/examples/todo-typescript/src/Todo.test.tsx b/waspc/examples/todo-typescript/src/Todo.test.tsx index b515530f0e..ce54febd76 100644 --- a/waspc/examples/todo-typescript/src/Todo.test.tsx +++ b/waspc/examples/todo-typescript/src/Todo.test.tsx @@ -7,7 +7,7 @@ import { Todo, areThereAnyTasks } from './Todo' import { MainPage } from './MainPage' import type { AuthUser } from 'wasp/auth' import { getMe } from 'wasp/client/auth' -import { Tasks } from 'wasp/crud/Tasks' +import { Tasks } from 'wasp/client/crud' const mockTasks = [ { diff --git a/waspc/src/Wasp/Generator/SdkGenerator.hs b/waspc/src/Wasp/Generator/SdkGenerator.hs index 043875c0b9..e1621de90a 100644 --- a/waspc/src/Wasp/Generator/SdkGenerator.hs +++ b/waspc/src/Wasp/Generator/SdkGenerator.hs @@ -38,6 +38,7 @@ import Wasp.Generator.Monad (Generator) import qualified Wasp.Generator.NpmDependencies as N import Wasp.Generator.SdkGenerator.AuthG (genAuth) import Wasp.Generator.SdkGenerator.Client.AuthG (genNewClientAuth) +import Wasp.Generator.SdkGenerator.Client.CrudG (genNewClientrudApi) import qualified Wasp.Generator.SdkGenerator.Common as C import Wasp.Generator.SdkGenerator.CrudG (genCrud) import Wasp.Generator.SdkGenerator.EmailSenderG (depsRequiredByEmail, genEmailSender) @@ -118,6 +119,7 @@ genSdkReal spec = <++> genNewClientAuth spec <++> genNewServerApi spec <++> genNewServerCrudApi spec + <++> genNewClientrudApi spec where genFileCopy = return . C.mkTmplFd diff --git a/waspc/src/Wasp/Generator/SdkGenerator/Client/CrudG.hs b/waspc/src/Wasp/Generator/SdkGenerator/Client/CrudG.hs new file mode 100644 index 0000000000..f73cf2c3ee --- /dev/null +++ b/waspc/src/Wasp/Generator/SdkGenerator/Client/CrudG.hs @@ -0,0 +1,51 @@ +module Wasp.Generator.SdkGenerator.Client.CrudG + ( genNewClientrudApi, + ) +where + +import Data.Aeson (object, (.=)) +import qualified Data.Aeson as Aeson +import Data.Maybe (fromJust) +import StrongPath (reldir, relfile, ()) +import qualified StrongPath as SP +import Wasp.AppSpec (AppSpec, getCruds) +import qualified Wasp.AppSpec.Crud as AS.Crud +import Wasp.AppSpec.Valid (getIdFieldFromCrudEntity) +import Wasp.Generator.Crud (getCrudOperationJson) +import Wasp.Generator.FileDraft (FileDraft) +import Wasp.Generator.Monad (Generator) +import qualified Wasp.Generator.SdkGenerator.Common as C +import Wasp.Util ((<++>)) + +genNewClientrudApi :: AppSpec -> Generator [FileDraft] +genNewClientrudApi spec = + if areThereAnyCruds + then + sequence + [ genCrudIndex spec cruds + ] + <++> genCrudOperations spec cruds + else return [] + where + cruds = getCruds spec + areThereAnyCruds = not $ null cruds + +genCrudIndex :: AppSpec -> [(String, AS.Crud.Crud)] -> Generator FileDraft +genCrudIndex spec cruds = return $ C.mkTmplFdWithData [relfile|client/crud/index.ts|] tmplData + where + tmplData = object ["cruds" .= map getCrudOperationJsonFromCrud cruds] + getCrudOperationJsonFromCrud :: (String, AS.Crud.Crud) -> Aeson.Value + getCrudOperationJsonFromCrud (name, crud) = getCrudOperationJson name crud idField + where + idField = getIdFieldFromCrudEntity spec crud + +genCrudOperations :: AppSpec -> [(String, AS.Crud.Crud)] -> Generator [FileDraft] +genCrudOperations spec cruds = return $ map genCrudOperation cruds + where + genCrudOperation :: (String, AS.Crud.Crud) -> FileDraft + genCrudOperation (name, crud) = C.mkTmplFdWithDstAndData tmplPath destPath (Just tmplData) + where + tmplPath = [relfile|client/crud/_crud.ts|] + destPath = [reldir|client/crud|] fromJust (SP.parseRelFile (name ++ ".ts")) + tmplData = getCrudOperationJson name crud idField + idField = getIdFieldFromCrudEntity spec crud diff --git a/waspc/src/Wasp/Generator/SdkGenerator/CrudG.hs b/waspc/src/Wasp/Generator/SdkGenerator/CrudG.hs index 6f3b08284c..30bc7ccdf9 100644 --- a/waspc/src/Wasp/Generator/SdkGenerator/CrudG.hs +++ b/waspc/src/Wasp/Generator/SdkGenerator/CrudG.hs @@ -1,23 +1,15 @@ module Wasp.Generator.SdkGenerator.CrudG ( genCrud, - getCrudTypesImportPathForName, ) where import Data.Aeson (KeyValue ((.=)), object) import qualified Data.Aeson.Types as Aeson.Types -import Data.Maybe (fromJust) import StrongPath - ( File', - Path, - Posix, - Rel, - reldir, - reldirP, + ( reldir, relfile, (), ) -import qualified StrongPath as SP import Wasp.AppSpec (AppSpec, getCruds) import qualified Wasp.AppSpec as AS import qualified Wasp.AppSpec.App as AS.App @@ -28,33 +20,18 @@ import Wasp.Generator.Crud (crudDeclarationToOperationsList, getCrudFilePath, ge import Wasp.Generator.FileDraft (FileDraft) import qualified Wasp.Generator.JsImport as GJI import Wasp.Generator.Monad (Generator) -import Wasp.Generator.SdkGenerator.Common (makeSdkImportPath) import qualified Wasp.Generator.SdkGenerator.Common as C import Wasp.Generator.SdkGenerator.ServerOpsGenerator (extImportToJsImport) -import Wasp.Util ((<++>)) genCrud :: AppSpec -> Generator [FileDraft] genCrud spec = if areThereAnyCruds - then - genCrudOperations spec cruds - <++> genCrudServerOperations spec cruds + then genCrudServerOperations spec cruds else return [] where cruds = getCruds spec areThereAnyCruds = not $ null cruds -genCrudOperations :: AppSpec -> [(String, AS.Crud.Crud)] -> Generator [FileDraft] -genCrudOperations spec cruds = return $ map genCrudOperation cruds - where - genCrudOperation :: (String, AS.Crud.Crud) -> FileDraft - genCrudOperation (name, crud) = C.mkTmplFdWithDstAndData tmplPath destPath (Just tmplData) - where - tmplPath = [relfile|crud/_crud.ts|] - destPath = [reldir|crud|] fromJust (SP.parseRelFile (name ++ ".ts")) - tmplData = getCrudOperationJson name crud idField - idField = getIdFieldFromCrudEntity spec crud - genCrudServerOperations :: AppSpec -> [(String, AS.Crud.Crud)] -> Generator [FileDraft] genCrudServerOperations spec cruds = return $ map genCrudOperation cruds where @@ -91,6 +68,3 @@ genCrudServerOperations spec cruds = return $ map genCrudOperation cruds operationToOverrideImport (operation, options) = makeCrudOperationKeyAndJsonPair operation importJson where importJson = GJI.jsImportToImportJson $ extImportToJsImport <$> AS.Crud.overrideFn options - -getCrudTypesImportPathForName :: String -> Path Posix (Rel r) File' -getCrudTypesImportPathForName crudName = makeSdkImportPath $ [reldirP|server/crud|] fromJust (SP.parseRelFileP crudName) diff --git a/waspc/src/Wasp/Generator/ServerGenerator/CrudG.hs b/waspc/src/Wasp/Generator/ServerGenerator/CrudG.hs index bdf184a8dd..0b5689d582 100644 --- a/waspc/src/Wasp/Generator/ServerGenerator/CrudG.hs +++ b/waspc/src/Wasp/Generator/ServerGenerator/CrudG.hs @@ -24,7 +24,6 @@ import Wasp.Generator.Crud import qualified Wasp.Generator.Crud.Routes as Routes import Wasp.Generator.FileDraft (FileDraft) import Wasp.Generator.Monad (Generator) -import Wasp.Generator.SdkGenerator.CrudG (getCrudTypesImportPathForName) import qualified Wasp.Generator.ServerGenerator.Common as C import Wasp.Generator.ServerGenerator.JsImport (extImportToImportJson) import Wasp.JsImport (JsImportPath (RelativeImportPath)) @@ -96,8 +95,7 @@ genCrudOperations spec cruds = return $ map genCrudOperation cruds "userEntityUpper" .= maybeUserEntity, "overrides" .= object overrides, "queryType" .= queryTsType, - "actionType" .= actionTsType, - "crudTypesImportPath" .= SP.fromRelFileP (getCrudTypesImportPathForName name) + "actionType" .= actionTsType ] idField = getIdFieldFromCrudEntity spec crud maybeUserEntity = AS.refName . AS.Auth.userEntity <$> maybeAuth diff --git a/waspc/waspc.cabal b/waspc/waspc.cabal index 560d20398d..fa227ff71c 100644 --- a/waspc/waspc.cabal +++ b/waspc/waspc.cabal @@ -311,6 +311,7 @@ library Wasp.Generator.SdkGenerator.Client.AuthG Wasp.Generator.SdkGenerator.Server.AuthG Wasp.Generator.SdkGenerator.Server.CrudG + Wasp.Generator.SdkGenerator.Client.CrudG Wasp.Generator.ServerGenerator Wasp.Generator.ServerGenerator.JsImport Wasp.Generator.ServerGenerator.ApiRoutesG