Production-Grade TypeScript

Production-Grade TypeScript Running API Extractor

Learning Paths:
Check out a free preview of the full Production-Grade TypeScript course:
The "Running API Extractor" Lesson is part of the full, Production-Grade TypeScript course featured in this preview video. Here's what you'd learn in this lesson:

Mike runs API Extractor after building the project. The TypeScript declaration files are analyzed, and API Extractor exports the surface reports.

Get Unlimited Access Now

Transcript from the "Running API Extractor" Lesson

>> So that's one thing that happened. We have these three roll ups and let me make it a little bit more clear why I call these roll ups. I wanna create a new folder, a new file here. You don't have to do this and it's not in the notes, but, I just wanna give you something that will help this land.

[00:00:36] All right, so I have a function here called subtract. And I could go into my index Ts, and at the bottom, it could say export, subtract from subtract. And I'm gonna run this report again. I know I forgot to step here, all right? I said this out loud, but I'm forgetting my own advice here.

[00:01:05] The input for API extractor is declaration files. I'm reading that index DTS for my dist folder. And then API extractors taking that in and making new DTS files. So I missed the build step, right? I don't have in my dist folder, I don't have anything in here that looks like my subtract file that I just created.

[00:01:29] So I could do yarn build, I should see subtract pop up, and I do and now let`s run this. Okay, so there we go. We see this subtract function, it appears in these files directly, there's subtract up here, right? It appears in these files directly as if everything is coming from this one module.

[00:01:56] So now it's kinda like react where we're importing, create element. We're importing the react types, like react.function component. All of that's coming from one module, even though my source code is organized differently. There's no trace of this subtract being a separate module of some sort. That's what makes this a roll up, right, we're not seeing references to other files here.

[00:02:24] We're seeing everything in one file, all together, that's why this is called a roll up. I got a warning here as well. And this is saying, I am missing a release tag. And what it's telling me is actually, this is a great error message. Subtract is exported by the package, but it's missing a release tag.

[00:02:44] It's encouraging me to say, look, is this an alpha test, a beta test, public, or internal? Let's make it beta. One little tricky thing here, you're gonna wanna have these dashes between the name of the argument and the description. This tool is particular about that. So we'll say calculate the difference between two numbers, and then we'll mark it as beta.

[00:03:23] If we run this again, we should see, it may complain about other things, but it shouldn't complain about that anymore. Sorry, once again, I forgot my build step. Okay, so now I'm seeing something different and this is super cool. I am seeing a notification that I've changed my public API surface.

[00:03:49] Something I did in this code change. It wasn't just a trivial bug fix, I have changed what I'm exporting in some way. So now it's time for me to show you another thing that gets created by this and it's in that etc folder. This is a markdown file and it's called an API report.

[00:04:09] I'll show you the rendered version cuz this is what you would see if you're browsing GitHub or something. So it's effectively showing you what your public API surface looks like. Now in my TypeScript libraries, I have this built automatically, so every pull request comes with a change to this file.

[00:04:30] So that when you're reviewing your code, you can have a discussion around maybe we decide we're gonna make b like the second argument, subtract, maybe it becomes optional. Let's see what that would look like. We're gonna make a commit, API extractor, basic setup and pushing it. So let's make that second thing optional and let's say, actually, we can make it default to 0.

[00:05:01] And I don't need to specify that it's a number now that it has an initializer. So that's the change I made. And let's say I build and maybe through a Git hook of some sort. We run this API extractor, we generate this new API report. Here's what you would see in a code review.

[00:05:29] You'd see this. Well, look at that, like this makes it super clear in ways that might not be evident just looking at the source code itself. I mean here it's a bit obvious, but I'm sure you can imagine that at scale, small little changes. It's sometimes unclear as to what the bottom line is for your API surface, is this a backwards compatible change to make?

[00:05:57] Raise your hand if you think it is? I'm raising my hand, it's pretty good hint. Look, all the hands went up. [LAUGH] Say it's amazing I as the teacher, I can sort of make everything true. So, this is a backwards compatible change, because if I was passing two numbers before, I can still do that, and it's fine.

[00:06:19] I am opening up a new pointless use case, where I'll take your number and subtract zero from it, like not the best improvement to make to this library. But everything that used to work continues to work as it did. So I would say all right, we can call this a minor release.

[00:06:37] But if it were in the other direction, if it were optional and is now required, that's a major version. It's very easy to see that when you have this like single report on what your exploited API looks like. This is a tool that I didn't even know I needed this much.

[00:06:56] But I it makes it a lot easier to open source things, because I can trust the community to make contributions. And it's very clear to me when something's not gonna affect the public API all that much, and so we can take a little more of a risk there.

[00:07:14] As opposed to setting a new precedent, like whatever change we make, we must forever ensure that that continues to work. That's a big challenge, right? So this makes it super clear what kind of things going on there. So, one last thing, there's this temp folder. So it contains two files.

[00:07:36] First, we have a mark down file that looks just like the API report. This is an identical file right now. And then we have a JSON file. This is the input. This JSON file is what we're gonna use to make documentation. You're gonna wanna Git ignore this temp folder.

[00:07:57] And the reason is, it is more of a staging area. That is only important in a transient sense, sort of a midpoint in a more meaningful workflow and we don't wanna check it in. So I'm gonna add this to the bottom of my Git ignore temp. And then I can do git rm temp, get rid of it.

[00:08:35] Part of the problem is I already made a little commit with that stuff, so and I'm gonna rerun the extractor just to get those files back. But Git ignored this time. I believe I have to do this, okay? So let me explain how this normally works. dash dash local, that's something you're gonna wanna do rarely, not rarely, but you're gonna wanna do it with intent.

[00:09:09] Normally you'll run this without the dash dash local thing. So let's say I went back to the original implementation here. I believe this command is going to exit zero. Nope, it didn't. Why didn't it? Cuz I didn't build, I keep forgetting this step. Yarn builds cuz we've gotta make our declaration file, run again, should exit zero.

[00:09:39] Commit, exit one, sorry, I meant it should exit unsuccessfully. It's exiting unsuccessfully because the API surface it found through analyzing my code Is different than what exists in that etc folder. So this is something you could run in continuous integration, where you'd be able to detect that this is a change that users are gonna feel.

[00:10:07] This is a change in how this library presents itself to the outside world. You could run this almost like you'd run your tests. Dash dash local effectively means well, let's see how they documented. But it means I have intentionally made a change to the API. And I wish to set that as the new sort of standard, the new human approved thing.

[00:10:34] So let's see how they describe this. It indicates that it's running as part of a local build on the developers machine. And it disables validation that would normally be performed for a production build. For example, it automatically copies the API report into that etc folder and sets it as the new approved version.

[00:11:00] That's why we ran it first, right? But normally you don't wanna make a change to this and you wanna check it in with your code. And then in CI, you'd run this task without the dash, dash local flag. And that would give you the assurance that the code change that you're looking and the API report that came with it are the total extent of the changes that user should see.

[00:11:29] Otherwise this will fail and it should. Pretty cool stuff and it really helps you find out what's going on with your API surface.