# nei-ts-helper

> Automatic generation of NEI TypeScript interface

Latest version **1.0.10** (published 2024-10-17) · ISC license · 0 weekly downloads

## Install

```sh
npm install nei-ts-helper
pnpm add nei-ts-helper
yarn add nei-ts-helper
bun add nei-ts-helper
```

Provides the command `nei-ts-helper`.

## Health

**Score 35/100 (D)** — status: maintenance-mode.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: stale; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.10 |
| Published | 2024-10-17 |
| First published | 2021-03-24 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 12 |
| Unpacked size | 94.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | luofeiyue, whiskeyi, yousy, guoyeeg, azgaga, liushichuan, yaochen, shenyuan, aflyermin, ignous, jeekdong |

## Links

- npm: https://www.npmjs.com/package/nei-ts-helper
- npm.io page: https://npm.io/package/nei-ts-helper

## Dependencies (12)

- [qs](https://npm.io/package/qs.md) ^6.9.4
- [ora](https://npm.io/package/ora.md) ^5.1.0
- [chalk](https://npm.io/package/chalk.md) ^4.1.0
- [nconf](https://npm.io/package/nconf.md) ^0.11.0
- [rimraf](https://npm.io/package/rimraf.md) ^3.0.2
- [inquirer](https://npm.io/package/inquirer.md) ^7.3.3
- [commander](https://npm.io/package/commander.md) ^6.2.0
- [node-fetch](https://npm.io/package/node-fetch.md) ^2.6.1
- [@babel/core](https://npm.io/package/@babel/core.md) ^7.12.10
- [@babel/register](https://npm.io/package/@babel/register.md) ^7.12.10
- [@babel/preset-env](https://npm.io/package/@babel/preset-env.md) ^7.12.11
- [@babel/preset-typescript](https://npm.io/package/@babel/preset-typescript.md) ^7.12.7

## Recent versions

- 1.0.10 (latest) — 2024-10-17
- 0.1.4-beta-0 (beta) — 2022-08-24
- 1.0.9 — 2022-12-10
- 1.0.7 — 2022-12-10
- 1.0.6 — 2022-11-17
- 1.0.5 — 2022-11-11
- 1.0.4 — 2022-11-11
- 1.0.3 — 2022-11-10
- 1.0.2 — 2022-11-10
- 1.0.1 — 2022-11-10
- 1.0.0 — 2022-11-10
- 0.1.4 — 2022-08-24
- 0.1.3 — 2022-04-07
- 0.1.2 — 2022-04-07
- 0.1.1 — 2022-04-06
- … 4 more at https://npm.io/package/nei-ts-helper/versions

## README

- [有啥用](#有啥用)
- [咋用呢](#咋用呢)
- [配置文件](#配置文件)
- [命令行参数](#命令行参数)
- [咋运作的](#咋运作的)
  - [流程](#流程)
  - [几个概念](#几个概念)
  - [生成代码](#生成代码)
- [最佳实践](#最佳实践)
- [待做](#待做)

## 有啥用

使用 **TypeScript** 开发项目本身是一件非常愉悦的事情，但是总会有些**麻烦的事情**打破这份愉悦，业务开发中最常见的问题：我要对接口 **请求&返回** 数据写声明吗？`any` 处理起来非常方便，但是没有了数据的提示和检查，可是看着臭长的接口返回完全提不起写声明的兴趣┓( ´∀` )┏(尤其遇到喜欢频繁改动接口数据的后端就更痛苦了)

**`nei-ts-helper`** 可以帮助你摆脱这些无趣的事情，它帮助你从 **NEI** 平台定义的接口转化为 **Typescript** 声明代码

## 咋用呢

**`nei-ts-helper`** 是一个命令行工具，它根据配置文件自动生成 **Typescript** 声明至指定文件夹

1. 安装 **`nei-ts-helper`**

    ```bash
    npm i nei-ts-helper --save-dev
    // or
    yarn add nei-ts-helper --dev
    ```

2. 在根目录新建配置文件 **`nei-ts-helper.js` / `nei-ts-helper.ts`**

    如：
    ```ts
    import { defineConfig } from 'nei-ts-helper/lib'
  
    export default defineConfig({
      indentSize: 2,
      root: 'typings',
      version: 2,
      apiList: {
        urls: {
          GetDomainList: 'xxxxx'
        },
        output: {
          'domain-list.ts': [
            'GetDomainList'
          ]
        }
      }
    })
    ```

    ```js
    module.exports = {
      indentSize: 2,
      root: 'typings',
      version: 2,
      apiList: {
        urls: {
          GetDomainList: 'xxxxx'
        },
        output: {
          'domain-list.ts': [
            'GetDomainList'
          ]
        }
      }
    }
    ```

    详细配置文件书写见下面

3. 添加 `scripts` 

    ```json
    "nei": "nei-ts-helper -all"
    ```

4. 添加 `NEI` 访问令牌

    它使用 `NEI` 提供的 `openApi` 获取接口相关信息，所以我们需要创建一个[**访问令牌**](https://nei.hz.netease.com/setting/personal-access-token/)

5. 根目录运行 `npm run nei`

    根据命令行提示填入访问令牌，选择保存将会自动存储在 系统 `HOME` 下的 `.nei-ts-helper` 文件夹

## 配置文件

可以使用 `-c / —config <config-path>` 手动指定配置文件，默认会自动读取当前运行环境目录下的 `nei-ts-helper.ts` / `nei-ts-helper.js`，配置文件导出一个配置对象，字段参数如下：

- 声明
  ```tsx
    interface ApiConfigV2<T extends string> {
      urls: {
        [key: string]: T;
      },
      output: {
        [key: string]: ApiConfigV2<T>['urls'][string][];
      }
    }

    interface ConfigV2<T extends string> {
      apiList: ApiConfigV2<T>;
      /** 输出文件目录 */
      root: string;
      /** 缩进空格数，默认2 */
      indentSize?: number;
      version: 2;
    }
  ```
- `apiList`

    接口配置

    - `urls`: 接口的 `NEI` 链接，key 是接口名，value 是 `NEI` 链接
    - `output`: 输出文件，key 是输出文件名，value 是接口名数组
    
- `root`

    输出文件基础目录

- `indentSize`

    缩进空格数，默认2

- `version`

    配置版本后，当前固定为 2

推荐使用 `ts` 格式文件编写，导入相应声明获得配置文件格式的校验

## 命令行参数

* 只生成部分声明

```bash
nei-ts-helper [-pf / --part-file <outputFile...>]
```

`-pf/--part-file` 参数后传入需要生成声明的文件名(对应 `nei config` `中的output` )

如以下命令仅会生成包含在 `home.ts` 和 `active.ts` 文件中的声明

```bash
nei-ts-helper -pf home.ts active.ts
```

* 生成全部声明

```bash
nei-ts-helper -all
```

现在支持拆分多个文件编写 `TS` 声明配置。因此如果需要一次性生成全部声明，需要使用 `-all` 参数。会遍历并执行当前目录下所有的配置文件

* -ouc/--only-update-config

只更新配置文件，不生成文件声明

## 咋运作的

原理十分简单，就是调用 `NEI` `openApi` 接口获取接口参数，通过字符串拼接的形式生成声明代码

核心代码在 `src/core` 目录下，分为三个模块

**read-config**

读取&解析配置文件

**fetch-interface**

调用 `NEI` `openApi` 接口获取接口参数

**generator**

生成 `TypeScript` 声明代码的核心逻辑

### 流程

![process](https://lofter.lf127.net/1613745544623/nei-ts-helper.png)

### 几个概念

我们将 `NEI` 中一个字段的数据类型分为

1. 基础类型

    `String`，`Number`，`Boolean`，`Variable`，`File`，`UNKNOWN`

    我们将它和 TypeScript 中的类型一一对应

2. 复合类型

    基础类型的组合，包括

    - 匿名复合类型
      ![anoInterface](https://lofter.lf127.net/1613785420385/Untitled1.png)
    - 具名复合类型
      ![independInterface](https://lofter.lf127.net/1613785473543/Untitled2.png)
3. 枚举类型

`NEI` 获取的接口声明类型我们称为 **`ParamInterface`** ，其中可能包含基础类型和复合类型字段，对于复合类型字段需要根据 `type` 到 **`DataType`** 类型中查找

对于一个接口我们最关心的是两个参数 `pid` 和 `id`

- 根据 `pid` 获取该项目的 **`DataType`** 数据
- 根据 `id` 获取该接口的 **`ParamInterface`** 数据

### 生成代码

处理 `TypeScript` 声明代码的生成，本质是对复合类型递归遍历为基础类型的生成，通过 `NEI` 基础类型到 `TypeScript` 基础类型的映射关系完成 声明的生成

1. 基础类型代码生成主要是两个函数 `productSingleStatement`  和 `productUnionStatement`
2. 复合类型代码生成主要是两个函数
    - `productIndependentInterface`
        具名复合类型 通过该方法生成独立的声明
    - `productAnonymousInterface`
        匿名复合类型 通过该方法生成声明

## 最佳实践
只使用基于「自动生成的声明」二次封装的声明
* 自动生成的声明，名称/存储位置都可能发生改变，直接引用的方式修改成本大
* 接口生成的声明往往层级嵌套深，二次封装简化使用的同时还可以语义化重命名

## 待做

- [ ]  非请求的测试
- [x]  部分接口更新
- [ ]  更新是否覆盖原有接口数据

---
_Source: https://npm.io/package/nei-ts-helper · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
