-
Notifications
You must be signed in to change notification settings - Fork 12
/
09s-creating-a-meteorite-package.md.erb
247 lines (186 loc) · 9.11 KB
/
09s-creating-a-meteorite-package.md.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
---
title: Meteor 패키지 만들기
slug: creating-a-meteor-package
date: 0009/01/02
number: 9.5
sidebar: true
contents: Local in-app 패키지를 작성한다.|패키지에 대한 몇 가지 테스트 방법을 알아본다.|작성한 패키지를 Atmosphere에 릴리즈한다.
paragraphs: 22
---
오류에 대한 재사용 가능한 패턴을 구축했는데, 이를 묶어 스마트 패키지를 만들고 이를 미티어 커뮤니티에서 공유하도록 하면 어떨까?
첫째, 이 패키지의 구조를 만들어야 한다. 우리는 이 패키지를 `packages/errors` 라는 이름의 디렉토리에 넣는다. 이렇게 하면 자동으로 사용되는 커스텀 패키지가 된다(Meteor가 `packages/` 디렉토리 에 symlink로 패키지를 설치한다는 사실을 알지 모르겠다).
둘째, 그 폴더에 `package.js`를 만든다. 이 파일은 미티어에게 해당 패키지를 사용하는 방법과 그 패키지가 내보내는 symbol들을 알려준다.
~~~js
Package.describe({
summary: "A pattern to display application errors to the user"
});
Package.on_use(function (api, where) {
api.use(['minimongo', 'mongo-livedata', 'templating'], 'client');
api.add_files(['errors.js', 'errors_list.html', 'errors_list.js'], 'client');
if (api.export)
api.export('Errors');
});
~~~
<%= caption "packages/errors/package.js" %>
이 패키지에 세 개의 파일들을 추가한다. 이 파일들은 Microscope에서 가져오는데 네임스페이스를 바꾸는 것과 약간 개선된 API를 제외하면 거의 변화가 없다:
~~~js
Errors = {
// Local (client-only) collection
collection: new Meteor.Collection(null),
throw: function(message) {
Errors.collection.insert({message: message, seen: false})
},
clearSeen: function() {
Errors.collection.remove({seen: true});
}
};
~~~
<%= caption "packages/errors/errors.js" %>
~~~html
<template name="meteorErrors">
{{#each errors}}
{{> meteorError}}
{{/each}}
</template>
<template name="meteorError">
<div class="alert alert-error">
<button type="button" class="close" data-dismiss="alert">×</button>
{{message}}
</div>
</template>
~~~
<%= caption "packages/errors/errors_list.html" %>
~~~js
Template.meteorErrors.helpers({
errors: function() {
return Errors.collection.find();
}
});
Template.meteorError.rendered = function() {
var error = this.data;
Meteor.defer(function() {
Errors.collection.update(error._id, {$set: {seen: true}});
});
};
~~~
<%= caption "packages/errors/errors_list.js" %>
### Microscope로 패키지 테스트하기
작성한 코드가 작동하는 지를 확인하기 위해 로컬에서 Microscope로 테스트를 진행한다. 패키지를 프로젝트에 연동하기 위해 `meteor add errors` 명령을 수행한다. 그 다음, 이 새 패키지로 인해서 필요없게 된 기존의 파일들을 삭제한다:
~~~bash
$ rm client/helpers/errors.js
$ rm client/views/includes/errors.html
$ rm client/views/includes/errors.js
~~~
<%= caption "bash 콘솔에서 예전 파일들을 삭제하기" %>
한 가지 더 할 일은 올바른 API를 사용하도록 약간 수정을 하는 것이다:
~~~js
Router.onBeforeAction(function() { Errors.clearSeen(); });
~~~
<%= caption "lib/router.js" %>
~~~html
{{> header}}
{{> meteorErrors}}
~~~
<%= caption "client/views/application/layout.html" %>
~~~js
Meteor.call('post', post, function(error, id) {
if (error) {
// display the error to the user
Errors.throw(error.reason);
~~~
<%= caption "client/views/posts/post_submit.js" %>
~~~js
Posts.update(currentPostId, {$set: postProperties}, function(error) {
if (error) {
// display the error to the user
Errors.throw(error.reason);
~~~
<%= caption "client/views/posts/post_edit.js" %>
<%= scommit "9-5-1", "기본적인 오류 패키지를 만들고 이를 연동했다." %>
이 수정작업이 완료되고 나면, 패키지 이전의 상태로 되돌려야 한다.
### 테스트 작성하기
패키지를 개발하는 첫 단계는 애플리케이션에서 테스트하는 것이지만, 그 다음 단계는 패키지의 작동을 적절하게 테스트하는 테스트 세트를 작성하는 것이다. 미티어 자체에 Tinytest(빌트인 패키지 테스터)가 들어있는 데, 이것을 이용하면 테스트를 쉽게 할 수 있고, 다른 사람들과 이 패키지를 공유할 때 평정심을 유지할 수 있다.
오류 코드로 몇 가지 테스트를 수행하기 위해 Tinytest를 사용하는 테스트 파일을 만들어보자:
~~~js
Tinytest.add("Errors collection works", function(test) {
test.equal(Errors.collection.find({}).count(), 0);
Errors.throw('A new error!');
test.equal(Errors.collection.find({}).count(), 1);
Errors.collection.remove({});
});
Tinytest.addAsync("Errors template works", function(test, done) {
Errors.throw('A new error!');
test.equal(Errors.collection.find({seen: false}).count(), 1);
// render the template
OnscreenDiv(Spark.render(function() {
return Template.meteorErrors();
}));
// wait a few milliseconds
Meteor.setTimeout(function() {
test.equal(Errors.collection.find({seen: false}).count(), 0);
test.equal(Errors.collection.find({}).count(), 1);
Errors.clearSeen();
test.equal(Errors.collection.find({seen: true}).count(), 0);
done();
}, 500);
});
~~~
<%= caption "packages/errors/errors_tests.js" %>
이 테스트에서는 기본함수인 `Meteor.Errors`이 동작하는 지를 검사한다. 뿐만 아니라 템플릿에서 `rendered` 코드가 여전히 기능하는 지에 대해서도 검사한다.
미티어 패키지 테스트를 작성하는 과정의 세세한 것까지 여기서 다루지는 않을 것이다(API는 아직 확정된 것이 아니고 매우 유동적이다). 하지만 희망하건데 이것의 작동 방법은 자체로 입증이 될 것이다.
미티어에게 `package.js`에서의 테스트 실행 방법을 지시하려면 다음 코드를 사용하기 바란다:
~~~js
Package.on_test(function(api) {
api.use('tmeasday:errors', 'client');
api.use(['tinytest', 'test-helpers'], 'client');
api.add_files('errors_tests.js', 'client');
});
~~~
<%= caption "packages/errors/package.js" %>
<%= scommit "9-5-2", "패키지에 테스트 기능을 추가했다." %>
그러면 다음 명령어로 테스트를 실행할 수 있다:
~~~bash
$ meteor test-packages tmeasday:errors
~~~
<%= caption "터미널" %>
<%= screenshot "s7-1", "모든 테스트 통과" %>
### 패키지 릴리즈
이제, 패키지를 릴리즈하여 모두가 이를 이용할 수 있게 하려고 한다. 그렇게 하려면 Atmosphere에 올리면 된다.
우선, `smart.json`을 추가하여 Meteor와 Atmosphere에 그 패키지에 대한 중요한 상세 내용을 알린다:
~~~json
{
"name": "errors",
"description": "A pattern to display application errors to the user",
"homepage": "https://github.com/tmeasday/meteor-errors",
"author": "Tom Coleman <[email protected]>",
"version": "0.1.0",
"git": "https://github.com/tmeasday/meteor-errors.git",
"packages": {
}
}
~~~
<%= caption "packages/errors/smart.json" %>
<%= scommit "9-5-3", "smart.json 파일을 추가했다." %>
그 패키지에 대한 정보를 제공하기 위하여 몇 가지 기본적인 메타데이터를 넣는다. 여기에는 이것의 주요 기능, 호스트 git 주소, 그리고 초기 버전 정보가 포함된다. 만약 이 패키지가 다른 Atmosphere 패키지에 의존한다면, 그 의존성 정보를 기술하는 `"packages"` 섹션을 추가한다.
이 모두가 마무리되면 릴리즈는 쉽다. git 저장소를 만들고 원격 git 서버로 올리고, `smart.json`에 그 주소에 대한 연결정보를 추가한다.
[GitHub](http://github.com)에서 이 작업을 하려면, 우선 새 저장소를 만든 다음, 그 저장소에서 패키지의 코드를 얻는 일반적인 과정을 따른다. 그리고, `meteor release` 명령어를 사용하여 게재한다:
~~~bash
$ git init
$ git add -A
$ git commit -m "Created Errors Package"
$ git remote add origin https://github.com/tmeasday/meteor-errors.git
$ git push origin master
$ meteor release .
Done!
~~~
<%= caption "터미널 (`packages/errors` 내에서 실행한다)" %>
주: 패키지 이름은 유일해야 한다. 위의 내용을 문자 그대로 따라하여 동일한 패키지 이름을 사용하면, 충돌이 발생해서 작동하지 않게 될 것이다. 미래에 Atmosphere는 저자에 따른 네임스페이스를 가지게 될 것이므로, 이 이름이 바뀔 수 있다는 점을 감안하기 바란다.
두 번째 주: http://atmosphere.meteor.com에 로그인하여 `meteor release`를 호출할 때 커맨드 라인에서 입력할 username과 비밀번호를 만들어야 한다.
이제 패키지가 릴리즈되면, 프로젝트에서 그것을 제거하고 그것을 직접 추가하여 복원한다:
~~~bash
$ rm -r packages/errors
$ meteor add errors
~~~
<%= caption "터미널 (앱의 루트 경로에서 실행한다)" %>
<%= scommit "9-5-4", "개발 트리에서 패키지를 삭제했다." %>
이제 Meteor에서 패키지를 다운로드하는 것을 처음으로 볼 수 있을 것이다. 잘했다!