Turn Any Data Source into GraphQL With StepZen
with Carlos Eberhardt
StepZen allows us to combine multiple backends into a single GraphQL API. In this episode, Carlos Eberhardt will teach us how it works and how we can get started!
Topics
Resources & Links
Transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hello, everyone. And welcome to another episode of Learn with Jason! Today on the show, we have Carlos Eberhardt. Carlos, thank you very much for joining us. How are you doing today?
CARLOS: I'm doing great. I hope this will be fun.
JASON: I'm excited to hang out with you. Let's talk about you. For folk the not familiar with your work, you want to give us a background?
CARLOS: Sure, my name is Carlos Eberhardt. I work at a company called StepZen now, kind of an early startup. And we're building a product that helps create a single API out of a bunch of different data sources. In the past I've done a lot of different things. Spent most of my time, kind of formative years, I guess, at a large retailer in the Minneapolis area doing a bunch of different roles. And from there, slid over into sort of the -- the more enterprise software world working for an API management company that got acquired. And now with we've started something new.
JASON: Great! Great, great. And so, we talked a little bit about -- we're getting some love for your T-shirt in the chat.
CARLOS: I didn't even plan it.
JASON: Yeah, welcome, everybody. It's good to see you. I see a lot of names. Brandon, hey, what's up! Brandon, welcome back. And, yeah, so, let's talk about a little bit about StepZen and kind of the problem that it solves. Maybe start with the problem. I'm gonna take a track at framing this. So, the challenge that I see myself and others run into when we start taking this -- this new exciting world of headless by storm is that there is a service for everything. I can -- if I want to take payments, I can go grab Stripe right now. I can go set up a store with BigCommerce or -- set up a blog with Strapi or Prismic or Sanity or any of these, right? I can set up all different services, I can stand up my own APIs. I can reach into APIs from, you know, all sorts of other services that I'm using to manage my stuff. And this is really powerful. Means I can build anything and I don't have to learn how to build these backend services. But the challenge comes that I now am instead of managing like one data source -- which was the -- that's the promise of monolithic apps. When you hear somebody talk about why a monolith is a good thing, actually, what they mean is, it's -- it's all in one place. You know where everything is, you know where it's coming from, you know where the code is. And this distribution via headless gives us a lot of benefits. There's a huge number of reasons why going to this decoupled architecture and going API-first, there are benefits. But the challenge is we lose that benefit of knowing where everything is and where everything comes from. So, that's the challenge. Do you want to talk a little bit about how -- well, first of all, did I get that right? Is that the right challenge that steps into yourself?
CARLOS: Right. I think that's a fair way to put it. You could argue that challenge is what some of the old API management processes and companies tried to resolve too, right? I have a much different systems and I want to put a facade on top of them so it's easier to access them and manage them. We didn't really see that happen a lot with sort of -- in the enterprise space, anyway, with companies that kind of adopted an API management. They didn't necessarily do, I'm gonna build a single API for an app. And it's gonna compose everything that it needs. And I think that's what we're seeing as being a really powerful pattern for some of these -- as you said, kind of these headless sort of app situations where instead of having to manage, you know, the logic of mixing data sources together, or even sometimes it business logic in, for example, the Jamstack world, you've got sort of frontend markup and you have APIs on the back. And if those APIs aren't connected it's to the, you're doing that on the frontend. And that leads to a lot of sort of sketchy stuff happening. We think that you can take -- and specifically, we think that GraphQL is really well-suited to solve this problem. And as long as you can kind of get everything into a nice GraphQL schema, you've got one endpoint. And you can do all of the sort of API management things you need to worry about in terms of protection and authorization and everything on a single endpoint and either spin that up very easily for a single app. Or reuse that for multiple apps. There's a lot of flexibility that you get in doing something like this.
JASON: Yeah, yeah. Thank you very much for the sub, by the way, Cassidy. Welcome. This is actually -- you're bringing up something. And this is a little bit of a hot topic that I see come up from time to time which is the concept of GraphQL in general. And it seems like there are two extreme views on GraphQL. And then a lot of use cases kind of fall in the middle. But the extremes seem to be something like what you're talking about or what Gatsby talks about where the idea is that GraphQL is the right solution in the majority of cases. It simplifies things, it unifies things, et cetera. And then the other argument is that GraphQL is almost always an over-complication. And so, you know, depending on who you're talking to or which developer -- whose story you're reading, it feels like you're gonna get two very different takes on GraphQL and its utility and its value in a system. So, I would love to actually just dig into a little bit with you. When you're thinking about GraphQL, you said that, you know, GraphQL is the right abstraction for this. What do you see as its strengths? And like, you know, what -- what are the tradeoffs and why are they worth it?
CARLOS: Yeah, yeah. First off, I was in the camp -- when GraphQL first calm out I was working at this API company. I was a recovering Rastafarian in terms of hypermedia and all that. When GraphQL came out, everything is a disaster, everything is a post. You're posting where all you're doing is retrieving data and it just seemed like it was over-complicated things. And what really switched it for me was when I started looking at -- I think and that is still fair. If I had a single API that I was working with that was a nice, clean REST API and --
JASON: Sorry, you're on a timer here, we're about to drown.
CARLOS: I would maybe lean towards saying REST is okay. Everything is covered there. As you mentioned at the start, now there's so many different systems that we end up talking to with a lot of different apps. And what GraphQL makes really nice is moving that connection logic, or the joining logic to the backend so the frontend doesn't have to worry about it. And you can control it at the backend. You don't have to start worrying, where are my keys for all these different systems? Are they living somewhere I need to pay attention to? Or hide that somewhere? So, I think I've sort of moved away from thinking that it's an over-complication just through usage. And I think -- I don't want to decide for anyone else, but I have a feeling that if you tried that, as someone who is like, oh, this is overly complicated. If you could play with it in sort of a simple way, you would start to realize that it's actually not that over-complicated and another thing that you can do is you can simplify your schemas. So, you don't necessarily have to build a monster schema that has every field in the database, every table in the database. If it's easy enough to do, you can make multiple schemas and tune them for what you need to do. So, you can kind of simplify even the complexity of the schema itself.
JASON: Yeah. And, you know, what? One of the things that you brought up there was this idea of like the -- the complexity of it, right? And what I really have -- like my argument in favor of GraphQL is that it takes away the need for every frontend team to understand the full complexity of setting up data access for every instance. And whey like -- you know, like when you're talking about any implementation, very rarely are we talking about actually removing complexity entirely. Usually what we're doing is we're moving it somewhere else that's less cumbersome to manage. And what I've seen with GraphQL is that we've taken this complexity that was at the UI layer. Everybody who worked in the UI needed to be aware and have manage this complexity of this is where the data comes from, this is what the actual URL of the end point is, this is the authentication schema for each one of these endpoints, et cetera, et cetera, et cetera. And then you -- you had to like deal with that and keep track of it and share these tokens around. When you move it into GraphQL, what you've done is you've taken that away from all the frontend developer who is aren't dealing with like the middle tier, the data access. They don't have to care anymore. They have to explore the data through the GraphQL endpoint, pull out what they need and build and work. And all that complexity moves down to just the set of developers who are actively managing GraphQL itself. Because that gets centralized, you get this ability to do better caching. You get the ability to do better security. You get the ability to -- you know, all of these benefits kind of fall out of consolidating that complexity into one domain. And that, to me, feels like where GraphQL really starts to shine is, you know, I don't want every developer on my team to have to know about or care about auth. You know? That's a hard concept when you're a, you know, first year developer to have to figure out like, where do I put headers in requests?
CARLOS: I mean, the more you make everyone know everything, the risk goes up for people doing the wrong thing. That's a very enterprise thing to say. But it's kind of how it is. There is a bit of a risk, I know. It's super-important that you mention kind of moving complexity around. Because in my experience, from talking to frontend Devs who consume APIs and things like that, very good at designing sort of just what they need on a frontend. Also, in my experience, working with a lot of backend folks, they're not necessarily as good as -- at designing those interfaces, right? It's like I have a database here. I'm gonna expose everything. That was -- that was one of the things we always used to talk about was there is sort of a different opinion of an outside-in versus an outside-in approach. And if you move the design and curation of that API all the way to the backend folks, you're more likely to get sort of an inside-out interface which doesn't necessarily make things simpler.
JASON: Sure.
CARLOS: When I was at the retailer, we had a product table with 1500 columns. Weird code names that meant different things to different systems. You don't want to just barf that out to your frontend Devs. It doesn't make sense to me. Especially as you're working with -- as we see more and more now, you're working with third-party companies building things for you. Building mobile app experiences, whatever it happens to be. You don't want them to learn all of your internal knowledge about how things work. I do think that there's still value in creating that facade-like layer. But with a GraphQL API. So, similarly if I what the frontend folks or the consuming side needs to know and also give the complexity and capabilities to the backend so that they can make sure that essentially, hey, this is a really nice clean API. It's also secure. We can optimize it, et cetera, et cetera.
JASON: Right.
CARLOS: And over time we can change how this API is implemented, what systems it's provided to. If I switch map providers, or mapping geolocation providers, I can swap that on the backside and the front side never needs to care.
JASON: Right. And I really do love that part of GraphQL that we have the ability to simplify, to augment, to extend the data sources that are in the background in a way that doesn't need to modify the underlying system. In a way that doesn't need to mess with the front end Devs. We can't, as you said, like it's honestly it's kind of a bad idea to just -- to just expose like unlimited fields to a frontend Dev because we'll use one for a purpose, oh, well, we need a unique identifier. So, I'll throw in this whatever field that kind of looks like an identifier. It appears to be unique for everybody. But we don't know what that field actually is. And then something goes weird and we've accidently broken stuff. And, you know, it causes a lot of -- it causes a lot of like confusing issues.
CARLOS: Yep.
JASON: And so, I do love this idea of -- again, when we consolidate this control, we can make thoughtful decisions about it. One of the big challenges I had when I was at IBM, for example, is we had dozens of teams. And each of these teams controlled one part of a moving system. And all of them were evolving at the same time. So, at any given moment you were likely to see a new release of at least one of those teams per day. And usually those would include some thing that would augment the way your system worked. Most of the time you wouldn't touch it, but sometimes you would get an unexpected break. We didn't have good ways for the teams to speak to each other. You have 30 plus points of contact, getting high context Communication is not a high tractable problem, we couldn't do it. But what we could do by centralizing the GraphQL is make it easy for each team, okay, we can communicate to one team, to the GraphQL team, that we've made a change. And the GraphQL team could make sure that we deprecated the field properly, added thing are abstraction. Made it possible for people to understand, oh, this field that I'm using now throws a warning now that I have the API. It's deprecated and goes to the change log for the team that made the change. We started to see it as it was the right intermediary because it didn't cause extra work for the frontend teams because the GraphQL team built that abstraction on top. It caused less work for the UI teams, things were less predictable, they were in one place. That justified the existence of the GraphQL team and ended up with us being able to move much, much faster. So, oh, yeah. Anthony's posting the project that we did. Gramps was the name of the project. This was before things like GraphQL had federation and schema stitching and things like to. So, we built a really kind of hackie implementation at IBM of throwing everything at the wall and trying to make it work. And it was good, it was a plugin-based schema thing. But, yeah. So, anyways, that's -- like, as you can probably tell from the way I'm talking about this, I fall more on the GraphQL is often a good abstraction. And worth the effort of adoption. But yeah. Anyways, just -- just kind of thinking about that. So, StepZen. How does StepZen, I guess, like -- when we're talking about the unique advantage here, it's using GraphQL. How does it make it easier to do the things that we have been talking about? These abstractions and auth management and stuff like that?
CARLOS: There's a couple of things we do. Without going into too much feature-diving talk. When we look at stuff later on, maybe we can get into that. Essentially, it's a configuration-driven system. You don't have to write code for resolvers and things like that. So, if you have a database, there's a configuration, a GraphQL directive, on how to connect to that database. And we put some intelligence into the system, oh, okay. If you're talking to this database, what table? And if you designed a schema on top of that, we will coerce what comes back into that schema for you. So, it's essentially just -- I'm defining my SDL and then I'm using some custom GraphQL directives, here's how you fill this SDL when you get a request for this type. And then we've got a few other sort of constructs. It's not -- I don't think it's rocket science. But we make it really easy to deploy bundles of schema and configuration values to different endpoints. So, if I have a team that sort of builds my customer data, they can define their schema and have that available as sort of like the whole thing, right? This is everything that we've got. And then it's very easy for another team to come along and say, take that schema and strip out -- and make it fit exactly what they want. And deploy just that to their own endpoint. So, that they're not having to follow that whole main schema. And you can tie those things together. Since it's all configuration-driven, it's fairly easy to build up automation around this for a CI/CD process as well so you can have the controls in place to make sure changes aren't happening willy nilly. A lot of that would apply for to sort of the enterprise space or a mid-size company. We do have customers who are, you know, single application-focused that are using it primarily just to -- to build GraphQL APIs for -- in a sense almost each page of their application so that the frontend doesn't have to do any kind of business logic as well, right? So, it's everything is designed so that when I navigate from page to page, there's a GraphQL query that goes along with that. If I'm making a change, there's a mutation that goes in, here's what we're submitting. When the user does X, this is everything that happens, when the user goes here, this is everything that we need. And it moves that business logic into sort of a schema definition so that it makes it very, very easy for them to control on the backside and make sure the app behaves the they that they want.
JASON: Gotcha. Okay. At this point I have questions. But I think the easiest thing would be to just start looking at it. So, before we do that, though, I want to do a quick round of congratulations. First of all, chat, that was easily the most chaotic opening that we've done on the show in weeks. Congrats -- you hit every single piece of chaos available in the overlay. Well done! And Carlos, like a pro, you didn't even flinch. You just handled the madness and carried on. So, congratulations to everybody! You all did great! So, let's switch over to the pair programming view here. And let's do a shoutout to our live captioning. We've had Amanda with us since the jump doing live captioning. And she's here from White Coat Captioning. Thank you so much. Captioning is made possible through the support of our sponsors, Netlify, Fauna, Hasura, and Auth0 are kicking in to make this show more accessible to more people. Means a lot to me. I appreciate it. Today we are talking to Carlos, give him a follow on Twitter. We are also going to be using StepZen. So, go and check that on out. Okay. So, at this point, we've talked about what StepZen is, and the benefits of GraphQL. I think at this point the easiest thing we can do to go further is to actually start using this thing. So, what are my first steps if I want to get it started?
CARLOS: Yeah. So, let's assume that you've kind of looked at the website and you've said, yeah, this sounds kind of interesting. I want to poke at it. I can do a few different things and you've read all of our marketing bits. Just click sign up in the upper right there. And you can sign in with GitHub.
JASON: All righty.
CARLOS: Right now what we're doing is we've got an account that we will hand you. And you probably don't want to go to my account right now because you'll reveal some screens. So, if you want to do that off-screen, that would be handy. And those are essentially your credentials to log into the -- to the system. We have a --
JASON: Got it. Okay. Let me create a -- a new project here. You hackers! You dirty hackers! Do I need to like use a generator to create this?
CARLOS: Not yet. But we probably do need to install the CLI. So, let's start with that.
JASON: Okay. Let me do this real quick. What I will do is I'm gonna open up just a -- place where I can drop these keys.
CARLOS: Oh! I nearly forgot. I do have a little starter repo in our samples directory. Which it doesn't do much, but it has a little bit of information in there that will help us as we start to build us out. And let's start there with the directory. And then we can install the CLI and go from there.
JASON: All right. So, I have stored those. There a place that I go to get -- should I just leave this off-screen here?
CARLOS: I'm not sure which is which.
JASON: Sorry, I'm in the my account. I've copied the admin and API keys out in a place where I can get them again.
CARLOS: You're gonna need your account name. The name of some sort.
JASON: Got it, got it.
CARLOS: And the admin API key. Those are the thing use need to log in with and then we won't need them again.
JASON: Okay. Next, let me pull up -- you hackers
You dirty hackers! I'm going to -- is quick start the right place to go?
CARLOS: It's going to walk you through installing the CLI. Let's do that.
JASON: StepZen CLI. Okay. I'm gonna run npm install. Let me get this a little bit higher and this a little bit lower.
CARLOS: It works if you wanted to use the copy button. But you never know. We could --
JASON: Oh, right! Copy button. I could have hit that.
CARLOS: You can always speak stuff into your pace buffer, though. This should just take a second. Oh, and requires Node 14. We're probably okay there. There's probably a couple of warnings. But I think we're okay. Oh! Yeah, can you pop over to 14?
JASON: Yeah, definitely.
CARLOS: And then let's redo that.
JASON: Nope. Go, StepZen.
CARLOS: I love Node for hacking and playing around. I'm less in love with it when it comes to stuff like this because there's so many version changes. Now we're here. You can do a StepZen login. And it should prompt you for your account name which you copied.
JASON: Okay. And then I need an admin key. So, I'm gonna pull this off screen.
CARLOS: It masks it.
JASON: Oh, it does mask it. Okay. Let me --
CARLOS: It's just the web page doesn't mask it.
JASON: Got it. Okay.
CARLOS: There you go.
JASON: Now I have successfully logged in.
CARLOS: You have logged in. Let's clone the starter repo. If you have the GitHub -- yep. There you go. It's under StepZen-samples. And it's called starter.
JASON: Okay.
CARLOS: And you can throw that right in this directory if you want.
JASON: I'm gonna call this one... StepZen so that I actually remember what it is.
CARLOS: Cool.
JASON: And let's get in there.
CARLOS: Go in there. And then we can either poke around on the -- there is no npm install. It's just stuff, yeah.
JASON: Oh, it's no npm install, huh?
CARLOS: No, we're all just configuration at this point.
JASON: Oh! Okay. I gotcha.
CARLOS: It's going to take this bundle and upload it and create an endpoint for us when we do that.
JASON: Okay. Got it. Let's make this a little bit easier to scan. Make this a bit smaller. Okay. So, we're in the README. Inside of the README, I see sample GraphQL.
CARLOS: Yep. Everything is commented out. But this is just GraphQL schema. This is a couple little thing. And this is the configuration sample right now where we would put API keys or data source names or anything that's secret that we want StepZen to know about but we don't necessarily want anyone else to know about. So, we can share schemas with each other and not share the config. So, you could build a really cool schema that does a bunch of stuff and says you need to use Fauna and this API and that API.
JASON: I gotcha.
CARLOS: And somebody would say, okay, I need to create the configuration on my side and you could use the same stuff.
JASON: Gotcha, gotcha, gotcha. So, looking at this, we've got our index.
CARLOS: Indexes where we kind of -- that is going to certainly collect all of the other SDL files we want to use. Sample is in there right now. We can take that out when we actually upload something.
JASON: Okay.
CARLOS: And we'll build a new schema. We'll start from scratch and get going. What I would we would do is build weather.graphQL. We'll build a weather API. It's a little dull. There's a ton of companies. We'll do one for free. US weather only because of using government services.
JASON: Okay.
CARLOS: But this will show you something unique and hopefully give you a chance to come up with some interesting questions and things like that. Okay. First, find a search window and type in NWS API and that will get us to what we need to get to pull things in. And it is the --
JASON: Got it.
CARLOS: Weather.gov. This is sort of the process that I'm thinking of. I've got an API that I want to use. I want to pull it into my GraphQL schema. How do I do? Well, the first thing I need to do is learn how to use that API. That's something that's still there. Let's jump right over to examples. Because, you know, it's government, there's a lot of words. And so, here, how do I get the forecast? This is what we want to do. We want to get the forecast. So, it looks like we have to make that kind of a call with an office and a grid X and a grid Y. But you don't know that. You're jumping to the right spot. We need to make two calls to get the forecast. We need to get that and get the office and then use that office to get the forecast.
JASON: Okay.
CARLOS: So, let's make that first call. And if you just take the example API in there, see what that pulls up. The one for the points, not below, the one for the forecast.
JASON: Oh, for the points.
CARLOS: Do that process first. Take in the lat long, and then we'll get the office and then we'll get the office and get the forecast.
JASON: Gotcha.
CARLOS: Simple REST API stuff. What we want to do is scroll down a little bit and find the data that we want. So, it's a little -- I might need to put on glasses.
JASON: Let me make it bigger.
CARLOS: Point. Scroll down a little bit more. This is starting to look good. Properties.
JASON: Oh, hey! Look! Those look familiar.
CARLOS: And look at the thing right above it. Top. That looks like the office name. But they called it gridId.
JASON: Got it.
CARLOS: We have gridId, gridX, and gridY, one and a string. And let's go back over to code and create a graph that will have that information. That's all we care about.
JASON: Okay. Sure. Back to here. What should I call this one do you think?
CARLOS: I would call this WXPoint, it's what it's called in their stuff. You could call it anything. We need a grid ID.
JASON: That's a string. Is this standard GraphQL? I mark it at required?
CARLOS: Yep.
JASON: Then we have a gridx. That is an Int.
CARLOS: Yep, Int.
JASON: gridY: Int. Anything else?
CARLOS: No, that's all we need. We're just going to grab that data. We could do more. And we've got some tooling that will auto-Hoover in these JSONs and sort of build you a sample schema. But we're not gonna use any of that stuff today. Okay. So, we've got a type define. Now we need to tell StepZen, how do I call and get that type? Let's make a new type query and build a query for it right in here. And it's handy that you know what you're doing. Because otherwise I would be saying a lot of letters. Let's call this getWXPoint.
JASON: Okay.
CARLOS: And bring in two arguments, right? Which one is the lat. And that's a long --
JASON: Is float a valid?
CARLOS: Yep, float. Sorry. Yep. Float is right. And LNG, or whatever you want to call it, actually, perfect.
JASON: No, wait, it should be lng. That makes more sense.
CARLOS: It will be easier later on, but we have ways to do that. Right after that close paren we need to tell it the type of the query.
JASON: Right. That's going to return a WXPoint.
CARLOS: Exactly. I don't know if you need -- doesn't matter, that's fine. Okay. Open your curly brace. Wait.
JASON: No, I think -- yeah, this was me getting myself confused.
CARLOS: Yep, yep, okay.
JASON: Yeah.
CARLOS: So, now we need to tell steps -- we have a query, but StepZen doesn't know what to do. There's a query and these parameters and get data from somewhere. It could be coming from anywhere. Now we're going to introduce one of the StepZen directives called @rest. You can do it there. What does a rest endpoint need to know? It needs to know the endpoint it's gonna call. Too bad we don't have our StepZen plugin ready, we would be able to telesense a lot of this stuff for you. Take that URL that you called.
JASON: This one.
CARLOS: Yep. Just copy that sucker and just drop it right in there. Okay. Now obviously we're not gonna call the same thing everything time. We need to pump in those variables from the query. And the way we do that is with a dollar sign and a var name. It will be dollar sign lat and dollar sign lng. There's one trick here, because this URL has a comma in it, we need really clear telling StepZen where the variable ends. Put a semicolon after lat. Otherwise it gets confuse the.
JASON: Right. It would pick that up as a word character.
CARLOS: Yes. That should be good. The next thing we need to do -- StepZen knows given a lat and lng, how do we take what comes back and put it into the type that I'm expecting to return, right? So, if we look at the JSON for the response again in the browser window, we'll see that these gridX, gridY and that other thing --
JASON: So, it's gonna be like response.properties.gridX.gridY.
CARLOS: You don't need to do that much even. Go back to the code.
JASON: Back to the code.
CARLOS: Yes. Just type in the name of this argument for the REST connector is resultroot. All one word, lower case. And there we just need to tell it properties. One word.
JASON: I like that. This is intuitive. This makes sense to me.
CARLOS: Once you play with it, it gets more and more intuitive. Trust me, there's some gotchas that will come up. Save this. Save this file. Go over to our index.graphql. And change that to say weather.
JASON: Okay.
CARLOS: There you go. Save that. Pop open a terminal here. And you can type in stepzen start. This will do a couple of things. One, it will validate your schema to make sure there's no missing times. First, where do you want to put it? It gives a name. You can change it. I usually do something like that, yeah.
JASON: Okay.
CARLOS: And now it it's deploying it.
JASON: And --
CARLOS: It's gonna take over your browser here. It should --
JASON: Took me to. Let me copy-paste this out.
CARLOS: Make sure you get it there. If you tell it to, it will tell you that you deployed it to a live URL. Easthills. That's where all this stuff is diploid. We pop up a local proxy. It's easy to do it with graphical. You can see that it works. It you hop over to that localhost window and click the explorer button.
JASON: I love that you put the explorer in here.
CARLOS: Yeah. So, there it is. And now -- you need to use numbers that are in the US.
JASON: Okay. So, let's look at -- let's get like -- let's see... I'm in Portland.
CARLOS: Which I would have to guess is like, yeah, a 45 and minus 122.
JASON: Okay. So, if I put in 45 and then I put in 122... it's minus 122 to go west, is that right?
CARLOS: Yep.
JASON: Okay. And then I want to get the grid. X and Y.
CARLOS: Cool.
JASON: Look at it go!
CARLOS: It kind of looks like the three-later code for a Portland office.
JASON: Yes. And then we can validate this pretty quickly, right? We can run this query. Let's change this out to be PQR, and then 112-102.
CARLOS: Yeah.
JASON: 112, 102. And let's see out weather looks in Portland.
CARLOS: Properties, periods and then this -- they have basically today, tonight, et cetera, and you can see --
JASON: Yeah!
CARLOS: Cool, right?
JASON: Yeah. And this looks -- I mean, this all looks --
CARLOS: It's accurate, anyway.
JASON: Let's look at Portland weather. Let's go to the weather.
CARLOS: I'm not monitoring your account on the StepZen side and frantically typing in the results.
JASON: So, this is really cool, right? So, now we have -- we've got the right thing coming back.
CARLOS: Yep.
JASON: It's pulling up a forecast that looks accurate.
CARLOS: Yep.
JASON: And, you know, that's just from the weather service, not from us.
CARLOS: Right.
JASON: It's doing the right thing. This is cool. This is really cool.
CARLOS: We made one API call. We need to make the other one. If all I did was this, it's not as useful of a GraphQL API.
JASON: Sure.
CARLOS: Let's add one that makes that weather call.
JASON: Okay.
CARLOS: We need a type for the forecast. We can make this as complete or as not as you want. But if you look at the properties for the -- what was the name of it? Periods. Let's just -- I think these are the fields that we're gonna want to add. So, we'll do number, name, you know, and if you want to just copy and paste those and quickly eliminate -- there you go. And that's gonna be an int.
JASON: The name --
CARLOS: While we're doing this that's useful.
JASON: Let's go with --
CARLOS: Grab start time and end time though. Because then I get to talk about a StepZen thing.
JASON: Okay. You want me to put these in date times?
CARLOS: Exactly, we've got a DateTime and do coercion into a DateTime for you.
JASON: Okay. Grab the temperature. And that's going to be -- I wonder if it goes --
CARLOS: I put float when it did it myself. I've only seen ints.
JASON: Then it was temperatureUnit is gonna with a string. Don't need wind.
CARLOS: Short forecast is nice. If you were going to build a web appear, endpoint is cool. You have a thing on your page. Essentially, getting a little repetitive. But if you wanted to it be useful, grab all the fields and then I can do whatever I want to.
JASON: Okay. That --
CARLOS: Cool.
JASON: Seems useful.
CARLOS: Yep. So, there's your type. Oh, there's one other thing. Let's look at one other thing just quickly I wanted to point out. On that response, there was a null in there. Under temperature trend, right? So, we don't really know what type that is. So, how would we do that on the StepZen side? We've got a type called JASON, all caps. If you see a JSON type, and something comes in here, just whatever is there, flump it in as JSON. The nested structure,it will pull that in. Sometimes a string, it will be a string, et cetera.
JASON: Okay. Great. And we can leave that as nullable since it might come in as null.
CARLOS: Unless you get into the real everything is strongly typed and I know the specifics. When I'm screwing around, I leave most of the stuff as nullable. A lot of times with the REST API, there's not a lot of rules. If I ask for the weather in Portland, always null this out.
JASON: No parens, no rules.
CARLOS: Exactly. We have the type in place. Let's make a query to pull that type out.
JASON: Okay. So, my query it pull that type out is going to be getForecast.
CARLOS: I'm doing to get pointForecast, we will have time to do something fun later.
JASON: Okay.
CARLOS: What do we need when we make that call? We need the office. Let's call it office just for fun. String, yep. And then we need a gridX and a gridY.
JASON: GridX was an int, gridY is also an int.
CARLOS: Yep.
JASON: And that is going to return a forecast? Or an array of forecasts?
CARLOS: An array of forecasts, exactly. So, bracket those. There you go.
JASON: Okay. So, for folks who aren't familiar with this, this ensures that we don't get any null results. And that we don't get a null object. But we can get an empty array. So, it will either be an empty array, or if it's not empty, everything inside the array will be a forecast. This one was hard more me when I first looked at it, doesn't it mean it's going to fail if it's empty? No, it will fail from it's an empty array or an array of forecasts.
CARLOS: Yep. This is all super-valuable stuff with GraphQL that I have to admit I usually don't take advantage of because I'm lazy. And I just let things null out. Especially when I'm building something. And then you can always go back and tighten this stuff up. That's another nice thing about not having to build resolvers for all of this. You just let the schema do the work. Okay. This is at REST again. And you can just drop it right underneath it if you want. Yeah. There you go. Endpoint, I would do the same thing. We're gonna just copy over that URL. And replace the values.
JASON: Okay. So, this one is office.
CARLOS: Yep.
JASON: This one is gridX and this one is gridY.
CARLOS: Yep. And again, you need a comma in there. Drop that in just to make sure we don't get confused and result root on this is a little bit different because it's under properties.
JASON: Properties. Periods.
CARLOS: Properties, periods. So, I'm gonna let you guess.
JASON: Now, this one, it's an array. So, I'm wondering if it's like this, or I'm wondering if it's more like this?
CARLOS: It's close to both of those. It's not either, though.
JASON: Okay.
CARLOS: It is properties.periods. And then just throw brackets at the end of it telling it that we're going to look for a list.
JASON: Gotcha. Gotcha, gotcha.
CARLOS: And that should be it. So, if we save. Is your terminal still running?
JASON: Good question. Yes, it is.
CARLOS: Okay. So, if you save, it will auto deploy. And then if you reload this guy, we should see a new -- there grow.
JASON: Cool! Okay. So, we had figured out that it was peak UR112.102. Okay. So, 112, 102, PQR, and lets be all of it.
CARLOS: and look at that.
JASON: Cool. And we can see, it gave us back an array. And each of these is one of these periods objects.
CARLOS: Yep. Yep. Exactly.
JASON: That's -- that's cool.
CARLOS: Cool. So, we've kind of got a free weather API. At least for the US. I can get myself a forecast. And the National weather Service has a lot of data. So, you could start to do the same type of thing to build out all kinds of fun stuff. And it's all free, which is awesome. But this is still -- I don't think this is great, still. Because I'm making two calls. If I have a lat long, I get my office and then I get my point forecast. So, let's make a third query that combines those two together. In one. So, we don't need any new types because we're all doing the same thing. Let's call this query getForecast.
JASON: All right.
CARLOS: And this one's gonna take a lat and a long of floats.
JASON: Okay.
CARLOS: Just like that. Exactly.
JASON: Let me take a guess. And because of that, we're gonna be able to do this, is that right?
CARLOS: Yep.
JASON: Nice.
CARLOS: Yep. So, now we need to tell StepZen how is it gonna solve this? It's not making a REST call. What it's doing is doing something we call a sequence. So, it's @sequence. And the first thing, if I remember correctly is steps. So, yeah, sequence has steps. I think we missed an opportunity to call it steps with a Z. But that's just me. In there, we've got curly braces.
JASON: Curly braces.
CARLOS: No, you were right. You've got --
JASON: Okay.
CARLOS: The list and each of the steps is within a curly brace. So, we're gonna do a query for steps. So, it's just query, colon and the name of the query in quotes, which is getWXPoint. So, StepZen is going to do that first. Now we make another step. And I'm gonna make a mistake intentionally just to show you something. And then this is getPointForecast. If you guess what the mistake is, that's awesome. But save this and try to upload and we should get an error on your console. There you go.
JASON: WXpoint office doesn't exist.
CARLOS: It doesn't know how to find office.
JASON: We need to map grid ID to office.
CARLOS: Yep.
JASON: I'm pretty impressed here because it got everything else.
CARLOS: It's because GraphQL -- it's the schema. It can look at it and say, oh, this takes this and I'm getting this. And, yeah, it doesn't match. So, there's another attribute of this step that we had called arguments. And again, those square brackets, curly brackets because this could be a list of things. And let's -- what do we call this one? I think it's name. So, what's the argument name, first off? Nope. It's just name -- not quotes.
JASON: Oh, right, right, right. I don't know what I'm doing here.
CARLOS: I do that all the time. What is the argument name? It's office. And then we have something called field. What field do we find office in? So, field and that is gridId. Yeah. You got it.
JASON: Okay. That makes sense. Let's see if it's giving us errors now. It is not.
CARLOS: Happy.
JASON: Get forecast. Okay. Now my latitude, longitude. And go 45 and it was negative 122.
CARLOS: Roughly good. Oh, that's gonna be a null, right?
JASON: All right. That's the only one that we didn't want.
CARLOS: The one that comes back null. There you go.
JASON: Okay.
CARLOS: So, it just -- and basically StepZen, we do caching on our side. What happened is we hit off two queries, that's why this was so quick when it came back. Ran it the first time, got the point, got the forecast. Then you just asked for didn't fields, but it was essentially the same calls that were going out the backside. We could serve all of that up from cache.
JASON: Gotcha.
CARLOS: Cool, right? If I had to do this on a web page, okay, whip out Axios and get my thing and parsing that. What fields do I need? Grab those. None of this is impossible. But it's nice to do it just in one simple GraphQL call.
JASON: What I like about this is that there's plumbing happening here. Like where for me, as a frontend developer, I want to get a list of the forecasts so that I can show it on a page.
CARLOS: Yep.
JASON: I don't really want to think about how to make this call to this call to this call. And more importantly, like a huge problem they used to have when I was working at IBM, actually, one of the reasons we went toward GraphQL. We didn't have good training for frontend developers to do like all these REST calls. And so, they all built them differently. They would use didn't tools, they would mismatch libraries so we would have three versions of Axios deployed to our frontend. Or one person would be using caching and it was done well. And one person would be making that same request 50 times because they needed like that source data to make a subsequent request for comments and they didn't know how to cache. It wasn't part of their experience or expertise. So, they would just make that call every time. And if the API wasn't caching for 'em, they didn't know any better. They just hit, hit, hit, and suddenly we're hammering our APIs with our frontends. It's nobody's fault. It's just a lack of training, lack of -- we're taking somebody out of their expertise.
CARLOS: Yep.
JASON: So, by going to GraphQL, now I would have a hard time accidently being inefficient here.
CARLOS: It's still possible. Trust me.
JASON: Sure, sure.
CARLOS: But if you're smart about it, yeah. You absolutely would. And you were on say a team that was really thinking about how are we gonna do this? You would say, okay, here's what we want on the frontend. You would design your types and your queries from sort of a frontend perspective. And think, how do we map these up on the backend? And the backend folks could do that so that you actually get -- rather than one side just own the whole thing --
JASON: Right.
CARLOS: You separate out that knowledge and make sure that the people that have the most at stake. I'm a frontend guy sometimes too. And I really don't care if I hammer an API a hundred times or one time. If it works. Right? I'm solving a problem, it works. Performance is okay? Great. But the backend guys, absolutely. I might be paying for some of those calls.
JASON: Right.
CARLOS: Costs money. I really do care. So, separating that out I think is super-useful. Now, there's a couple -- there's another thing I could show you here. This isn't great here. I would really love to just type in an address.
JASON: I would love to be able put in a city name.
CARLOS: I shared an API key with you earlier.
JASON: Yes, let me grab that one.
CARLOS: There's a couple things we haven't done. We haven't put any secrets into this. We haven't shown how that works. We should show how if somebody needs to do that, they can do that. And there's another directive that's really powerful that I wanted to show you as well. So, this one, I'm using the API I'm using is called -- it's by a company calls HERE. It's pretty straightforward. What I thought I would do is I would just kind of tell you what -- because I'm --
JASON: Is this one here?
CARLOS: Yeah. No offense to these guys. But the docs are a little bit troublesome to navigate. It might be quicker if I just tell you what to type in because there's not that much stuff.
JASON: Sure.
CARLOS: Or I could message it to you too, I guess. But first let's get a geolocation thing working. So, let's go over to code. VSCode and make a new file called location. Location.graphql.
JASON: Location dot graph -- if I could spell it. The thing I like least about GraphQL is having to type PHQL. I never, ever get it right. Okay.
CARLOS: Now here we're going to put it in a type. Let's just call it address.
JASON: Address.
CARLOS: No, location. That's fine. You be you. And we wanted to have a title, which is a string. Because this is kind of nice to see sometimes. And these, again, this is just coming from the HERE API stuff. And then a lat and a long which are floats.
JASON: Okay. Anything else?
CARLOS: Nope. That's it. That's all we need. The HERE API does a ton of great stuff. It's a fantastic API, fast, lots of information. But this is all we really care about here. So, let's call it locate, I guess. And it takes -- or whatever you want to call it. The name doesn't matter too much. It's easy. It takes a single parameter called Q.
JASON: Q. Oh, like query.
CARLOS: Because it doesn't have to be a city.
JASON: Okay. I get ya. I get ya.
CARLOS: A box, where you want the weather. It can be a city or whatever. And that's gonna return a location. Yeah. Now we do @rest again. And I'll tell you the endpoint is -- there you go. HTTP --
JASON: And it was result root.
CARLOS: Yep. There's two things we need.
JASON: Okay.
CARLOS: Endpoint is HTTPS, whack, whack, geocode.search.hereapi.com/v1/geocode. This is the most boring part of the stream so far, I think. And then question mark. And there's two parameters we're gonna use. API key.
JASON: Like this? Or lower case?
CARLOS: It doesn't matter. We're designing what it is. But it should just be lower case according to them. I don't think they care. But equals dollar sign apikey. And q equals q. Dollar sign Q.
JASON: I don't need it.
CARLOS: It's only when you're doing something kind of funky with injecting it into -- there you go.
JASON: Okay. There's our big thing. Double checking, slash geocode, and the API key variable that we have not set, and Q, which will be this one, which is a query string.
CARLOS: Yep. So, resultroot is gonna be items with the square brackets.
JASON: Okay. Oh, does this need to be a -- an array, then?
CARLOS: We're just gonna take the first one.
JASON: Okay.
CARLOS: I've seen it return, like if you put in Sao Paulo, for example, there's a bunch of those cities in the world, you can get multiples. We'll just worry about one. And doing something else, the way this response is, it's a little bit of nested JSON. Here's the match, and then a position element which inside of it has a lat and a long.
JASON: Gotcha.
CARLOS: What I want to do is pull those up to the top type. This is something you may do for various reasons. But the way we do that is with an attribute called setters. So, new line and call it setters. And this is, again, is a list of things. So, and in curly braces, we are setting a field called lat. And that is in a path. There's a path. Called -- and that is gonna be position.lat.
JASON: Okay. So, let me -- let me walk through this to make sure I understand what we're doing. So, what we're getting back from the API is we're going to get back items and then items is gonna be an array. And inside each one we're gonna get a name. And then we'll get a position.
CARLOS: Yep.
JASON: And inside that, we're gonna get lat.
CARLOS: Yep.
JASON: And long.
CARLOS: Exactly. Exactly.
JASON: Okay. And what we've done here --
CARLOS: We would have take an look at it, you could have seen it. But just in the interest of time. I wanted to --
JASON: And so, what we have done here is basically you're going to get this result and the result root is items. So, once we've done that, it's gonna go in and take us down to this point. So, now this is what's being sent into our fields for each entry. And then we're saying for the lat, which is this one, we want to find that at position.lat which brings us into this object here.
CARLOS: Yep.
JASON: So, that's -- good. Okay. All right. That makes sense. I can follow that. And so, then to do the longitude, we'll do the same thing.
CARLOS: Yep, yep. And this admittedly is a bit of a, you know -- I've kind of set it up so that I can talk about this thing, obviously. But I wanted to make sure that we understood that there are also ways -- rather than just grabbing the structure, we can pick and choose and pull things out. And you can even do this without the result root and just set paths on all the fields if you have to really get surgical and pull in there.
JASON: Gotcha, yeah.
CARLOS: It's just a different way of kind of getting at that data. Okay. So, there's one more thing we need for the REST thing. As you mentioned, we don't have the API variable key anywhere. So, we need a configuration.
JASON: Like fully spelled out.
CARLOS: Yep, fully spelled out. Call it here API or whatever you want. Just in text. It's just a string.
JASON: Oh, like -- oh, oh! We're basically defining a key in the config doc.
CARLOS: Exactly.
JASON: It's gonna do look. I understand.
CARLOS: You can put multiple variables in there --
JASON: Here?
CARLOS: We need to call it this and rename it to config.yaml. And then the name is gonna be -- yep. We can just pick that sucker and rename it and you can leave the other one there, it's fine. And this is gonna be API key. And then paste in the API key I gave you. If you leak it, that's fine. I can kill it later.
JASON: Can we set that an environment variable?
CARLOS: Yeah, we can. We can. It's got be prefixed with StepZen underscore. So, do StepZen_APIkey, or HERE key or whatever.
JASON: Like that? Yep. And then set an environment variable to that API key.
JASON: Okay. If you're okay to roll the key, put that in. What we could do is run this -- like in here, we could do StepZen, here API key --
CARLOS: Yep, yep.
JASON: Equals key. And then we would run StepZen start. And that would let us pull that. When we deploy, we would just set this in StepZen? Where do we set it for it to get picked up by StepZen?
CARLOS: What the CLI does when you're doing this, it says, hey, I see a value in the config file that is StepZen underscore. This looks like there's an environment variable. I will see if there's environment variables to substitute in when I upload to StepZen, the cloud service.
JASON: Okay.
CARLOS: There's a few theories about how you want to run things. But typically it's the YAML to secrets. It's not something I would check into GitHub, but I manage through another process. We have another way to build this, if you have a process, it will do that sort of thing.
JASON: Okay.
CARLOS: Okay. So, where are we? We still need to add this location.graphql to our index before we do anything. So, it should be all set to go. Add location.graphql. And we're also near the end here, I think. Save this sucker. We should --
JASON: There it goes.
CARLOS: Hopefully it works. Looks like it works.
JASON: Okay.
CARLOS: If we referenced a config name that didn't exist in our configure, StepZen would yell at us too. It would say, hey, I don't know what you're talking about.
JASON: Okay.
CARLOS: Now just throw in --
JASON: You just put in like Portland?
CARLOS: Free form. Type what you want. And, yeah. There you go. There it is.
JASON: Look at it go!
CARLOS: It's pretty quick, right?
JASON: Okay. So, now I want to wire these up. I want to make this thing all the way -- all the way automated. So, if I go back in here, can I simplify this even further and just say, like city?
CARLOS: Totally could do that.
JASON: Okay.
CARLOS: Could totally do it that way. Or the other thing you could do is you could go into location, right? Go up into the type. This is a different way to do this. Right there. The type of location. Let's add a new field to that. And call it forecast.
JASON: Yes. Okay. I like this.
CARLOS: This is gonna be an array of forecast, right? Or a list. There you go. And then this uses a -- another directive we got called @materializer.
JASON: Okay.
CARLOS: Great name. And now we just tell it what query to use.
JASON: Materializer sounds a lot like what I would name a metal band.
CARLOS: I love it. Materializer.
JASON: This one would be getForecast. And we have a lat and long, shouldn't have to change anything. It should just work.
CARLOS: We could do the same thing, if fields were named wrong, the argument is here.
JASON: We could map them with arguments.
CARLOS: Do that kind of thing, yeah.
JASON: Okay. So, now...
CARLOS: So, now you see --
JASON: Oh, this is exciting.
CARLOS: Oregon. You don't care --
JASON: I don't care about the lat and longitude anymore. I just want the short far that the, temperature and the unit.
CARLOS: The name is nice. Name is the thing that give use tonight, tomorrow, et cetera.
JASON: Oh, yeah, that's a good call.
CARLOS: Again, that's a little bit of backend knowledge that comes through. There you go.
JASON: Look at this. So, now we can say, I want the weather for Portland --
CARLOS: Yep.
JASON: And it pulls through.
CARLOS: Yeah.
JASON: And, you know, I could get more thoughtful with my query names and stuff. And just say I want to get the weather and put in the name or something. Like, ah, those. Cool. I love -- and here's what I think is magical about this. Is like what we just did is the sort of thing that has to happen one time when you start thinking about the way that something really does come together like that. The way that orchestration works. For the people who are using this on the frontend, because we've got caching in place, because we've got the, you know, the field mapping and everything, what this does for the frontend team is it basically turns this into a non-issue. You don't even need know that this is pulling from two separate APIs and three separate API calls. You're just saying, yeah, we want people to be able to search for their city or whatever. You know? And then pull in their -- and, yeah. So, let's look at -- let's find an address in -- in Portland. Here is a great restaurant. So, we're gonna pull in... where is this address? 734 East Burnside, Portland, Oregon. All right sop, we're going to go to Canard tonight and get some delicious steam burgers. We're going to search for the weather. Now in my weather app, in my restaurant app, for example, I could say, where do you want to go tonight? And you could go to make your reservation and do this search and I could just say, yeah, you can eat outside tonight. It's gonna be clear and kind of warm.
CARLOS: Exactly. Exactly. We didn't do it, but Maps has got a great API as well. Google Maps. Hey, I want to find a restaurant in Portland and then I want to see what the weather is going to be like for the next three days. You can do all of this stuff and put it into one API. So, all of the logic for the experience that I want to build the user, it lives many my call. Right? I don't have to worry about managing keys, et cetera. All that stuff. And then, yeah, this may work. I don't know.
JASON: It does work. Cool. So, this HERE API, you could just search for a restaurant. I mean, that's -- that's really cool.
CARLOS: Yeah.
JASON: And like if we wanted to go to a different city. Like what's another... what's the weather like in Chicago today? Mostly sunny. Yeah. So, okay. I don't think Alinea has a patio, but you could eat on the patio at Alinea tonight.
CARLOS: Yeah. We worked with the REST connector. In the key that was commented out, hi a couple other examples of things you could do. Looking down in the queries, there's REST, we could take in a GraphQL endpoint or DB query, we could hit databases directly as well.
JASON: Yeah, cool. Yeah, yeah.
CARLOS: A lot of that stuff.
JASON: And then if I want to limit my user type, for example, came back with you said 1300 columns, I could define an interface that says just the ones to grab and it will auto trim? That's what this will do?
CARLOS: Yeah, even if you do the type that way. The interface is more interesting when you have two different backends that maybe provide the same data. And you want essentially to say, here's my interface for what, say, shipment tracking is, right? And then I've got a FedEx tracker and a UPS tracker type and all this. And they may have extra fields. But they all satisfy that core interface.
JASON: Yeah.
CARLOS: And then I could do -- what's the GraphQL word for it?
JASON: Resolver?
CARLOS: It doesn't matter too much. But basically I can say, hey, I'm going to be getting delivery status, if it's from UPS, I want this field from UPS.
JASON: Oh, I get it. The fragments.
CARLOS: Exactly. You can do a lot of fun stuff. We touched the surface of, hey, I've got some APIs and I want to put them together.
JASON: This is really powerful stuff. And I can see the benefit here is like one of the things that's challenging about GraphQL is when you start looking at the construction of it as building the GraphQL system. There's the schema.
CARLOS: Yep.
JASON: Then there are resolvers. And then there's the like server, right? And what I like here is -- this is, you know, it's config-driven and that's always a decision that you got to make as team.
CARLOS: Absolutely.
JASON: are we going to be, config is code? Or how are we gonna do this. But what I like about this, for a lot of -- for the 80% use cases, this removes the need to go and build resolvers. You can define the whole thing in one place. You have your STL and you can map things one to the other using these directives.
CARLOS: Yep.
JASON: That feels very convenient. And if I'm thinking about, you know, like I've got a bunch of services and we need to make complex calls with these services, I don't want to necessarily maintain a bunch of custom resolvers when I could do just something like this and say, yeah, throw this one -- slam this query into this query into this query. And all that have turns into a great experience for the frontend Devs and for the user and StepZen is gonna automate the caching and stuff. So, I mean, we -- honestly, we finished faster than I thought we would. This is pretty incredible. Is there anything else that you wanted to show off here?
CARLOS: We could do a database connection if you want. I have one. I don't necessarily know it's that shocking. I have a sample customers table that has addresses and we connect to it and now I get a list of customers. And we can do a materializer again on the customer type that pulls in the weather for that address.
JASON: Yeah.
CARLOS: It's more of the same essentially at that point. I think. Especially since the, you know, the viewers, we're not gonna be able to look at the database. So, you don't really know what is in there. You just see what comes out of StepZen, right?
JASON: Yeah.
CARLOS: The only other thing I wanted to talk about, is maybe -- and this isn't a great thing to talk you through actually doing. But so, the way these services -- because we have a live API. So, if grow and take your query and use a different tool to call that endpoint down at the bottom there, easthills.stepzen.net, you can hit that from a website, et cetera. Right now it's protected via header with an API key. And that is either your admin key or your service key, we call it. There are two keys. The -- the admin key allows you to actually make changes to your schema. That's what the CLI is when is it uploads things. The API or service key, we can recycle these, there's a bunch of them. Is more used for just calling. Calling the queries.
JASON: Okay.
CARLOS: Things. And --
JASON: So, what we could do here is we can go and let's hit this one. Deal with that later. So, we can hit this API.
CARLOS: Yep.
JASON: And we're gonna send in an authorization key. And now -- so, you're saying that API key is read-only?
CARLOS: Yeah. For the -- for -- you cannot make changes to the schema, et cetera. But you can run, you know, essentially you can run any query that's defined. We didn't talk about mutations either. Obviously, we support mutations. If you want to write data to a service or a REST API, you can map that out too.
JASON: Do I drop this straight in or prefixed with --
CARLOS: It's prefixed with APIkey.
JASON: Like that?
CARLOS: Yep.
JASON: Okay. So, I'll drop in that API key. And then many my body, I can send in... send it in raw. And do a query. That's -- that's how that works, I'm pretty sure. And then we can take this query here. Let's see if that explodes on me. It probably will. And then variables is gonna be empty. Bad request. And it's a bad request --
CARLOS: Did doesn't like that body.
JASON: Yeah. We got take all these out.
CARLOS: I haven't used postman, but they do have that little GraphQL button in the type. And I don't know if that is smart enough to just --
JASON: Oh! Just me not reading things. Let's try that.
CARLOS: There you go. Cool.
JASON: Beautiful. Look at it go, everyone. And then if I don't have that header, if I turn this header off...
CARLOS: If you turn it off, you should get a 401.
JASON: Ta-da!
CARLOS: If we had enough time -- your schema right now has all those other queries in it. Right? But in my config file, I can define something we call a predicate. Which essentially says, and we sort of give it a query template. And we can decide whether to allow or deny that template. So, we can basically say, all that you can do with this endpoint is call forecast. Or call locate. That's the only query you could call. And it wouldn't need an API key. So, you can set it up so that if you've got a bunch of different query methods in your schema, but you have one that you want to use on say like a Jamstack site, right? And I don't want to have to worry about managing any API keys, environment variables, anything like that, you could use this idea of a predicate and essentially just open up just a slim little portion of your schema to the world.
JASON: I mean, we've got 17 minutes, Carlos, do you think we can do it?
CARLOS: Oh, I'm gonna have to find an example.
JASON: We definitely don't need to take those kinds of risks.
CARLOS: Let's try it, let's try it.
JASON: Okay.
CARLOS: Let me just navigate over a little bit. And I may end shooting this over to you over Discord.
JASON: Okay.
CARLOS: Cause it's a fair bit of typing.
JASON: So, Tony is asking a question while you're looking for that. Which is, if we do open a predicate and someone who is not auth just Spammed that API, does that affect our usage? Like would it contribute toward our usage limit?
CARLOS: I'm sorry?
JASON: I'm assuming that StepZen has a usage-based kind of model like number of requests or something like that. If we open up a predicate and then somebody else hammered that API, it would hit our --
CARLOS: It counts.
JASON: Okay. So, but that's a thing to consider. If we are not wanting that to happen, then we would want to keep using the API key. And that would --
CARLOS: If you want to secure it. Obviously, I don't think we necessarily have the whole trick with making things magically secure and perfect on the Internet yet. Because that's a big trick. But this does go a bit of the way forward. If you were concerned at all about anything like that, I would recommend still using some sort of a serverless function to call so you've got that layer of misdirection for anyone who wants to try to abuse things. It's just another control point you can turn on and off.
JASON: Yeah, for sure.
CARLOS: So, let me. I'm gonna shoot this you over Discord. It's gonna be YAML. So, we'll see how --
JASON: YAML, YAML, YAML, YAML!
CARLOS: See how that works. This is gonna be -- I just to want say that this is sort of early -- you should --
JASON: YAML, YAML, YAML, YAML, JSON!
CARLOS: This is early stuff. We haven't documented this yet. We're kind of going under the covers a little bit.
JASON: Gotcha.
CARLOS: This level -- this rule set lives at the same level as the configuration set.
JASON: Okay. So, we've got a rule set. And the query --
CARLOS: From somewhere else. Yeah, so, this actually enforces a very specific query. It was looking at my last FM track. So, we need to change this query to manage so that it's only looking up the query that you want to run.
JASON: Okay.
CARLOS: So, find your query and copy that sucker out.
JASON: There we go!
CARLOS: Why is your -- so, your little straight up bar looks a little bit like a slash to me. But that's not it.
JASON: No, it's just getting highlighted for whatever reason.
CARLOS: So, now the cool thing to do would be to use a variable. Make a variable in getForecast.
JASON: Yep. Let's go with... q. That will be a string. And then we'll drop in q.
CARLOS: Yep. And so, under rules, you could just change this predicate to be true. And it would allow any query. You know, any parameter. But if you only wanted to allow looking up Portland, Oregon, for example, you could change that -- actually, you don't even need to use the variables thing. Just say the predicate is true.
JASON: Okay.
CARLOS: What this should do is just allow any getForecast query on that endpoint.
JASON: Okay. And so, that is deploying. And so, now I have my auth header in here.
CARLOS: Turn that sucker --
JASON: Let's run this. It works.
CARLOS: Should work.
JASON: Turn it off. Let's run this.
CARLOS: Ope.
JASON: Oh, wait, it's because I need to change the body to actually have the right name. So, let me go to the body.
CARLOS: And needs to use variables to match.
JASON: We'll call this getForecast and we're going to give it a q: String, q and the variables now. It's gonna be q and we'll say... Le Pigeon, Portland, Oregon. I don't know why I'm only thinking of Dave Rucker's restaurants today. But that's the way it works. It works! Pretty cool stuff.
CARLOS: Pretty cool stuff. There's other things we have planned for this. You know, using job tokens and introspecting parts of those. So, if I get something set up where only logged in users can use those queries. Still to come. Not finalized yet. This is a little bit early. But this is the kind of thing that I think is really slick when you let yourself go of I'm not going to write all the code for this, I'm just going to configure it. I'm going to do extra switches and flips. Now I can do a lot of really cool stuff without a lot of work.
JASON: Yes. I can see -- I can feel how powerful this is in the sense of like -- I don't know what I did here with these like weird -- whatever. I'm not gonna think about that too hard.
CARLOS: Don't worry about it.
JASON: But, you know, we've got this very powerful, very cool setup here where I'm able to look at this and say, yes, I want it to look -- I want it to work like this. I want people to be able to touch this one. I don't want people to have to go and think about what this actually -- like what it works like. How it --
CARLOS: Yeah.
JASON: What it does. I just want them to be able to go and use it.
CARLOS: Yep, yeah.
JASON: Right? And for something low risk. Right?
CARLOS: Yep.
JASON: Like a well-cached, non-sensitive API. Go ahead and hammer on it. It's cached, can't hurt it, right? For something that is more sensitive, we probably want to be more deliberate, require API key access. But what I like is this is a really good onramp if like I just want to expose an API for a service of mine, but I want to use the same API endpoint for like my privileged stuff and my unprivileged stuff.
CARLOS: Yep.
JASON: So, that I can lock down all of the things that need to be behind an API key. Changing user accounting, like to put that in a practical example, let's say I want to build my blog on StepZen. And I'm using a database behind the hood. I want to be able to list blog posts because they're public. And I want anybody to be able to do that. So, now there's an API that lets you get my blog posts. However, to change the publishing status of one of those blog posts it send that mutation, you need to have an API to do that. You need to prove that you have access to this. That way I would be able to have the same API exposed to everybody, but you have specific actions based on your API key that are additionally available to you. I love that.
CARLOS: Yep. Yep. The other thing you could do, super-simple as well. We picked an endpoint to deploy this to when we started, we can change that at any time. The other one is still available if you want it to be, right? You can basically take a schema that's complete and full and deploy it under one spot. And then, you know, take portions of those files or trim the types, whatever, upload that new bundle. I haven't done any work, just edited my schema. Upload to a different endpoint. Now I have two endpoints and decide what to do that way. You get a lot of flexibility. Rather than just writing and service and it's there and needing to spin up another service.
JASON: Right.
CARLOS: We take that bundle and combine into a single schema and get to the endpoint.
JASON: That's super-handy. I love it. And JacobBolda is in the chat, it you do this and combine it with something like Cloudinary, you've basically created the value prop of Gatsby, pulling all your data from all these difference places together at build time. We can now do this at runtime. And I'm also thinking, one question I have is let's say I did want a customer resolver? So, we just showed how to wire together different services.
CARLOS: Yep.
JASON: What if I wanted to pull in -- like Cloudinary has a fetch API. I can put any URL from around the web. I know we don't have time to do it. But we have this icon available to us here. What if I wanted to wrap that icon with a Cloudinary fetch call which, you know, would then become like -- I don't know. Cloudinary icon. Or something like that, right? And then I would want to be able to do that. Is that something I could use StepZen to wire it up?
CARLOS: Yeah, yeah. Because -- so, the materializer can be a query or a mutation too, right? So, if I needed to actually make a change to something --
JASON: Gotcha.
CARLOS: I should double check myself on that. Because I haven't tried it. And it depends on how you define that Cloudinary call. You could define it as a query even though it's technically a mutation. But you could set it up so that it makes that API call. And it would just be materializer and drop in the new query and it, you know, what value do I pull in? Will I pull in -- and I post that up to Cloudinary and then Cloudinary is gonna return something. And there's a type I have for that. And boom, you know, I'm solid that way. So, you can really start to play around with tying things together.
JASON: Right.
CARLOS: And you're going to run into troubles, I haven't been able to do that. But we're stomping them down as fast as we find them right now in terms of some of that stuff.
JASON: Nice. And I see Anthony dropped in the chat how to do WordPress and Cloudinary. I think that includes how to plug that into StepZen. We will put that not show notes. With that, I think we are out of time. Carlos, I think this is awesome. I think this is a really cool service. I think that it's -- if you are in the situation where you find yourself writing these kind of plumbing queries where you're plugging one thing into another thing and you need these value chains to get to data, I really like it. It's -- it seems like something that would be really powerful. If somebody wants to go further, where would you send them for next steps here?
CARLOS: Okay. So, what I would -- sign up for an account and run through the docs. Our intro is okay in terms of touching a lot of different things. It's fairly straightforward, fairly simple. Kind of gets you going fast. And then we've got a few different things along the left-hand side there on what you can try. If I want to connect backends, messing with frontends, how do I make these calls to this stuff.
JASON: Nice.
CARLOS: And GitHub, we have samples there, and dropping them out there and Anthony is on the team, doing a great job of populating that stuff out there. A lot of times the stuff we do on our blog leads to that. Look at that stuff, see if there's something that kind of piques your interest. Or if there isn't, or if you have questions, we do have a Discord chat that you can find on our website. And we've got people looking at that all the time. So, happy to jump in and connect with people.
JASON: Nice.
CARLOS: Yeah. We're at the stage right now where if you have a project that you want to work on and you're stuck, we would love to help you figure it out. That helps us too. We start to see, why did you have a problem? Or, oh, that's a really interesting idea we didn't think of. We need to think about how to support that. We love that kind of feedback.
JASON: You heard it here. You can go straight in here and find Carlos to send feedback directly on Twitter. You can also follow StepZen_dev if you want to send feedback that way. Anywhere else you want people to check? Any other sources?
CARLOS: I think that's probably the best spot. That and the website. Give it a shot, hop on Discord, give us feedback. All that is good.
JASON: There's a Discord link on the doc. You can jump on there. With that, we have had Amanda with us all day doing live captioning. Thank you very much, Amanda. That is through White Coat Captioning who is available for all your captioning needs. That's made possible through the support of our sponsors, Netlify, Fauna, Hasura, Auth0, all kicking in a little bit to make this show more access to believe more people. Means a lot to me. I deeply appreciate it, and I hope you do as well. That's on the home page of the site. And while you're on the home page, check out the schedule. We have some really, really good stuff coming up. We are going to play a game called Battlesnake next week. I truly have no idea what I'm in for. I think it sounds like so much fun. Legit have no idea how it's gonna work. I am terrified. Then we're gonna do streaming data in PyTorch. I don't know anything about Python. This is gonna be a great episode. We're gonna do TwilioQuest which is like a game that teaches you Twilio and like how to do different things. So, this one I think is gonna be super-fun. I'm really excited about that. Modern CSS, we're gonna do UX and UI, notion workflows for content management, Next.js with Contentful. The list goes on and on. So many good people coming up on the show. Check that out, add it in Google Calendar and it will put you on the list so you never miss one. Go to Twitch and smash that follow button. Like and subscribe. What else are you supposed to do? Ring that bell? I don't know. This was super-fun. Carlos, thank you so much for spending time with us today. Any parting words for the chat?
CARLOS: No. I just -- thank you, Jason. This was a great opportunity. I'm really, really happy that I had a chance to do it. And it was fun.
JASON: I had a blast. Boop that horn. Whatever it is you want to do. We're going to find someone to raid. Carlos, thank you again. We will see you all next time!