npm package: @hubspot/ts-export-types-reader
Description: Reader utilities for the @hubspot/ts-export-types package
Latest version: 1.1.0

<p align="center">
  <img src="https://img.shields.io/npm/v/@hubspot/ts-export-types-reader?color=%23f5c518&style=flat-square" alt="npm version" />
  <img src="https://img.shields.io/npm/l/@hubspot/ts-export-types-reader?color=%2300d9ff&style=flat-square" alt="license" />
  <img src="https://img.shields.io/badge/TypeScript-5.0+-3178c6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript" />
</p>

<h1 align="center">@hubspot/ts-export-types-reader</h1>

<p align="center">
  <strong>Types and utilities for working with generated API types</strong><br />
  Companion package to <code>@hubspot/ts-export-types</code> for consuming and traversing analyzed type information.
</p>

<p align="center">
  <a href="#overview">Overview</a> •
  <a href="#installation">Installation</a> •
  <a href="#usage">Usage</a> •
  <a href="#api-reference">API Reference</a>
</p>

---

## Overview

This package provides TypeScript types and utilities for working with the type information generated by `@hubspot/ts-export-types`. It includes:

- **Type definitions** — All `ApiNode` types representing exports, functions, classes, properties, and more
- **Type guards** — Functions for narrowing `ApiNode` types safely
- **Result utilities** — Helpers for looking up exports and referenced types

## Installation

When using `npm`:

```bash
npm install @hubspot/ts-export-types-reader
```

## Usage

### Working with analyze results

```ts
import {
  type AnalyzePackageResult,
  createAnalyzeResultReader,
} from '@hubspot/ts-export-types-reader';

// Load your generated API types (from @hubspot/ts-export-types output)
import apiData from './api/api.json';

const api = createAnalyzeResultReader(apiData as AnalyzePackageResult);

// Find an export by name
const myFunction = api.findExportByName({
  exportPath: '.',
  exportName: 'myFunction',
});

// Find a referenced type by its ID
const myType = api.findReferencedTypeById('MyType:my-package:dist/index.d.ts');
```

### Using type guards

```ts
import {
  type ApiNode,
  isFunctionNode,
  isObjectNode,
  isTypeReferenceNode,
  isUnionNode,
} from '@hubspot/ts-export-types-reader';

function processNode(node: ApiNode) {
  if (isFunctionNode(node)) {
    console.log('Function parameters:', node.parameters);
    console.log('Return type:', node.returnType);
  }

  if (isObjectNode(node)) {
    node.properties.forEach((prop) => {
      console.log(`Property: ${prop.name}`);
    });
  }

  if (isUnionNode(node)) {
    node.types.forEach(processNode);
  }

  if (isTypeReferenceNode(node)) {
    console.log('References type:', node.typeId);
  }
}
```

### Traversing types

```ts
import {
  type AnalyzePackageResult,
  type ApiNode,
  createAnalyzeResultReader,
  isTypeReferenceNode,
} from '@hubspot/ts-export-types-reader';

function collectAllTypeIds(
  api: ReturnType<typeof createAnalyzeResultReader>,
  node: ApiNode,
  visited = new Set<string>()
): string[] {
  const typeIds: string[] = [];

  if (isTypeReferenceNode(node)) {
    if (!visited.has(node.typeId)) {
      visited.add(node.typeId);
      typeIds.push(node.typeId);

      const referencedType = api.findReferencedTypeById(node.typeId);
      typeIds.push(...collectAllTypeIds(api, referencedType, visited));
    }
  }

  return typeIds;
}
```

## API Reference

### Result utilities

#### `createAnalyzeResultReader(result: AnalyzePackageResult): AnalyzeResultExport`

Creates a helper object for querying analyze results.

```ts
interface AnalyzeResultExport {
  findExportByName(options: FindExportByNameOptions): ExportNode;
  findReferencedTypeById(typeId: string): ApiNode;
}

interface FindExportByNameOptions {
  exportPath: string; // e.g., "." or "./utils"
  exportName: string; // e.g., "myFunction"
}
```

### Types

#### `AnalyzePackageResult`

The root type for analyze output:

```ts
interface AnalyzePackageResult {
  exports: Record<string, ExportNode[]>;
  types: Record<string, ApiNode>;
}
```

#### `ApiNode`

Union of all possible node types:

```ts
type ApiNode =
  | ArrayNode
  | BuiltInTypeReferenceNode
  | ClassNode
  | ConditionalNode
  | ConstructorNode
  | ExportNode
  | ExternalTypeReferenceNode
  | FunctionNode
  | InlinedTypeReferenceNode
  | IntersectionNode
  | LiteralNode
  | MappedTypeNode
  | MethodNode
  | ObjectNode
  | ParameterNode
  | PrimitiveNode
  | PropertyNode
  | TupleElementNode
  | TupleNode
  | TypeParameterNode
  | TypeReferenceNode
  | UnionNode
  | UnknownNode;
```

#### `ApiNodeKind`

Constants for all node kinds:

```ts
const ApiNodeKind = {
  Array: 'array',
  BuiltInTypeReference: 'built-in-type-reference',
  Class: 'class',
  Conditional: 'conditional',
  Constructor: 'constructor',
  Export: 'export',
  ExternalTypeReference: 'external-type-reference',
  Function: 'function',
  InlinedTypeReference: 'inlined-type-reference',
  Intersection: 'intersection',
  Literal: 'literal',
  MappedType: 'mapped-type',
  Method: 'method',
  Object: 'object',
  Parameter: 'parameter',
  Primitive: 'primitive',
  Property: 'property',
  Tuple: 'tuple',
  TupleElement: 'tuple-element',
  TypeParameter: 'type-parameter',
  TypeReference: 'type-reference',
  Union: 'union',
  Unknown: 'unknown',
} as const;
```

### Type guards

All type guards follow the pattern `is{NodeType}(node: ApiNode): node is {NodeType}`:

| Function                      | Narrows to                  |
| ----------------------------- | --------------------------- |
| `isArrayNode`                 | `ArrayNode`                 |
| `isBuiltInTypeReferenceNode`  | `BuiltInTypeReferenceNode`  |
| `isClassNode`                 | `ClassNode`                 |
| `isConditionalNode`           | `ConditionalNode`           |
| `isConstructorNode`           | `ConstructorNode`           |
| `isExportNode`                | `ExportNode`                |
| `isExternalTypeReferenceNode` | `ExternalTypeReferenceNode` |
| `isFunctionNode`              | `FunctionNode`              |
| `isInlinedTypeReferenceNode`  | `InlinedTypeReferenceNode`  |
| `isIntersectionNode`          | `IntersectionNode`          |
| `isLiteralNode`               | `LiteralNode`               |
| `isMappedTypeNode`            | `MappedTypeNode`            |
| `isMethodNode`                | `MethodNode`                |
| `isObjectNode`                | `ObjectNode`                |
| `isParameterNode`             | `ParameterNode`             |
| `isPrimitiveNode`             | `PrimitiveNode`             |
| `isPropertyNode`              | `PropertyNode`              |
| `isTupleElementNode`          | `TupleElementNode`          |
| `isTupleNode`                 | `TupleNode`                 |
| `isTypeParameterNode`         | `TypeParameterNode`         |
| `isTypeReferenceNode`         | `TypeReferenceNode`         |
| `isUnionNode`                 | `UnionNode`                 |
| `isUnknownNode`               | `UnknownNode`               |

### Node type interfaces

#### `ExportNode`

Represents an exported symbol:

```ts
interface ExportNode {
  kind: 'export';
  exportName: string;
  declarationKind: ExportDeclarationKind;
  isType?: boolean;
  isDefault?: boolean;
  type: ApiNode;
  jsdoc?: Jsdoc;
}

type ExportDeclarationKind =
  | 'const'
  | 'let'
  | 'var'
  | 'function'
  | 'class'
  | 'type'
  | 'interface'
  | 'enum';
```

#### `FunctionNode`

Represents a function type:

```ts
interface FunctionNode {
  kind: 'function';
  functionKind: FunctionKind;
  parameters: ParameterNode[];
  returnType: ApiNode;
  typeParameters?: TypeParameterNode[];
  name?: string;
  isAsync?: boolean;
  jsdoc?: Jsdoc;
}

type FunctionKind = 'arrow' | 'expression' | 'declaration' | 'call-signature';
```

#### `ClassNode`

Represents a class:

```ts
interface ClassNode {
  kind: 'class';
  name?: string;
  isAbstract: boolean;
  typeParameters?: TypeParameterNode[];
  implements?: ApiNode[];
  constructors: ConstructorNode[];
  properties: PropertyNode[];
  methods: MethodNode[];
  staticProperties: PropertyNode[];
  staticMethods: MethodNode[];
  jsdoc?: Jsdoc;
}
```

#### `TypeReferenceNode`

References a type defined in the `types` map:

```ts
interface TypeReferenceNode {
  kind: 'type-reference';
  typeId: string;
  typeString: string;
  typeArguments?: ApiNode[];
}
```

#### `ExternalTypeReferenceNode`

References a type from an external package:

```ts
interface ExternalTypeReferenceNode {
  kind: 'external-type-reference';
  typeName: string;
  typeString: string;
  packageName: string;
  packageVersion: string;
  typeArguments?: ApiNode[];
}
```

## Requirements

- Node.js >= 18.0.0

## License

MIT © [HubSpot](https://github.com/HubSpot)