目的
Node.jsの開発でSails.jsを使ってます。複数のアプリケーションでModel/Serviceを共有したい時があると思うんですが、npm化して共有するにはどうしたら良いか調べました。
前提
sails-generate-entitiesというnpmを利用して継承コピーするような形で複数アプリケーションで共有します。最初はSailsのinstallable hookの仕組みを使ってModelやServiceを差し込もうとしていたんですが、どうも安定して動かないのでこの方法に落ち着きました。
手順
sails-generate-entitiesをインストールする
複数のアプリケーションで共有したいModel等を持っているアプリケーションにsails-generate-entitiesをインストールします。
$ npm install --save sails-generate-entities
index.jsを記述する
書き方はこちらが参考になる。
https://github.com/tjwebb/sails-permissions/blob/master/index.js
モジュール名にはこのアプリケーションの名称というかnpmの名称を入れるイメージで、IDにはsails generate <ID>というイメージで呼び出すくらいの感じで理解しておく。下記はModelとServiceだけを対象にするindex.jsです。
module.exports = require('sails-generate-entities')({
module: '<モジュール名>',
id: '<ID>',
statics: [
'api/models/Article.js',
'api/models/ArticleTag.js',
'api/models/Comment.js',
'api/models/Tag.js',
],
classes: [
'api/services/ArticleService.js',
],
functions: [
]
});
ちなみに直接モデル名とか指定しなきゃいけないのがややイケてないですが…。module.exportsの手前でフォルダの中身調べて〜というようなプログラムを書いたんですが、exportsが読まれるタイミングに間に合わないのか全くうまくいきませんでした。
npmをGitHubでホストする
作ったSailsアプリケーションをnpmとしてGitHubでホストします。いつもどおりリポジトリを作っておくだけで良かったと思います。プライベートでももちろん大丈夫です。
利用するアプリケーション側でnpmをインストールする
package.jsonの書き方は下記のような感じです。Publicなリポジトリの場合は普通にhttpでも大丈夫です。Privateの場合は、git+sshでやると良いようです。ちなみにこの場合は、npm installするユーザーの.sshにGitHubで作成したSSH Key(公開鍵)に対応する秘密鍵をid_rsaという名称で保存しておくとスムーズにいくようです。
{
"name": "hoge",
"private": true,
"version": "0.0.0",
"description": "a Sails application",
"keywords": [],
"dependencies": {
"<npm名>": "git+ssh://git@github.com:<個人orチームアカウント>/<リポジトリ名>.git",
"bluebird": "^2.9.14",
...
"lodash": "^3.6.0",
"rc": "~0.5.0",
"sails": "~0.11.0",
"sails-disk": "~0.10.0",
"sails-mysql": "^0.10.11"
},
"scripts": {
"start": "node app.js",
"debug": "node debug app.js",
},
"main": "app.js",
"devDependencies": {
...
}
}
ここを見ると、npmのバージョン番号の指定などいろいろ設定できそうな事が分かります。
https://docs.npmjs.com/cli/install
ちなみにsails-generate-entitiesがlodashを使う関係上、lodashは入れておく必要があります。
.sailsrcを編集する
.sailsrcファイルを編集します。
{
"generators": {
"modules": {
"<Generatorの引数として受けたい名称>": "<npmモジュール名称>"
}
}
}
ジェネレータを実行しnpmから継承コピーする
$ sails generate <Generatorの引数として受けたい名称>
これでnpm内部のindex.jsで指定されたファイルが、アプリケーションの中でコピーされます。コピーされたファイルはこのような感じになっています。「これしか方法はないのか…」という感じですが、コピーされたファイルを見てもまあ一番安全で確実な方法だとは思います。。
// api/models/Article.js
var _ = require('lodash');
var _super = require('SELECK_models/api/models/Article');
_.merge(exports, _super);
_.merge(exports, {
// Extend with custom logic here by adding additional fields, methods, etc.
/**
* For example:
*
* foo: function (bar) {
* bar.x = 1;
* bar.y = 2;
* return _super.foo(bar);
* }
*/
});
もちろん普通にsails liftできて、普通に動きます。