From b4971f17b77ae967dbd06847a1abe5f4ea94ec27 Mon Sep 17 00:00:00 2001 From: Thomas Sigdestad Date: Fri, 9 Feb 2024 16:52:06 +0100 Subject: [PATCH] added API augmentation section --- docs/api.adoc | 75 +++++++++++++++++++++++++++++++- docs/app.adoc | 13 +++--- samples/guillotine/guillotine.ts | 38 ++++++++++++++++ 3 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 samples/guillotine/guillotine.ts diff --git a/docs/api.adoc b/docs/api.adoc index 151eeb9..ead8df5 100644 --- a/docs/api.adoc +++ b/docs/api.adoc @@ -236,6 +236,77 @@ image::morgan-original.png["The original version of Morgan Freemans photo is wid NOTE: The red "autofocus" circle, when set, helps the image service to crop the images optimally - as you can see above. -== One final step +== API augmentation -Knowing how headless a CMS can get with an API calle Guillotine, and GraphQL queries flowing from your fingertips. It's time for the big finale where you <>. +Now the real magic begins! You programmatically augment and extend the Guillotine API. The use-cases are limitless, but rather than babbling about it - why not try it out yourself? + +We'll keep it simple. In the next steps you'll add a new `age` field to the Person content type, and use the `dateofbirth` to calculate the persons age. + +. From the `samples/` folder of your app, *copy or move* the `guillotine/` folder to `src/main/resources/`. You should then have the following TypeScript controller ready: ++ +./src/main/resources/guillotine/guillotine.ts +[source,TypeScript] +---- +include::{sourcedir}/samples/guillotine/guillotine.ts[] +---- ++ +. Guillotine requires the app to be redeployed (or restarted) in order to pick up changes to schemas and/or controllers. Stop the build (using control-c) and start it again: ++ + ^c + enonic dev ++ +. Back in Query Playground, run the following query: ++ +.Query using the new field +[source,GraphQL] +---- +{ + guillotine { + getChildren(key: "/persons", first: 2) { + displayName + ... on com_example_myapp_Person { + data { + age + dateofbirth + } + } + } + } +} +---- ++ +The response should now contain a new age filed, with a calculated value: ++ +.Query response +[source,JSON] +---- +{ + "data": { + "guillotine": { + "getChildren": [ + { + "displayName": "Léa Seydoux", + "data": { + "age": 38, + "dateofbirth": "1985-07-01" + } + }, + { + "displayName": "Jeffrey Wright", + "data": { + "age": 58, + "dateofbirth": "1965-12-07" + } + } + ] + } + } +} +---- + + +As you have now seen, XP lets you run server-side https://developer.enonic.com/docs/xp/stable/framework[TypeScript and JavaScript code]. API augmentation is just the tip of the iceberg - believe us. + +== One last thing + +With GraphQL queries flowing from your fingertips. It's time for the big finale where you <>. diff --git a/docs/app.adoc b/docs/app.adoc index 2fbe919..6979202 100644 --- a/docs/app.adoc +++ b/docs/app.adoc @@ -67,18 +67,17 @@ Assuming `mysandbox` is still running in another Terminal window, run these comm cd myapp enonic dev -The last command will build and deploy the app to `mysandbox` - then keep watching for changes in the code to automatically rebuild as you work on it. +The last command will build and deploy the app to `mysandbox`. [NOTE] -==== -Look for the following output to verify that the app has been built: +=== +The initial build may take a while to setup, look for these lines to confirm it has completed - BUILD SUCCESSFUL in 6s - 3 actionable tasks: 3 executed - Waiting for changes to input files... +BUILD SUCCESSFUL in 6s +3 actionable tasks: 3 executed +Waiting for changes to input files... ==== - == Moving forward You just created and built your very own application. In the next chapter you'll get familiar with <>. diff --git a/samples/guillotine/guillotine.ts b/samples/guillotine/guillotine.ts new file mode 100644 index 0000000..2fb52e1 --- /dev/null +++ b/samples/guillotine/guillotine.ts @@ -0,0 +1,38 @@ +// Using the Person data type +const personType = 'com_example_myapp_Person_Data'; + +export const extensions = (graphQL) => { + return { + creationCallbacks: { + [personType]: function (params) { + // Add a new field: age + params.addFields({ + age: { + type: graphQL.GraphQLInt + } + }); + } + }, + resolvers: { + [personType]: { + // Implement the age resolver + age: (env) => { + if (!env.source.dateofbirth) {return null;} + + // Caclulate age + let age = null; + const today = new Date(); + const birthDate = new Date(env.source.dateofbirth); + age = today.getFullYear() - birthDate.getFullYear(); + const m = today.getMonth() - birthDate.getMonth(); + + // Tune for moth and day + if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) { + age--; + } + return age; + } + } + }, + } +}; \ No newline at end of file