# Utils

&#x20;Utils是Packhouse內部的函數組，有許多功能都來自於Utils的建構，包括[Tool ID](#generateid)、[Mold Verify](#verify)等。

{% hint style="info" %}
所有的Utils是指向同一個對象，意味著你可以藉由Utils物件進行拓展，但我們不建議這麼做，良好的拓展方法請參照[Plugins](https://packhouse-doc.metalsheep.com/the-instance/plugin)。
{% endhint %}

## How To Use

#### Core

```javascript
const Packhouse = require('packhouse')
const packhouse = new Packhouse()

packhosue.utils === Packhouse.utils // true
```

#### Tool

```javascript
const tool = {
    myTool: {
        install({ store, utils }) {
            store.id = utils.generateId()
            store.uuid = utils.generateId
        },
        handler(self) {
            console.log(self.store.id)
            console.log(self.store.uuid())
        }
    }
}
```

#### Mold

```javascript
const molds = {
    uuid(value, { utils }) {
        return utils.generateId()
    }
}
```

## Methods

#### **getType**

能比`typeof`獲取更多的型態，沒在下列名單內的揭回傳`typeof`的型態：

```javascript
packhouse.utils.getType([]) // array
packhouse.utils.getType(NaN) // NaN
packhouse.utils.getType(null) // empty
packhouse.utils.getType(undefined) // empty
packhouse.utils.getType(/test/) // regexp
packhouse.utils.getType(new Promise(() => {})) // promise
packhouse.utils.getType(Buffer.from('123')) // buffer
packhouse.utils.getType(new Error()) // error
```

#### **verify**

一個簡單的驗證方法，並回傳新的物件。

{% hint style="info" %}
`verify`與`mold`是分離的系統，無法使用`mold`表達示。
{% endhint %}

> `verify`驗證的`type`對象是多個型態，而支援的類型請參閱[getType](#gettype)。

```javascript
let options = {
    a: 5,
    b: []
}

let data = packhouse.utils.verify(options, {
    // [required, allow types, default value]
    a: [true, ['number']],
    b: [true, ['array']],
    c: [false, ['number'], 0]
})

console.log(data.a) // 5
console.log(data.c) // 0
```

#### **generateId**

仿`uuid`建立，回傳一個隨機`uuid`，但這並不是標準的`uuid`演算法。

```javascript
console.log(typeof packhouse.utils.generateId()) // string
```

但這不代表你無法使用[uuid](https://www.npmjs.com/package/uuid)演算法：

```javascript
let uuid = require('uuid/v4')
let packhouse = require('packhouse')

packhouse.utils.generateId = uuid
```

#### **peel**

針對物件深度取值，可以參考[可選鍊](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/%E5%8F%AF%E9%80%89%E9%93%BE)。

```javascript
let a = {
    b: {
        c: {
            d: 5
        }
    }
}
console.log(packhouse.utils.peel(a, 'b.c.d')) // 5
console.log(packhouse.utils.peel(a, 'b.c.e')) // undefined
```

#### loader

返回一個Promise，第一次執行後會執行程序，但後續的呼叫皆回傳第一次呼叫的結果。

`loader`的存在目的很簡單，在Tool Install的週期時，有時會存在需非同步請求才能獲得的資料，但該週期又不支援非同步運算，因此你可以藉由`loader`進行包裹來達成初步的Cache。

> 更進階的快取應用可以參照[Order](https://packhouse-doc.metalsheep.com/plugins/order)。

```javascript
let loader = packhouse.utils.loader((resolve, reject) => {
    setTimeout(() => {
        resolve('hello')
    }, 1000)
})

loader().then(result => {
    // 等待一秒才執行
    console.log(result) // hello
    loader().then(result => {
        // 不需等待
        console.log(result) // hello
    })
})
```
