# Mew [![pipeline status](https://gitlab.weike.fm/bbg/mew/badges/master/pipeline.svg)](https://gitlab.weike.fm/bbg/mew/commits/master)

<div align='center'>
  <img width='200' height='auto' src='https://daka666-1253442168.file.myqcloud.com/college_pro_media/tool/files/20200921_151926_mew.jpg'>
  <p>梦幻，前端通用业务 SDK</p>
</div>

# Install

npm i @bbg/mew

# Usage

#### pc 或 h5 登录

先联系管理员将业务域名加入 sso 白名单，否则无法通过授权

先创建 Auth 实例，比如在 service/common.service.ts 里导出实例，方便复用单一实例

```js
export const auth = new Auth({
  env: ENV,
  source: SOURCE,
  source_appid: string, // 来源业务公众号appid，没有就不用带
})
```

H5 项目中，在 `http.ts` 里，401 时，使用 Auth 实例去登录

```js
import { commonService } = '_service'

commonService.auth.toSignInWxH5()
```

同理，pc 登录

```js
import { commonService } = '_service'

commonService.auth.toSignInPC()
```

因为登录后的回调中会携带加密 token，所以需要在全局处理解密 token，比如可以在 `src/index.ts` 里加入

```js
import { Auth } = '@bbg/mew'

Auth.decodeSsoToken()
```

会自动识别链接上的参数，并存 token 到本地，注意，这个方法是静态方法，无需实例化

#### 跨域无感知授权

比如我要在购买页 https://shop.haha.com 免登录跳到 https://pay.haha.com

```js
Auth.toUrlWithTicket({ url: 'https://pay.haha.com' })
```

注意：目标域项目 `https://pay.haha.com` 依然需要在全局使用 `Auth.decodeSsoToken()` 来全局解码

#### 本地存储和发布订阅

初始化，可以放在 src/lib/storage.ts

```js
import { Storage } = '@bbg/mew'
// 定义 storage key，防止重复，便于智能提示
import { storageType } = '_src/type/storage'

const storage = new Storage<storageType.Key>()

export default storage
```

src/type/storage.ts 可以定义storage的key

```js
export type Key =
  | 'haha'
  | 'uid'
```

业务代码里就可以这样用，具体看下面的API

```js
import { storage } from '_lib/storage'

storage.setItem('haha', { xixi: 123 })
console.log(storage.getItem('haha')) // { xixi: 123 }
```

# API

或直接查看[ts声明文件](lib/index.d.ts)获得最准确的API

#### Auth

```js
import { Auth } from '@bbg/mew
```

```js
/**
 * 实例化
 */
const auth = new Auth(params: {
  env: 'dev' | 'stage' | 'prod' // 当前环境
  source: string // 来源业务标识，需要和后端确定
  source_appid?: string // 来源业务公众号appid
})
```

```js
/**
 * wx h5登录，会跳转授权，成功后回调到ref上
 * @param params.ref 登录成功后的回调url
 */
auth.toSignInWxH5(
  (params: {
    ref?: string,
  } = {}),
)
```

```js
/**
 * pc登录
 * @param params.ref 登录成功后的回调url
 */
auth.toSignInPC(
  (params: {
    ref?: string,
  } = {}),
)
```

```js
/**
 * 退出登录
 * @param ref 回调链接（可选，默认为当前链接）
 */
  public signOut(params: { ref?: string } = {})
```

```js
/**
 * 从地址栏上解出token，并存入本地，此方法可以在全局挂上
 * params.currentUrl? 需要解析的地址，默认为当前地址
 * params.isKeepTokenInUrl? 是否需要保留sso_token在url上，默认会去除掉
 */
static decodeSsoToken(
  params: {
    currentUrl?: string
    isKeepTokenInUrl?: boolean
  }
)
```

```js
/**
 * 把token ticket 带在一个链接上，然后跳过去
 * @param params.url 跳过去的链接
 * @param params?.token 需要加密的token，不填默认取本地token
 * @param params?.isReplace 跳过去是否replace当前页面，默认location.assign
 */
static toUrlWithTicket(params: { url: string; token?: string, isReplace: boolean })
```

#### Storage

类

```js
// 创建实例，TKey是 union type
new Storage<TKey extends string>()
```

实例

```js
/**
 * 本地存储获取一个值，如果是数字字面量，一定是 number，因为基于 JSON.parse
 */
getItem<T = string>(key: TKey): T | null;
```

```js
/**
 * 本地存储设置一个值，value可以是对象
 */
setItem(key: TKey, value: {
    [key: string]: any;
} | string | number): void;
```

```js
/**
 * 清空localstorage
 */
clear(): void;
```

```js
/**
 * 本地会话存储获取一个值，如果是数字字面量，一定是 number，因为基于 JSON.parse
 */
getSessionItem<T = string>(key: TKey): T | null;
```

```js
/**
 * 本地会话存储设置一个值，value可以是一个值
 */
setSessionItem(key: TKey, value: unknown): void;
```

```js
/**
 * 清空sessionStorage
 */
sessionClear(): void;
```

```js
/**
 * 在内存设 kv
 */
set(key: TKey, value: any): void;
```

```js
/**
 * 在内存获取 kv
 */
get<T = string>(key: TKey): T | null;
```

```js
/**
 * 在内存移除 kv
 */
remove(key: TKey): void;
```

```js
/**
 * 本地存储移除一个值
 */
removeItem(key: TKey): void;
```

```js
/**
 * 本地会话存储移除一个值
 */
removeSessionItem(key: TKey): void;
```

```js
/**
 * 监听事件
 * @param key 要监听的事件名
 * @param callback 监听回调
 */
on(key: TKey, callback: (params: CustomEventInit) => void): void;
```

```js
/**
 * 发射事件
 * @param key 要发射的事件名
 * @param eventInit 事件参数
 * @param eventInit.detail 携带的数据
 * @param eventInit.bubbles bubbles 是否可以冒泡
 * @param eventInit.cancelable cancelable 是否可以取消
 */
emit(key: TKey, eventInit?: CustomEventInit): void;
```


# Dev

监听开发模式

`npm start`

构建并测试

`npm run build`
