@chevre/domain 22.9.0-alpha.71 → 22.9.0-alpha.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ // tslint:disable:no-console
2
+ import * as moment from 'moment';
3
+ import * as mongoose from 'mongoose';
4
+
5
+ import { chevre } from '../../../lib/index';
6
+
7
+ // const project = { id: String(process.env.PROJECT_ID) };
8
+
9
+ // tslint:disable-next-line:max-func-body-length
10
+ async function main() {
11
+ await mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });
12
+
13
+ const transactionRepo = await chevre.repository.Transaction.createInstance(mongoose.connection);
14
+ const result = await transactionRepo.countPotentiallyExpired({
15
+ expires: {
16
+ $lt: moment()
17
+ // tslint:disable-next-line:no-magic-numbers
18
+ .add(-60, 'seconds')
19
+ .toDate()
20
+ },
21
+ limit: 10
22
+ });
23
+ console.log('result', result);
24
+ }
25
+
26
+ main()
27
+ .then()
28
+ .catch(console.error);
@@ -0,0 +1,56 @@
1
+ // tslint:disable:no-console
2
+ import * as moment from 'moment';
3
+ import * as mongoose from 'mongoose';
4
+
5
+ import { chevre } from '../../../lib/index';
6
+
7
+ // const project = { id: String(process.env.PROJECT_ID) };
8
+
9
+ async function main() {
10
+ await mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });
11
+
12
+ const taskRepo = await chevre.repository.Task.createInstance(mongoose.connection);
13
+ const sendGridCredentials = await chevre.credentials.SendGrid.createInstance({
14
+ apiKey: <string>process.env.SENDGRID_API_KEY,
15
+ alert: {
16
+ sender: {
17
+ name: 'xxx',
18
+ email: 'xxx'
19
+ },
20
+ toRecipient: [
21
+ { email: 'xxx' }
22
+ ]
23
+ }
24
+ });
25
+ const chevreSettings = new chevre.settings.Settings(<any>{
26
+ abortedTasksWithoutReport: [
27
+ chevre.factory.taskName.ImportEventCapacitiesFromCOA,
28
+ chevre.factory.taskName.ImportEventsFromCOA,
29
+ chevre.factory.taskName.ImportOffersFromCOA
30
+ ]
31
+ });
32
+
33
+ const result = await (await chevre.service.task.createService()).notifyAbortedTasksByEmail({
34
+ dateAbortedGte: moment()
35
+ // tslint:disable-next-line:no-magic-numbers
36
+ .add(-10, 'days')
37
+ .toDate()
38
+ })(
39
+ {
40
+ task: taskRepo
41
+ },
42
+ chevreSettings,
43
+ {
44
+ sendGrid: sendGridCredentials
45
+ }
46
+ );
47
+ // tslint:disable-next-line:no-null-keyword
48
+ console.dir(result, { depth: null });
49
+ }
50
+
51
+ main()
52
+ .then(console.log)
53
+ .catch((error) => {
54
+ // tslint:disable-next-line:no-null-keyword
55
+ console.dir(error, { depth: null });
56
+ });
@@ -1,11 +1,24 @@
1
+ interface IAlert {
2
+ sender?: {
3
+ name: string;
4
+ email: string;
5
+ };
6
+ toRecipient?: [
7
+ {
8
+ email: string;
9
+ }
10
+ ];
11
+ }
1
12
  interface IOptions {
2
13
  apiKey: string;
14
+ alert?: IAlert;
3
15
  }
4
16
  /**
5
17
  * SendGrid認証情報
6
18
  */
7
19
  declare class SendGridCredentials {
8
20
  readonly apiKey: string;
21
+ readonly alert?: IAlert;
9
22
  constructor(options: IOptions);
10
23
  }
11
24
  export { SendGridCredentials };
@@ -6,8 +6,11 @@ exports.SendGridCredentials = void 0;
6
6
  */
7
7
  class SendGridCredentials {
8
8
  constructor(options) {
9
- const { apiKey } = options;
9
+ const { apiKey, alert } = options;
10
10
  this.apiKey = apiKey;
11
+ if (alert !== undefined) {
12
+ this.alert = alert;
13
+ }
11
14
  }
12
15
  }
13
16
  exports.SendGridCredentials = SendGridCredentials;
@@ -168,6 +168,17 @@ export declare class TransactionRepo {
168
168
  setTasksExportedById(params: {
169
169
  id: string;
170
170
  }): Promise<void>;
171
+ /**
172
+ * add(2025-03-13~)
173
+ */
174
+ countPotentiallyExpired(params: {
175
+ expires: {
176
+ $lt: Date;
177
+ };
178
+ limit?: number;
179
+ }): Promise<{
180
+ count: number;
181
+ }>;
171
182
  /**
172
183
  * add(2025-03-03~)
173
184
  */
@@ -793,6 +793,24 @@ class TransactionRepo {
793
793
  .exec();
794
794
  });
795
795
  }
796
+ /**
797
+ * add(2025-03-13~)
798
+ */
799
+ countPotentiallyExpired(params) {
800
+ return __awaiter(this, void 0, void 0, function* () {
801
+ const { expires, limit } = params;
802
+ const query = this.transactionModel.countDocuments({
803
+ status: { $eq: factory.transactionStatusType.InProgress },
804
+ expires: { $lt: expires.$lt }
805
+ });
806
+ if (typeof limit === 'number' && limit >= 0) {
807
+ query.limit(limit);
808
+ }
809
+ const count = yield query.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
810
+ .exec();
811
+ return { count };
812
+ });
813
+ }
796
814
  /**
797
815
  * add(2025-03-03~)
798
816
  */
@@ -24,6 +24,15 @@ declare function sendEmailMessage(params: factory.task.sendEmailMessage.IActionA
24
24
  }, credentials: {
25
25
  sendGrid: SendGridCredentials;
26
26
  }) => Promise<void>;
27
+ declare function notifyByEmail(params: {
28
+ subject: string;
29
+ content: string;
30
+ logLevel: LineNotifyLogLevel;
31
+ }): (__: {}, credentials: {
32
+ sendGrid: SendGridCredentials;
33
+ }) => Promise<{
34
+ result: import("@chevre/factory/lib/action/transfer/send/message/email").IResult;
35
+ }>;
27
36
  type LineNotifyLogLevel = 'log' | 'error' | 'info';
28
37
  declare function lineNotify({ subject, content, imageThumbnail, imageFullsize, logLevel }: {
29
38
  subject: string;
@@ -41,4 +50,4 @@ declare function triggerWebhook(params: factory.task.IData<factory.taskName.Trig
41
50
  potentialAction: PotentialActionRepo;
42
51
  setting: SettingRepo;
43
52
  }) => Promise<void>;
44
- export { lineNotify, sendEmailMessage, triggerWebhook };
53
+ export { lineNotify, notifyByEmail, sendEmailMessage, triggerWebhook };
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.lineNotify = lineNotify;
13
+ exports.notifyByEmail = notifyByEmail;
13
14
  exports.sendEmailMessage = sendEmailMessage;
14
15
  exports.triggerWebhook = triggerWebhook;
15
16
  const sgMail = require("@sendgrid/mail");
@@ -133,6 +134,114 @@ function sendEmailMessage(params) {
133
134
  yield repos.action.completeWithVoid({ typeOf: action.typeOf, id: action.id, result: result, recipe });
134
135
  });
135
136
  }
137
+ // tslint:disable-next-line:max-func-body-length
138
+ function notifyByEmail(params
139
+ // options: {
140
+ // timeout: number;
141
+ // useFetchAPI: boolean;
142
+ // }
143
+ ) {
144
+ // tslint:disable-next-line:cyclomatic-complexity max-func-body-length
145
+ return (__, credentials) => __awaiter(this, void 0, void 0, function* () {
146
+ var _a, _b, _c, _d, _e, _f, _g, _h;
147
+ const shortSubject = params.subject;
148
+ const message = util.format('\n%s\n%s\n%s\n%s\n%s\n\n%s', `[${params.logLevel}] ${shortSubject}`, `now:${(new Date()).toISOString()}`, `pid:${process.pid}`, `GAE_APPLICATION:${process.env.GAE_APPLICATION}`,
149
+ // `GAE_INSTANCE:${process.env.GAE_INSTANCE}`,
150
+ `GAE_SERVICE:${process.env.GAE_SERVICE}`, params.content);
151
+ let msg;
152
+ let result = {};
153
+ try {
154
+ const apiKey = credentials.sendGrid.apiKey;
155
+ if (typeof apiKey !== 'string') {
156
+ throw new factory.errors.Internal('API Key not found');
157
+ }
158
+ sgMail.setApiKey(apiKey);
159
+ const senderName = (_b = (_a = credentials.sendGrid.alert) === null || _a === void 0 ? void 0 : _a.sender) === null || _b === void 0 ? void 0 : _b.name;
160
+ const senderEmail = (_d = (_c = credentials.sendGrid.alert) === null || _c === void 0 ? void 0 : _c.sender) === null || _d === void 0 ? void 0 : _d.email;
161
+ const toRecipientEmail = (Array.isArray((_e = credentials.sendGrid.alert) === null || _e === void 0 ? void 0 : _e.toRecipient))
162
+ ? (_g = (_f = credentials.sendGrid.alert) === null || _f === void 0 ? void 0 : _f.toRecipient.at(0)) === null || _g === void 0 ? void 0 : _g.email
163
+ : undefined;
164
+ if (typeof senderName !== 'string') {
165
+ throw new factory.errors.Internal('senderName not found');
166
+ }
167
+ if (typeof senderEmail !== 'string') {
168
+ throw new factory.errors.Internal('senderEmail not found');
169
+ }
170
+ if (typeof toRecipientEmail !== 'string') {
171
+ throw new factory.errors.Internal('toRecipientEmail not found');
172
+ }
173
+ const emailMessage = {
174
+ about: {
175
+ typeOf: 'Thing',
176
+ identifier: 'TaskAborted',
177
+ name: shortSubject
178
+ },
179
+ identifier: 'taskAborted',
180
+ sender: {
181
+ name: senderName,
182
+ email: senderEmail
183
+ },
184
+ text: message,
185
+ toRecipient: [{
186
+ name: 'developers',
187
+ email: toRecipientEmail
188
+ }],
189
+ typeOf: factory.creativeWorkType.EmailMessage
190
+ };
191
+ const emailMessageFrom = {
192
+ name: emailMessage.sender.name,
193
+ email: emailMessage.sender.email
194
+ };
195
+ let subject;
196
+ // 互換性維持対応として、String型に対応
197
+ if (typeof emailMessage.about === 'string') {
198
+ if (String(emailMessage.about).length > 0) {
199
+ subject = String(emailMessage.about);
200
+ }
201
+ }
202
+ else if (typeof ((_h = emailMessage.about) === null || _h === void 0 ? void 0 : _h.name) === 'string') {
203
+ if (emailMessage.about.name.length > 0) {
204
+ subject = emailMessage.about.name;
205
+ }
206
+ }
207
+ const emailDatas = (Array.isArray(emailMessage.toRecipient))
208
+ ? emailMessage.toRecipient.map((toRecipient) => {
209
+ return {
210
+ name: toRecipient.name,
211
+ email: toRecipient.email
212
+ };
213
+ })
214
+ // Arrayでない時期への互換性維持対応
215
+ : [{
216
+ name: emailMessage.toRecipient.name,
217
+ email: emailMessage.toRecipient.email
218
+ }];
219
+ msg = Object.assign(Object.assign(Object.assign({ to: emailDatas, from: emailMessageFrom }, (typeof subject === 'string') ? { subject } : undefined), (String(emailMessage.text).length > 0) ? { text: String(emailMessage.text) } : undefined), {
220
+ // html: '<strong>and easy to do anywhere, even with Node.js</strong>',
221
+ // categories: ['Transactional', 'My category'],
222
+ // 送信予定を追加することもできるが、タスクの実行予定日時でコントロールする想定
223
+ // sendAt: moment(email.send_at).unix(),
224
+ // 追跡用に通知IDをカスタムフィールドとしてセットする
225
+ customArgs: {
226
+ emailMessage: emailMessage.identifier
227
+ // actionId: action.id,
228
+ // projectId: project.id
229
+ } });
230
+ // mlutiple recipients対応(2023-03-06~)
231
+ const response = yield sgMail.sendMultiple(msg);
232
+ // check the response.
233
+ if (response[0].statusCode !== http_status_1.ACCEPTED) {
234
+ throw new factory.errors.Internal(`sendgrid request not accepted. response is ${util.inspect(response)}`);
235
+ }
236
+ const { statusCode, statusMessage } = response[0];
237
+ result = { statusCode, statusMessage };
238
+ }
239
+ catch (error) {
240
+ throw error;
241
+ }
242
+ return { result };
243
+ });
244
+ }
136
245
  const MAX_LINE_NOTIFY_SUBJECT_LENGTH = 100;
137
246
  function lineNotify({ subject, content, imageThumbnail, imageFullsize, logLevel }
138
247
  // options: {
@@ -72,14 +72,17 @@ declare function execute(task: IExecutableTask<factory.taskName>): IOperationExe
72
72
  /**
73
73
  * トライ可能回数が0に達したタスクを実行中止する
74
74
  */
75
- declare function abort(params: {
76
- /**
77
- * 最終トライ日時から何分経過したタスクを中止するか
78
- */
79
- intervalInMinutes: number;
80
- notify: boolean;
81
- }): TaskOperation<void>;
82
75
  declare function notifyAbortedTasks(params: {
83
76
  dateAbortedGte: Date;
84
77
  }): TaskOperation<void>;
85
- export { ICallResult, IExecutableTaskKeys, IOperationExecute, executeById, executeOneIfExists, execute, abort, notifyAbortedTasks };
78
+ /**
79
+ * add(2025-03-13~)
80
+ */
81
+ declare function notifyAbortedTasksByEmail(params: {
82
+ dateAbortedGte: Date;
83
+ }): (repos: {
84
+ task: TaskRepo;
85
+ }, settings: Pick<Settings, "abortedTasksWithoutReport">, credentials: {
86
+ sendGrid: SendGridCredentials;
87
+ }) => Promise<void>;
88
+ export { ICallResult, IExecutableTaskKeys, IOperationExecute, executeById, executeOneIfExists, execute, notifyAbortedTasks, notifyAbortedTasksByEmail };
@@ -12,8 +12,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.executeById = executeById;
13
13
  exports.executeOneIfExists = executeOneIfExists;
14
14
  exports.execute = execute;
15
- exports.abort = abort;
16
15
  exports.notifyAbortedTasks = notifyAbortedTasks;
16
+ exports.notifyAbortedTasksByEmail = notifyAbortedTasksByEmail;
17
17
  /**
18
18
  * タスクサービス
19
19
  */
@@ -154,25 +154,62 @@ let notification;
154
154
  /**
155
155
  * トライ可能回数が0に達したタスクを実行中止する
156
156
  */
157
- function abort(params) {
157
+ // function abort(params: {
158
+ // /**
159
+ // * 最終トライ日時から何分経過したタスクを中止するか
160
+ // */
161
+ // intervalInMinutes: number;
162
+ // notify: boolean;
163
+ // }): TaskOperation<void> {
164
+ // return async (
165
+ // repos: {
166
+ // setting: SettingRepo;
167
+ // task: TaskRepo;
168
+ // },
169
+ // settings: Pick<Settings, 'abortedTasksWithoutReport'>,
170
+ // credentials: {
171
+ // lineNotify: LINENotifyCredentials;
172
+ // }
173
+ // ) => {
174
+ // const { abortedTasksWithoutReport } = settings;
175
+ // const abortedTask = await repos.task.abortOne(params);
176
+ // // tslint:disable-next-line:no-single-line-block-comment
177
+ // /* istanbul ignore if */
178
+ // if (abortedTask === null) {
179
+ // return;
180
+ // }
181
+ // if (params.notify === true) {
182
+ // // 中止を報告しないタスクであれば終了
183
+ // if (abortedTasksWithoutReport.includes(abortedTask.name)) {
184
+ // return;
185
+ // }
186
+ // if (notification === undefined) {
187
+ // notification = await import('./notification');
188
+ // }
189
+ // // 開発者へ報告
190
+ // const message = task2lineNotify({ task: abortedTask });
191
+ // await notification.lineNotify(
192
+ // {
193
+ // subject: message.subject, content: message.content,
194
+ // logLevel: 'error'
195
+ // }
196
+ // // { timeout, useFetchAPI }
197
+ // )(undefined, credentials);
198
+ // }
199
+ // };
200
+ // }
201
+ function notifyAbortedTasks(params) {
158
202
  return (repos, settings, credentials) => __awaiter(this, void 0, void 0, function* () {
159
203
  const { abortedTasksWithoutReport } = settings;
160
- const abortedTask = yield repos.task.abortOne(params);
161
- // tslint:disable-next-line:no-single-line-block-comment
162
- /* istanbul ignore if */
163
- if (abortedTask === null) {
164
- return;
165
- }
166
- if (params.notify === true) {
167
- // 中止を報告しないタスクであれば終了
168
- if (abortedTasksWithoutReport.includes(abortedTask.name)) {
169
- return;
170
- }
204
+ const abortedTasks = yield repos.task.projectFields(Object.assign({ statuses: [factory.taskStatus.Aborted], dateAborted: { $gte: params.dateAbortedGte } }, (abortedTasksWithoutReport.length > 0)
205
+ ? { name: { $nin: abortedTasksWithoutReport } }
206
+ : undefined), []);
207
+ if (abortedTasks.length > 0) {
171
208
  if (notification === undefined) {
172
209
  notification = yield Promise.resolve().then(() => require('./notification'));
173
210
  }
174
211
  // 開発者へ報告
175
- const message = (0, factory_1.task2lineNotify)({ task: abortedTask });
212
+ const message = (0, factory_1.tasks2lineNotify)({ tasks: abortedTasks });
176
213
  yield notification.lineNotify({
177
214
  subject: message.subject, content: message.content,
178
215
  logLevel: 'error'
@@ -182,7 +219,10 @@ function abort(params) {
182
219
  }
183
220
  });
184
221
  }
185
- function notifyAbortedTasks(params) {
222
+ /**
223
+ * add(2025-03-13~)
224
+ */
225
+ function notifyAbortedTasksByEmail(params) {
186
226
  return (repos, settings, credentials) => __awaiter(this, void 0, void 0, function* () {
187
227
  const { abortedTasksWithoutReport } = settings;
188
228
  const abortedTasks = yield repos.task.projectFields(Object.assign({ statuses: [factory.taskStatus.Aborted], dateAborted: { $gte: params.dateAbortedGte } }, (abortedTasksWithoutReport.length > 0)
@@ -194,12 +234,11 @@ function notifyAbortedTasks(params) {
194
234
  }
195
235
  // 開発者へ報告
196
236
  const message = (0, factory_1.tasks2lineNotify)({ tasks: abortedTasks });
197
- yield notification.lineNotify({
237
+ const notifyResult = yield notification.notifyByEmail({
198
238
  subject: message.subject, content: message.content,
199
239
  logLevel: 'error'
200
- }
201
- // { timeout, useFetchAPI }
202
- )(undefined, credentials);
240
+ })({}, credentials);
241
+ debug('notifyResult:', notifyResult);
203
242
  }
204
243
  });
205
244
  }
package/package.json CHANGED
@@ -112,5 +112,5 @@
112
112
  "postversion": "git push origin --tags",
113
113
  "prepublishOnly": "npm run clean && npm run build && npm test && npm run doc"
114
114
  },
115
- "version": "22.9.0-alpha.71"
115
+ "version": "22.9.0-alpha.73"
116
116
  }