mosaic

a client for managing components

npm install mosaic
42 downloads in the last week
84 downloads in the last month

Mosaic

马赛克(Mosaic)是所有以 Brix 组件形式编写的组件的管理工具,将业务中的各个区块以组件形式管理起来。 马赛克希望可以成为 BPM 工具的替代,后者依赖 NPM,不易扩展。

在你使用本工具之前,请先阅读 Brix 相关文档

安装

马赛克采用 Node.js 开发,通过 NPM 方式发布。所以使用马赛克,你需要安装:

  • Node.js
  • NPM

然后在终端执行:

npm install mosaic -g

装好之后,就可以使用 mosaic 命令了,还可以使用 mo 简写喔

mosaic help
mo help

用法

马赛克工具包含如下功能:

  • 发布组件
  • 下载组件
  • 开发核心组件
  • 开发乐高项目

所有功能都以子命令的形式提供,类似 git、brew 等工具:

  • mo publish
  • mo install
  • mo server
  • mo lego

发布组件

在组件目录执行:

mo publish

即可。如果不想 cd 来 cd 去,也可以指定一下组件相对当前目录的路径:

mo publish mux.tanx/dropdown

发布后,将可在 http://brix.alibaba-inc.com 看到所有发布的组件,自然也包括你刚发布的这个。 同时也可以在那找到你的组件在 CDN 的地址,通常为:

http://g.tbcdn.cn/mo/:namespace/:name/:version/:file

如果是 Brix 核心组件,则命名空间为 mosaics ,路径为:

http://g.tbcdn.cn/mo/mosaics/:name/:version/:file

如何在自己项目中使用这些外部组件(核心组件、或者其他业务组件),请看 http://thx.github.io/brix

下载组件

可以下载仓库中的组件到本地,通常这是不必要的,除非你需要将某些组件改头换面到自己业务的命名空间下。

mo install mosaics/wangwang/0.1.0
mo install mosaics/wangwang

均可。不指定版本的话,则默认下载最新的。将会下载组件包,并解压至当前目录,结构为:

mosaics
└── wangwang
    ├── README.md
    ├── index.js
    └── package.json

开发 Brix 核心组件

Brix 核心组件的命名空间为 mosaics,所有代码都在 https://github.com/mosaics,相应的, 我们要求核心组件开发者在本机也将组件目录组织为:

mosaics
├── dropdown
│   ├── README.md
│   ├── demo
│   │   └── wangwang.inc
│   ├── index.css
│   └── index.js
├── toc
│   ├── README.md
│   ├── index.js
│   └── package.json
└── wangwang
    ├── README.md
    ├── index.js
    └── package.json

然后,在 mosaics 目录下执行:

mo server

接着,访问 http://127.0.0.1:5000/dropdown 即可预览自己所要开发的组件了。预览的内容根据 README.md 的内容自动产生,具体写法可以参考 mosaics/wangwang 示例。

开发基于乐高平台的页面

使用如下命令启动服务:

mo lego

要求目录组织如下:

.
├── public
│   └── mux.lego
│       └── ceiling
│           ├── index.js
│           └── package.json
├── views
│   └── index.vm
└── server.js

实现

isaacs 大牛对 Node 社区影响深远,要做包管理工具, 完全跟他做的 NPM 不沾边是不实际的。在本项目中,依赖的与 NPM 相关的包有:

  • tar
  • semver
  • fstream
  • fstream-npm

tar

tar 是 NPM 中使用的打包库,作用很简单,就是 tar foo.tar foo,封装了各个平台的兼容性,提供了统一的接口:

fstream
  .Reader('path/to/package')
  .pipe(tar.Pack())
  .pipe(fstream.Writer('package.tar'))
  .on('close', function() {
    fs.existsSync('package.tar')
    // ==> true
  })

要打包(tar)一个组件目录,只需将其作为输入流,输送(pipe)到 tar.Pack(),再输送到输出流即可。 还可以中间加一个压缩步骤:

fstream
  .Reader('path/to/package')
  .pipe(tar.Pack())
  .pipe(zlib.Gunzip()) // Node 自带
  .pipe(fstream.Writer('package.tgz'))

fstream

fstream 自然不得不提,不清楚 Node 里是什么时候开始有这种流的设计,我还搞不太懂, 只能参考例子凑合着用,在 Node 里,我们可以如此打包、压缩单个文件:

fs.createReadStream('db-backup.sql')
  .pipe(tar.pack())
  .pipe(zlib.Gunzip())
  .pipe(fs.createWriteStream('db-backup.tgz'))

但是 fs.createReadStream 不支持从目录读取,因此大神 isaacs 封装了 fstream,方便操作。

在 fstream 的基础上,他又搞了 fstream-ignore 和 fstream-npm

fstream-npm

简单说,这个库的作用就是以一个目录为输入流,根据其中的三个文件内容,忽略掉此目录中的一些文件。 这个忽略的功能,自然是依靠 fstream-ignore 实现的。这三个文件是:

前两个不言自明,在 fstream-ignore 中已实现,fstream-npm 扩展了第三个,即允许用户在 package.json 中使用 files 属性显示指明所包含的文件,类似:

{
  "files": ["index.js", "mosaic.js"]
}

semver

语义化版本,去年就广而告之了,从官网做了摘要,翻译如下:

首先,你要声明一个公共 API。可以由文档和代码本身的约束组成。无论如何,首要的是这个 API 要清晰并且准确。 一旦确认了你的公共 API,你就要通过版本号中的特定上升来说明 API 的改变。设想一种版本格式为 X.Y.Z , 主版本号.次版本号.补丁版本号。不影响 API 的修复版本,上升补丁版本号;向后兼容的 API 增加、修改, 上升次版本号;向后不兼容的 API 修改,则增加主版本号。

详细的规则,和两个版本号的比较,semver.org 都有,isaacs 在 Node 中实现了这一逻辑, 并在 node-semver 的 README 中描述了其 API, 和版本号比较的逻辑。

npm loves you