Check out a free preview of the full Enterprise TypeScript course

The "API Reporting" Lesson is part of the full, Enterprise TypeScript course featured in this preview video. Here's what you'd learn in this lesson:

Mike adds an API surface report and documentation to the project by installing the api-extractor and api-documenter packages. The API Extractor package generates API report in a markdown file and can adapt the report based on alpha, beta, and public release statuses.


Transcript from the "API Reporting" Lesson

>> The next thing we're gonna add to our little TypeScript library is an API surface report and documentation. So we're gonna install some new tools in order to make this work. I'm gonna kill my yarn watch. I'm gonna make a quick git commit. Just seeing what was changed here.

This just looks like the yarn watch stuff. Really important that we start this next part of the course with a clean git staging area. Cleat, it's not what Linux knows about. All right, so time to add a couple new dependencies, yarn add -d for dev dependency, microsoft/api-extractor. Microsoft/api-documenter.

That is all. So as before, new tool, new config file, new way to create a starting point with a little CLI command so we don't have to write a bunch of stuff by hand. And this one is yarn api-extractor --init. No, sorry, no dash dash. Okay, this route was ran successfully.

[00:01:54], that's where you can look if you wanna learn more about this tool. The purpose we are using this tool for is a couple of things. It's gonna generate an API surface report so that if we make pull requests against this library, that might change the public API surface, it'll be super obvious to us and we'll know exactly how the public API is changing.

Sometimes this can be a little bit subtle, when you have deep modules within a library and maybe the return type of some function is ultimately exposed through the library's publicly usable surface. It's a great change detection mechanism there. And we're also going to use it to create declaration file roll ups.

So I mentioned that we're gonna have this idea of the publicly visible types, like people who just conventionally consume this library, they'll use these types. We'll have a type for beta testers. We'll have some types for alpha testers. And then we might have a set of types that's just for it's exposing all the internal stuff too, maybe we use that for our Jest testing purposes.

If we really wanted to write tests against some internal things, there's another declaration file that lets us reveal all the internal stuff as well. But you wouldn't see those, you'd have to do something explicit to consume anything other than sort of the public types, that's what everyone gets normally.

All right, so let's look at this file that was created, api-extractor.json. It's pretty huge, and we're gonna make a couple very small changes here. So where's this outline? So this little outline thing is nice when you're browsing a big JSON document, it's part of VS Code now. We're going to focus on this dtsRollup section.

You could also scroll down here and look for a top-level key, dtsRollup, right? But if you're somewhere else and you click this, it'll take you right to it, which is kinda nice. Okay, so we've got something here called. Well, first we wanna say that add a comma here after enabled true, cuz we're gonna uncomment some stuff below.

And next we're gonna go to this untrimmedFilePath. The untrimmed file, like the declaration file roll up, will contain all the private and internal stuff. So we're gonna add a little word after that, -private. This tool in this unscoped package name, it's just gonna put chat-stdlib. It's gonna get that from package json, it's the name of your package, we'll go there.

So there's your untrimmedFilePath. We're gonna keep scrolling down. We've got an alphaTrimmedFilePath. If we look at that, hey, an alpha's already there, that's totally acceptable. A betaTrimmedFilePath, we'll uncomment this as well, there's a -beta, that's something someone would have to opt into. And then publicTrimmedFilePath. And I'm gonna delete the public here so that it's just the name of the package, chat-stdlib.d.ts.

There's one more thing we gotta enable here. And I believe it's all the way up at the top, yes it is. It's gonna be mainEntryPointFilePath, it's right below the Schema. So go up to the top of the file, it'll be the first uncommented thing that you see here.

The input for API extractor is the declaration file, the entry point declaration file for your library. So this is in our dist folder. If your library had more than one file, these roll up files would contain all of the types for your library. You look in there and there would be module declarations.

It's still one file, but it would represent all of the different modules that you're publishing with your library, that's what makes it a rollup. We won't see that here because we're dealing with one file. Okay, that should be everything we need to do in this config file, so we can go ahead and close this and not worry about it again.

Let's make a new directory called etc. And then we're gonna run yarn api-extractor, run --local. The next thing you're gonna run is yarn api-extractor run --local. We're gonna press Enter. And here's what it spits out. So first, because we're using a very modern version of the TypeScript compiler right now, it's telling us about this.

Everything's gonna be okay, we're not using any TypeScript 5.3 features in this library, so it'll be fine. And this is kept up-to-date, it just lags a little bit behind, but it will be ready in a couple of weeks, I would assume. And it says the api report file was missing, so a new file was created, please add this file to git.

And it looks like in our etc folder, it created a markdown file. Let's look at what's in that file. So here's our etc folder. Here's this, and I'm gonna view this markdown file. And look at that, here's our api report and rendered markdown. And you can see that we've got a public and then we've got a beta here.

We're told not to edit this file directly, but it sort of describes the API surface of our library. It's not really documentation, there are code comments around deferred and the stringify error function. It's not there, this is just the API surface. So what we'll wanna do here, what do I need to do?

I'm not gonna worry about that. I have marked down linting in another part of this project, but we should be fine here. So I'm gonna close this, I'm gonna close this, and it's important. We have to make one more change and then we're gonna, well, two more changes, and then we're gonna save.

So we're gonna create a temp folder. And we wanna git ignore this. It seems, I already have something in this temp folder. I don't wanna check this into git, this is just sort of working state. This is files that API extractor leaves around for other things that are built on top of it.

So let's go into gitignore, and down at the bottom we can say, Something like that. And then one more thing before we commit, and that is going back to our package json, we wanna be very deliberate about what types we expose to consumers of this library. And if we look right now, we've got this dist/index.js.

And so what's implied by this is in our dist folder, this index.d.ts kind of describes the types associated with index.js, and that's what's gonna end up being consumed, right? But we can change our mind there, we can make it more explicit. And we're gonna say it's dist/chat-stdlib.d.ts. And why don't we go ahead and look at the differences between our index declaration file and all of these things that came out of api-extractor?

These are our roll ups, this is part of what came out. So this was the line I added. So our index declaration file, the important thing to note here is this. This stringifyError function is exported from our library, but we indicated that it is for beta users only.

This should not be included in the stable API surface of our library, but it is here. If we go to this thing that we're calling our public types, there's no function at the bottom. Hey, and there's even a note telling us something could have been here, but it was stripped away.

Because it's not part of what should be exposed for this release type, like a stable public release, including no beta functionality. And we'll go and look at beta. We'll sort of go in reverse order of maturity here. Well, beta, it does include a function declaration for this function.

Alpha, well, it's also gonna include the beta thing. But if there were things marked alpha, they would first appear here, they wouldn't be in the beta file. And then finally, in the private file, we should see stringifyError. We don't see a private thing here. Okay, there's one more thing.

You don't have to make this change, but I'll just show you how it works. If we did this and ran our api-extractor.
>> Do you have to rebuild the index DTS, since that's the-
>> I will, I will. Yeah, I do have to rebuild, thanks for catching that.

I think it'll work now. There it is. So that's private, and let's switch it back to internal and see what happens. Build. And it's gone. Part of why it's gone, or the reason it's gone, is in our tsconfig we had an option here called, It's up here, stripInternal.

Disable admitting declarations that have the internal tag in their js.comments. So that would be something where you truly, you want it dropped. You don't want any declarations there in any of the rollups. But you have three different pre-GA release types you can deal with there, you have private, alpha, beta.

So you can imagine. And we when we import this into our chat app, we're gonna need to use a beta function. And I'll show you how you can explicitly refer to that DTS rollup and say I wanna use that one as my types. And this is I think okay, because if you have someone who's opting into that, that's a deliberate step.

And in doing so, they're consuming something that says beta, and they have to write the word beta. And they couldn't come back and say, hey, you've changed this. So we got a question in the class about what happens if you don't see all of these different DTS rollup files?

And what happens if the wrong things are in there, if you're not seeing what I'm seeing? The thing that I would check is, first, if you're seeing anything at all in there, you probably have this main entry point defined properly, that's the input for API extractor. And then you wanna go and look at untrimmedFilePath.

And this is when we're talking about untrimmed, aside from stripInternal, untrimmed means the private stuff is left in there. In fact, if you didn't have stripInternal turned on, the internal stuff would be in there as well, truly untrimmed.
>> Sorry, could you scroll over there? Yeah, mine did not specify the -private.

>> I added that when we were going through.
>> That's what I missed, thank you.
>> Their defaults are a little different compared to what I would prefer. They have this as the default here. And I like, if a user's gonna consume my private types, I would like them to write the word private, so I tend to do this.

And they added the word, if we go down to the public one, publicTrimmedFilepath, they add the word public here. And I want the default to be public. If you're just using library name DTS like that, you're not writing the word private, you're not writing the word public, those are the types, that's the library, that's the default.

That's my own convention, you can pick whatever convention you'd like. Some people even like to put this DTS file in a different folder, like a temporary folder, and then they'll just build these rollup things. So they'll basically get rid of this file as part of their build, which is a valid thing to do, right?

Nobody needs that file anymore, and it's just one more thing someone could point to, and then there's this beta thing here. But that would simply be a matter of making your out there a little different. Or having a rim raf star dot disk slash startup DTS, something like that, to strip those away, and you would only do that after the rollups are complete.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now