npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

assemblyjs

v1.1.0

Published

Assembly is a function wrapper based on the concept of functional programming

Downloads

13

Readme

Assembly

NPM Version

警告

由於WebAssembly即將到來,為了防止誤會,我將停止更新Assembly,並將後續開發與維護轉移至Packhouse套件。

簡介

javascript是一個基於非同步驅動,且有數種呼叫function的概念,這點讓js於functional programming設計下險些困難。

而Assembly是一個函數包裝器,求助些許物件導向的概念,編寫出來的function可以泛用各種型態,並適應鍊式寫法。

安裝

npm

npm i assemblyjs

web

<script src="./dist/index.js"></script>
let factory = new Assembly()

webpack

import Assembly from 'assemblyjs'
let factory = new Assembly()

nodejs

let Assembly = require('assemblyjs')
let factory = new Assembly()

如何開始

建立工廠

Assembly是集結Group的工廠

Bridge是每次從工廠呼叫function時都會執行的函式,初始目的是為了動態載入group

let factory = new Assembly()
factory.setBridge((factory, groupName, toolName) => {
    if (factory.hasGroup(groupName) === false) {
        factory.addGroup(groupName, require(`./${groupName}`))
    }
})

Group

所有的function都必須在group下建構,因此建立group是第一步。

let group = new Assembly.Group()

當group被Assembly引入時可以藉由create客製化屬性,可用於模組化管理

alias只賦予系統訊息的命名,而非factory呼叫的key

let group = new Assembly.Group({
    alias: 'math',
    create(options) {
        this.options = options // {coefficient: 5}
    }
})
factory.addGroup('math', group, {
    coefficient: 5
})

Alone

獨立Group,使其不再受Factory管制。

let group = new Assembly.Group({
    create(options) {
        this.options = options // {coefficient: 5}
    }
})
group.addTool({
    name: 'sum',
    allowDirect: true,
    action: function(a, b, { include, group, store }, error, success) {
        success(a + b)
    }
})
let alone = group.alone({
    coefficient: 5
})
alone.tool('sum').direct(5, 10) // 15

Merger And Coop (ver1.0.8)

Merger是Group互相引用的接口

Merger的Group也會觸發create,請避免把負責被引用的Group加入Factory,除非他不需要接收外部參數

let valid = new Assembly.Group()
valid.addTool({
    name: 'validNumber',
    action: function(number, { include, group, store }, error, success) {
        if (typeof number === "number") {
            success()
        } else {
            error()
        }
    }
})

let math = new Assembly.Group({
    merger: { valid }
})

math.addTool({
    name: 'double',
    action: function(number, { include, group, store, coop }, error, success) {
        coop('valid').tool('validNumber').ng(error).action(number, () => {
            success(number * 2)
        })
    }
})

Tool

Tool是一個裝載function的單位,由group建造

Assembly帶有一個參數解析器,但在js不斷突變的狀況下,我無法保證該解析器能夠處理所有狀況,盡可能使用paramLength來處理,且定義paramLength將跳過執行解析器的動作,可以提供良好的效能

group.addTool({
    // (Require) function name
    name: 'sumAndAdd5',
    // 是否支援直接回傳,若有非同步處理請關閉(預設:true)
    allowDirect: true,
    // 手動定義參數長度
    paramLength: 2,
    // 在喚醒這個tool時建立
    create: function(store, { include, group }) {
        store.hello = 'world' // store是一個對外物件,你有需要的時候就會想到它的
        this.add = group.options.coefficient
    },
    // (Require) 對於外部來看這是個function(a,b),並沒有其他參數
    action: function(a, b, { include, group, store }, error, success) {
        success(a + b + this.add)
    }
})

呼叫function

let sumAndAdd5 = factory.tool('math', 'sumAndAdd5')
sumAndAdd5.store('hello') // 'world'
sumAndAdd5.direct(5, 10) // 20
sumAndAdd5.action(5, 10, (err, result) => {
    console.log(result) // 20
})
sumAndAdd5.promise(5, 10).then((result) => {
    console.log(result) // 20
})

// look for normal function.
let saa5 = sumAndAdd5.direct
saa5(5, 10) // 20

預填裝 (ver1.0.3)

let sumAndAdd5 = factory.tool('math', 'sumAndAdd5').packing(5, 10)
sumAndAdd5.direct() // 20
let sumAndAdd5 = factory.tool('math', 'sumAndAdd5').packing(5)
sumAndAdd5.direct(15) // 25
let sumAndAdd5 = factory.tool('math', 'sumAndAdd5').packing(5).packing(5)
sumAndAdd5.direct() // 15

解除預填裝 (ver1.0.6)

let sumAndAdd5 = factory.tool('math', 'sumAndAdd5').packing(5, 10).unPacking().direct(5, 5) // 15

預監聽錯誤 (ver1.0.5)

NG將協助你捕捉錯誤或優化程式碼

group.addTool({
    name: 'errorDemo',
    allowDirect: true,
    action: function(a, b, { include, group, store }, error, success) {
        let t = Math.random() > 0.5 ? error : success
        t()
    }
})
action

action預先呼叫錯誤,最後的callback將忽略賦予error

factory.tool('math', 'errorDemo').ng((err)=>{
    console.log(err)
}).action((res) => {
    console.log(res)
})
direct

direct原本在錯誤處裡上會直接throw error,但預處理則呼叫callback

factory.tool('math', 'errorDemo').ng((err)=>{
    console.log(err)
}).direct()
promise

promise在遭遇錯誤仍然會宣告reject,但同時執行錯誤的回呼函式

factory.tool('math', 'errorDemo').ng((err)=>{
    console.log(err)
}).promise()

Mold (v1.1.0)

Mold是一個參數配裝器,只支援同步處理,用於參數驗證與型態轉換。

group.addMold({
    // (Require) mold name
    name: 'int',
    // 回傳非true及驗證錯誤與回傳訊息
    check(param) {
        return typeof param === 'number' ? true : 'Not a number.'
    },
    // 參數處理
    casting(param) {
        return Number.floor(param)
    }
})
group.addTool({
    name: 'multiply',
    mold: [null, 'int'], //設定b參數一定要整數
    action: function(a, b, system, error, success) {
        success(a * b)
    }
})

factory.tool('math', 'multiply').direct(5.5, 10) // 55
factory.tool('math', 'multiply').direct(10, 5.5) // 50
factory.tool('math', 'multiply').direct(10, '5.5') // error 'Not a number.'

生產線

建構生產線是一個函數柯理化(curry)的過程,在這之前,先將整個function給定義好

include是一個Tool互相溝通的接口,作用域只到當下的group

let math = new Assembly.Group()
math.addTool({
    name: 'isNumber',
    allowDirect: false,
    action: function(params, { include }, error, success) {
    	let values = params.filter((n) => {
            return typeof n !== 'number'
        })
        if (values.length === 0) {
            success(true)
        } else {
            error('no number')
        }
    }
})
math.addTool({
    name: 'sum',
    allowDirect: true,
    action: function(a, b, { include }, error, success) {
        include('isNumber').action([a, b], (err) => {
            if (err == null) {
            	success(a + b)
            } else {
                error(err)
            }
        })
    }
})
math.addTool({
    name: 'double',
    allowDirect: true,
    action: function(number, { include }, error, success) {
        include('isNumber').action([number], (err) => {
            if (err == null) {
                success(number * 2)
            } else {
                error(err)
            }
        })
    }
})

factory.addGroup('math', math)

建構生產線

和Tool一樣,生產線仍依附在group上

group.addLine({
    name: 'compute',
    // 初始化是難免的,inlet會限制第一個呼叫的function,當其為null或空陣列時不限制
    inlet: ['add'],
    // 每次執行line都會刷新this的屬性
    input: function(number, { include }, error, start) {
    	this.number = number
        start()
    },
    output: function({ include }, error, success) {
    	success(this.number)
    },
    // 當執行鍊中觸發error就會觸發fail,err:{ stack, message} 的物件
    fail: function(err, report) {
    	report(err)
    },
    // layout為一個鍊中能呼叫的函數表,實質為Tool個體
    layout: {
        add: function(number, { include }, error, next) {
            include('sum').action(this.number, number, (err, result) => {
                if (err) {
                    error(err)
                } else {
                    this.number = result
                    next()
                }
            })
        },
    	double: function({ include }, error, next) {
            include('double').action(this.number, (err, result) => {
                if (err) {
                    error(err)
                } else {
                    this.number = result
                    next()
                }
            })
        }
    }
})

執行生產線

將5丟進去input之後,經由生產線擲出result

line不支援direct

factory.line('math', 'compute')(5).add(10).double().double().action((err, result) => {
    console.log(result) // 60
})
factory.line('math', 'compute')(5).add(10).double().promise().then((result) => {
    console.log(result) // 30
})

其他

版本LOG

開發者文件