npm package: @netty0911/tiny-app
Description: tiny app
Author: netty0911
Latest version: 2.0.15

# 核心库

## 安装

```bash
npm install @netty0911/tiny-app
```

## 应用注册

使用 `app.routes()` 注册应用。

`app.routes()` 接收两个参数：

- `name`：应用名称
- `routes`：应用路由，即应用名称和应用页面的映射关系

应用路由本质上使用了react-router-dom的路由配置，因此可以使用react-router-dom的路由配置方式。

示例：

下列代码注册了一个名为 `system` 的应用，该应用包含两个页面：`system/product` 和 `system/product/detail`。

```tsx
import { app } from '@netty0911/tiny-app';

app.routes('system', {
  'system/product': ProductIndexPage,
  'system/product/detail': ProductDetailPage,
})
```

以上代码被实际处理为：

```tsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Routes, Route } from 'react-router-dom';
import { history } from '@netty0911/tiny-app';

ReactDOM.render(
  <Router basename="/" location={history.location} navigationType={history.action} navigator={history}>
    <Routes>
      <Route path="system/product" element={<ProductIndexPage />} />
      <Route path="system/product/detail" element={<ProductDetailPage />} />
    </Routes>
  </Router>,
  document.getElementById('tiny-app')
);
```


## 应用路由

使用 `@netty0911/tiny-app` 提供的 `history` 进行路由操作。

```tsx
export interface History {
  readonly action: Action;
  readonly location: Location;
  createHref(to: To): string;
  push(to: To, state?: any): void;
  replace(to: To, state?: any): void;
  go(delta: number): void;
  back(): void;
  forward(): void;
  listen(listener: Listener): () => void;
  block(blocker: Blocker): () => void;
}
```

监听路由变化：

```tsx
import { useEffect } from 'react';
import { history } from '@netty0911/tiny-app';

export default function ProductIndexPage() {
  useEffect(() => {
    const unListen = history.listen(({ location, action }) => {
      // 这里可以做一些路由变化的操作
      console.log(location.pathname, action);
    });
    return () => unListen();
  }, [history]);

  return (
    <div>
      <h1>ProductIndexPage</h1>
    </div>
  );
}
```

## 用户信息

- 获取用户信息：`app.user.current()`
- 获取用户反CSRF凭据：`app.user.getCSRFToken()`
- 检查用户是否在指定白名单中：`app.user.checkWhitelist()`
- 清除用户登录态，并跳转到登录页：`app.user.redirectToLogin()`
- 清除用户登录态，并跳转到登录页：`app.user.logout()`

## API请求

使用 `app.cgi.request(body, options)` 进行接口请求。

```tsx
export interface RequestBody {
  /** 服务名 */
  service: string;

  /** 接口名 */
  action: string;

  /** 请求数据 */
  data?: any;
}

export interface RequestOptions {
  /**
   * 是否在顶部显示接口错误
   * 默认为 true，会提示云 API 调用错误信息，如果自己处理异常，请设置该配置为 false
   */
  tipErr?: boolean;

  /**
   * 请求时是否在顶部显示 Loading 提示
   * 默认为 true
   */
  tipLoading?: boolean;

  /**
   * 前端事务进行跟踪的请求头 X-TC-TraceId
   *
   * - 需满足标准uuid的正则 ` ^(\\w{8}(-\\w{4}){3}-\\w{12}?)`
   * 例如：958cccac-ab2a-dcfe-6fc4-1456f8ddc3a9
   */
  traceId?: string;
}
```

## 数据上报

### 点击流上报

方式1：

```js
app.insight.reportHotTag("xxx.yyy.zzz")
```

方式2：

```html
<a data-hot="xxx.yyy.zzz">链接</a>
```

### 事件上报

- 总字段个数（stringFields + integerFields）不能超过 20 个
- 字符串字段的长度，不能超过 4096

```js
app.insight.stat({
  ns: 'cvm',
  event: 'restart',
  stringFields: {
    instance: 'ins-1d7x8C3s'
  },
  integerFields: {
    instanceCount: 1
  }
});
```

### 任务上报

上报任务适合需要统计任务成功率和耗时场景

```js
const cvmRestartStat = app.insight.statTask('cvm-restart', 'cvm', 15000);
try {
  await performCvmRestart(instanceIds);
    // 上报成功，可以附带 int 和 string 变量
  cvmRestartStat.success({
    stringFields: {
      instance: instanceIds.join(';'),
    },
    integerFields: {
      instanceCount: instanceIds.length,
    }
  });
} catch(error) {
  // 失败可以上报 stack
  cvmRestartStat.fail({
    stack: error?.stack
  });
}
```

## 服务器

### 获取服务器时间

获取控制台的服务器时间。

```tsx
import { getCurrentServerTime } from '@tencent/tea-app';

console.log(getCurrentServerTime().toISOString());
```