@chevre/domain 22.9.0-alpha.84 → 22.9.0-alpha.85
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.
- package/lib/chevre/service/assetTransaction/reserve/exportTasksById.d.ts +1 -2
- package/lib/chevre/service/assetTransaction/reserve/exportTasksById.js +1 -3
- package/lib/chevre/service/assetTransaction.d.ts +1 -2
- package/lib/chevre/service/assetTransaction.js +2 -2
- package/lib/chevre/service/notification/notifyByEmail.d.ts +12 -0
- package/lib/chevre/service/notification/notifyByEmail.js +93 -0
- package/lib/chevre/service/notification/sendEmailMessage.d.ts +20 -0
- package/lib/chevre/service/notification/sendEmailMessage.js +136 -0
- package/lib/chevre/service/notification/triggerWebhook.d.ts +14 -0
- package/lib/chevre/service/notification/triggerWebhook.js +213 -0
- package/lib/chevre/service/notification.d.ts +3 -41
- package/lib/chevre/service/notification.js +7 -513
- package/package.json +2 -2
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { Settings } from '../../../settings';
|
|
2
1
|
import type { AssetTransactionRepo } from '../../../repo/assetTransaction';
|
|
3
2
|
import type { TaskRepo } from '../../../repo/task';
|
|
4
3
|
type ITaskAndTransactionOperation<T> = (repos: {
|
|
5
4
|
task: TaskRepo;
|
|
6
5
|
assetTransaction: AssetTransactionRepo;
|
|
7
|
-
}
|
|
6
|
+
}) => Promise<T>;
|
|
8
7
|
/**
|
|
9
8
|
* 取引タスク出力
|
|
10
9
|
*/
|
|
@@ -16,9 +16,7 @@ const factory = require("../../../factory");
|
|
|
16
16
|
*/
|
|
17
17
|
function exportTasksById(params) {
|
|
18
18
|
// tslint:disable-next-line:max-func-body-length
|
|
19
|
-
return (repos
|
|
20
|
-
// settings: Settings
|
|
21
|
-
) => __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
22
20
|
// const { useAssetTransactionSyncProcessing } = settings;
|
|
23
21
|
const transaction = yield repos.assetTransaction.findById({
|
|
24
22
|
typeOf: factory.assetTransactionType.Reserve,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as factory from '../factory';
|
|
2
|
-
import { Settings } from '../settings';
|
|
3
2
|
import type { AssetTransactionRepo } from '../repo/assetTransaction';
|
|
4
3
|
import type { TaskRepo } from '../repo/task';
|
|
5
4
|
import * as CancelReservationTransactionService from './assetTransaction/cancelReservation';
|
|
@@ -40,4 +39,4 @@ export declare function exportOneTransactionTasksIfExists(params: {
|
|
|
40
39
|
}): (repos: {
|
|
41
40
|
task: TaskRepo;
|
|
42
41
|
assetTransaction: AssetTransactionRepo;
|
|
43
|
-
}
|
|
42
|
+
}) => Promise<Pick<factory.assetTransaction.ITransaction<factory.assetTransactionType>, "id" | "typeOf"> | void>;
|
|
@@ -28,7 +28,7 @@ exports.reserve = ReserveTransactionService;
|
|
|
28
28
|
* reimplement as exportOneTransactionTasksIfExists(2025-03-18~)
|
|
29
29
|
*/
|
|
30
30
|
function exportOneTransactionTasksIfExists(params) {
|
|
31
|
-
return (repos
|
|
31
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
32
32
|
var _a;
|
|
33
33
|
const transaction = yield repos.assetTransaction.startExportTasks(Object.assign(Object.assign(Object.assign({ tasksExportAction: {
|
|
34
34
|
agent: { name: params.tasksExportAction.agent.name }
|
|
@@ -79,7 +79,7 @@ function exportOneTransactionTasksIfExists(params) {
|
|
|
79
79
|
yield ReserveTransactionService.exportTasksById({
|
|
80
80
|
id: transaction.id
|
|
81
81
|
// runsTasksAfterInSeconds: params.runsTasksAfterInSeconds
|
|
82
|
-
})(repos
|
|
82
|
+
})(repos);
|
|
83
83
|
break;
|
|
84
84
|
default:
|
|
85
85
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SendGridCredentials } from '../../credentials/sendGrid';
|
|
2
|
+
declare function notifyByEmail(params: {
|
|
3
|
+
subject: string;
|
|
4
|
+
content: string;
|
|
5
|
+
logLevel: LineNotifyLogLevel;
|
|
6
|
+
}): (__: {}, credentials: {
|
|
7
|
+
sendGrid: SendGridCredentials;
|
|
8
|
+
}) => Promise<{
|
|
9
|
+
result: import("@chevre/factory/lib/action/transfer/send/message/email").IResult;
|
|
10
|
+
}>;
|
|
11
|
+
type LineNotifyLogLevel = 'log' | 'error' | 'info';
|
|
12
|
+
export { notifyByEmail };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.notifyByEmail = notifyByEmail;
|
|
13
|
+
const client_1 = require("@sendgrid/client");
|
|
14
|
+
const http_status_1 = require("http-status");
|
|
15
|
+
const util = require("util");
|
|
16
|
+
const factory = require("../../factory");
|
|
17
|
+
// type ILineNotifyOperation<T> = (
|
|
18
|
+
// repos: undefined,
|
|
19
|
+
// credentials: {
|
|
20
|
+
// lineNotify: LINENotifyCredentials;
|
|
21
|
+
// }
|
|
22
|
+
// ) => Promise<T>;
|
|
23
|
+
// tslint:disable-next-line:max-func-body-length
|
|
24
|
+
function notifyByEmail(params) {
|
|
25
|
+
// tslint:disable-next-line:cyclomatic-complexity max-func-body-length
|
|
26
|
+
return (__, credentials) => __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
28
|
+
const { logLevel } = params;
|
|
29
|
+
const shortSubject = params.subject;
|
|
30
|
+
const message = util.format('\n%s\n%s\n%s\n%s\n%s\n\n%s', `[${logLevel}] ${shortSubject}`, `now:${(new Date()).toISOString()}`, `pid:${process.pid}`, `GAE_APPLICATION:${process.env.GAE_APPLICATION}`,
|
|
31
|
+
// `GAE_INSTANCE:${process.env.GAE_INSTANCE}`,
|
|
32
|
+
`GAE_SERVICE:${process.env.GAE_SERVICE}`, params.content);
|
|
33
|
+
let result = {};
|
|
34
|
+
try {
|
|
35
|
+
const apiKey = credentials.sendGrid.apiKey;
|
|
36
|
+
if (typeof apiKey !== 'string') {
|
|
37
|
+
throw new factory.errors.Internal('API Key not found');
|
|
38
|
+
}
|
|
39
|
+
const senderName = (_b = (_a = credentials.sendGrid.alert) === null || _a === void 0 ? void 0 : _a.sender) === null || _b === void 0 ? void 0 : _b.name;
|
|
40
|
+
const senderEmail = (_d = (_c = credentials.sendGrid.alert) === null || _c === void 0 ? void 0 : _c.sender) === null || _d === void 0 ? void 0 : _d.email;
|
|
41
|
+
const toRecipientEmail = (Array.isArray((_e = credentials.sendGrid.alert) === null || _e === void 0 ? void 0 : _e.toRecipient))
|
|
42
|
+
? (_g = (_f = credentials.sendGrid.alert) === null || _f === void 0 ? void 0 : _f.toRecipient.at(0)) === null || _g === void 0 ? void 0 : _g.email
|
|
43
|
+
: undefined;
|
|
44
|
+
if (typeof senderName !== 'string') {
|
|
45
|
+
throw new factory.errors.Internal('senderName not found');
|
|
46
|
+
}
|
|
47
|
+
if (typeof senderEmail !== 'string') {
|
|
48
|
+
throw new factory.errors.Internal('senderEmail not found');
|
|
49
|
+
}
|
|
50
|
+
if (typeof toRecipientEmail !== 'string') {
|
|
51
|
+
throw new factory.errors.Internal('toRecipientEmail not found');
|
|
52
|
+
}
|
|
53
|
+
const emailMessageFrom = {
|
|
54
|
+
name: senderName,
|
|
55
|
+
email: senderEmail
|
|
56
|
+
};
|
|
57
|
+
const subject = `[${logLevel}] ${shortSubject}`;
|
|
58
|
+
const emailDatas = [{
|
|
59
|
+
name: 'developers',
|
|
60
|
+
email: toRecipientEmail
|
|
61
|
+
}];
|
|
62
|
+
const sgClient = new client_1.Client();
|
|
63
|
+
sgClient.setApiKey(apiKey);
|
|
64
|
+
// const response = await sgMail.sendMultiple(msg);
|
|
65
|
+
const response = yield sgClient.request({
|
|
66
|
+
body: {
|
|
67
|
+
content: [{ type: 'text/plain', value: message }],
|
|
68
|
+
from: emailMessageFrom,
|
|
69
|
+
personalizations: [{ to: emailDatas }],
|
|
70
|
+
subject,
|
|
71
|
+
custom_args: {
|
|
72
|
+
emailMessage: subject
|
|
73
|
+
// actionId: action.id,
|
|
74
|
+
// projectId: project.id
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
method: 'POST',
|
|
78
|
+
url: '/v3/mail/send'
|
|
79
|
+
});
|
|
80
|
+
// check the response.
|
|
81
|
+
if (response[0].statusCode !== http_status_1.ACCEPTED) {
|
|
82
|
+
throw new factory.errors.Internal(`sendgrid request not accepted. response is ${util.inspect(response)}`);
|
|
83
|
+
}
|
|
84
|
+
const { statusCode } = response[0];
|
|
85
|
+
// const statusMessage = response[1];
|
|
86
|
+
result = { statusCode };
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
return { result };
|
|
92
|
+
});
|
|
93
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SendGridCredentials } from '../../credentials/sendGrid';
|
|
2
|
+
import * as factory from '../../factory';
|
|
3
|
+
import type { ActionRepo } from '../../repo/action';
|
|
4
|
+
import type { MessageRepo } from '../../repo/message';
|
|
5
|
+
import type { ProjectRepo } from '../../repo/project';
|
|
6
|
+
/**
|
|
7
|
+
* https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html
|
|
8
|
+
*/
|
|
9
|
+
declare function sendEmailMessage(params: factory.task.sendEmailMessage.IActionAttributes & {
|
|
10
|
+
sameAs?: {
|
|
11
|
+
id: string;
|
|
12
|
+
};
|
|
13
|
+
}): (repos: {
|
|
14
|
+
action: ActionRepo;
|
|
15
|
+
message: MessageRepo;
|
|
16
|
+
project: ProjectRepo;
|
|
17
|
+
}, credentials: {
|
|
18
|
+
sendGrid: SendGridCredentials;
|
|
19
|
+
}) => Promise<void>;
|
|
20
|
+
export { sendEmailMessage };
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.sendEmailMessage = sendEmailMessage;
|
|
13
|
+
const client_1 = require("@sendgrid/client");
|
|
14
|
+
// import * as sgMail from '@sendgrid/mail';
|
|
15
|
+
const http_status_1 = require("http-status");
|
|
16
|
+
const util = require("util");
|
|
17
|
+
const factory = require("../../factory");
|
|
18
|
+
const factory_1 = require("./factory");
|
|
19
|
+
function createSendEmailMessageActionAttributes(params) {
|
|
20
|
+
var _a;
|
|
21
|
+
const { agent, object, project, purpose, recipient, typeOf } = params;
|
|
22
|
+
return Object.assign({ agent, object, project, purpose, recipient, typeOf }, (typeof ((_a = params.sameAs) === null || _a === void 0 ? void 0 : _a.id) === 'string') ? { sameAs: { id: params.sameAs.id, typeOf: 'Task' } } : undefined);
|
|
23
|
+
}
|
|
24
|
+
function createMailData(params) {
|
|
25
|
+
return (repos, credentials) => __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
var _a, _b, _c, _d;
|
|
27
|
+
const project = yield repos.project.findById({
|
|
28
|
+
id: params.project.id,
|
|
29
|
+
inclusion: ['settings']
|
|
30
|
+
});
|
|
31
|
+
let mailData;
|
|
32
|
+
let apiKey = credentials.sendGrid.apiKey;
|
|
33
|
+
// プロジェクト固有のSendGrid設定があれば、そちらを使用
|
|
34
|
+
if (typeof ((_a = project.settings) === null || _a === void 0 ? void 0 : _a.sendgridApiKey) === 'string' && project.settings.sendgridApiKey.length > 0) {
|
|
35
|
+
apiKey = project.settings.sendgridApiKey;
|
|
36
|
+
}
|
|
37
|
+
if (typeof apiKey !== 'string') {
|
|
38
|
+
throw new factory.errors.Internal('API Key not found');
|
|
39
|
+
}
|
|
40
|
+
// sgMail.setApiKey(apiKey); // fix(2025-03-14~)
|
|
41
|
+
let emailMessage;
|
|
42
|
+
if (typeof params.object.text === 'string') {
|
|
43
|
+
emailMessage = params.object;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// メッセージリポジトリに対応(2024-04-29~)
|
|
47
|
+
emailMessage = yield repos.message.findByIdentifier({
|
|
48
|
+
identifier: params.object.identifier,
|
|
49
|
+
project: { id: project.id }
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const emailMessageFrom = {
|
|
53
|
+
name: emailMessage.sender.name,
|
|
54
|
+
email: emailMessage.sender.email
|
|
55
|
+
};
|
|
56
|
+
// プロジェクト設定対応(2023-08-21~)
|
|
57
|
+
const senderEmailByProjectSettings = (_d = (_c = (_b = project.settings) === null || _b === void 0 ? void 0 : _b.sendEmailMessage) === null || _c === void 0 ? void 0 : _c.sender) === null || _d === void 0 ? void 0 : _d.email;
|
|
58
|
+
if (typeof senderEmailByProjectSettings === 'string' && senderEmailByProjectSettings.length > 0) {
|
|
59
|
+
emailMessageFrom.email = senderEmailByProjectSettings;
|
|
60
|
+
}
|
|
61
|
+
const subject = emailMessage.about.name;
|
|
62
|
+
const emailDatas = (Array.isArray(emailMessage.toRecipient))
|
|
63
|
+
? emailMessage.toRecipient.map((toRecipient) => {
|
|
64
|
+
return {
|
|
65
|
+
name: toRecipient.name,
|
|
66
|
+
email: toRecipient.email
|
|
67
|
+
};
|
|
68
|
+
})
|
|
69
|
+
: [];
|
|
70
|
+
mailData = Object.assign({ to: emailDatas, from: emailMessageFrom, subject }, (String(emailMessage.text).length > 0) ? { text: String(emailMessage.text) } : undefined);
|
|
71
|
+
return { mailData, emailMessage, apiKey };
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html
|
|
76
|
+
*/
|
|
77
|
+
function sendEmailMessage(params) {
|
|
78
|
+
return (repos, credentials) => __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
const { mailData, emailMessage, apiKey } = yield createMailData(params)(repos, credentials);
|
|
80
|
+
// add recipe(2025-03-12~)
|
|
81
|
+
let recipe = (0, factory_1.createSendEmailMessageRecipe)({
|
|
82
|
+
mailData,
|
|
83
|
+
project: { id: params.project.id }
|
|
84
|
+
});
|
|
85
|
+
const startingAction = createSendEmailMessageActionAttributes(params);
|
|
86
|
+
const action = yield repos.action.start(startingAction, { recipe });
|
|
87
|
+
let result = {};
|
|
88
|
+
try {
|
|
89
|
+
mailData.customArgs = {
|
|
90
|
+
emailMessage: emailMessage.identifier,
|
|
91
|
+
actionId: action.id, // 追跡用に通知IDをカスタムフィールドとしてセットする
|
|
92
|
+
projectId: params.project.id
|
|
93
|
+
};
|
|
94
|
+
// reimplement using Client(2025-03-14~)
|
|
95
|
+
// const response = await sgMail.sendMultiple(mailData);
|
|
96
|
+
const sgClient = new client_1.Client();
|
|
97
|
+
sgClient.setApiKey(apiKey);
|
|
98
|
+
const response = yield sgClient.request({
|
|
99
|
+
body: {
|
|
100
|
+
content: [{ type: 'text/plain', value: mailData.text }],
|
|
101
|
+
from: mailData.from,
|
|
102
|
+
personalizations: [{ to: mailData.to }],
|
|
103
|
+
subject: mailData.subject,
|
|
104
|
+
custom_args: mailData.customArgs
|
|
105
|
+
},
|
|
106
|
+
method: 'POST',
|
|
107
|
+
url: '/v3/mail/send'
|
|
108
|
+
});
|
|
109
|
+
// check the response.
|
|
110
|
+
if (response[0].statusCode !== http_status_1.ACCEPTED) {
|
|
111
|
+
throw new factory.errors.Internal(`sendgrid request not accepted. response is ${util.inspect(response)}`);
|
|
112
|
+
}
|
|
113
|
+
const { statusCode } = response[0];
|
|
114
|
+
result = { statusCode };
|
|
115
|
+
recipe = (0, factory_1.createSendEmailMessageRecipe)({
|
|
116
|
+
mailData,
|
|
117
|
+
afterMedia: result,
|
|
118
|
+
project: { id: params.project.id }
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
try {
|
|
123
|
+
recipe = (0, factory_1.createSendEmailMessageRecipe)({
|
|
124
|
+
mailData,
|
|
125
|
+
project: { id: params.project.id }
|
|
126
|
+
});
|
|
127
|
+
yield repos.action.giveUp({ typeOf: action.typeOf, id: action.id, error, recipe });
|
|
128
|
+
}
|
|
129
|
+
catch (__) {
|
|
130
|
+
// 失敗したら仕方ない
|
|
131
|
+
}
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
yield repos.action.completeWithVoid({ typeOf: action.typeOf, id: action.id, result: result, recipe });
|
|
135
|
+
});
|
|
136
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as factory from '../../factory';
|
|
2
|
+
import type { ActionRepo } from '../../repo/action';
|
|
3
|
+
import type { PotentialActionRepo } from '../../repo/potentialAction';
|
|
4
|
+
import type { SettingRepo } from '../../repo/setting';
|
|
5
|
+
declare function triggerWebhook(params: factory.task.IData<factory.taskName.TriggerWebhook> & {
|
|
6
|
+
project: {
|
|
7
|
+
id: string;
|
|
8
|
+
};
|
|
9
|
+
}): (repos: {
|
|
10
|
+
action: ActionRepo;
|
|
11
|
+
potentialAction: PotentialActionRepo;
|
|
12
|
+
setting: SettingRepo;
|
|
13
|
+
}) => Promise<void>;
|
|
14
|
+
export { triggerWebhook };
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.triggerWebhook = triggerWebhook;
|
|
13
|
+
const crypto = require("crypto");
|
|
14
|
+
const http_status_1 = require("http-status");
|
|
15
|
+
const factory = require("../../factory");
|
|
16
|
+
const USERNAME_ARGUMENT_REQUIRED_MESSAGE = 'Missing required key \'Username\' in params';
|
|
17
|
+
function triggerWebhook(params) {
|
|
18
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
const setting = yield repos.setting.findOne({ project: { id: { $eq: '*' } } }, ['triggerWebhook']);
|
|
21
|
+
const retryCountMax = (_a = setting === null || setting === void 0 ? void 0 : setting.triggerWebhook) === null || _a === void 0 ? void 0 : _a.retryCountMax;
|
|
22
|
+
const retryIntervalInMS = (_b = setting === null || setting === void 0 ? void 0 : setting.triggerWebhook) === null || _b === void 0 ? void 0 : _b.retryIntervalInMS;
|
|
23
|
+
if (typeof retryCountMax !== 'number') {
|
|
24
|
+
throw new factory.errors.NotFound('setting.triggerWebhook.retryCountMax');
|
|
25
|
+
}
|
|
26
|
+
if (typeof retryIntervalInMS !== 'number') {
|
|
27
|
+
throw new factory.errors.NotFound('setting.triggerWebhook.retryIntervalInMS');
|
|
28
|
+
}
|
|
29
|
+
// retryableにする(2023-05-12~)
|
|
30
|
+
let retry = true;
|
|
31
|
+
let numberOfTry = 0;
|
|
32
|
+
while (numberOfTry >= 0) {
|
|
33
|
+
try {
|
|
34
|
+
numberOfTry += 1;
|
|
35
|
+
if (numberOfTry > retryCountMax) {
|
|
36
|
+
retry = false;
|
|
37
|
+
}
|
|
38
|
+
// retryInterval
|
|
39
|
+
if (numberOfTry > 1) {
|
|
40
|
+
yield sleep(retryIntervalInMS * (numberOfTry - 1));
|
|
41
|
+
}
|
|
42
|
+
yield processInformAction(params, setting)(repos);
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (retry) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function sleep(waitTime) {
|
|
57
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
setTimeout(() => {
|
|
60
|
+
resolve();
|
|
61
|
+
}, waitTime);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function createInformActionAttributes(params) {
|
|
66
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
var _a, _b;
|
|
68
|
+
const { about, object, purpose, recipient, project, id, typeOf } = params;
|
|
69
|
+
// redefine recipient(2025-02-15~)
|
|
70
|
+
let informRecipient;
|
|
71
|
+
// let informRecipient: factory.action.interact.inform.IRecipient | factory.action.interact.inform.IRecipientDeprecated = {
|
|
72
|
+
// ...recipient
|
|
73
|
+
// // url: target.urlTemplate // discontinue(2025-02-15~)
|
|
74
|
+
// };
|
|
75
|
+
if ((recipient === null || recipient === void 0 ? void 0 : recipient.typeOf) === factory.organizationType.Corporation && typeof recipient.id === 'string') {
|
|
76
|
+
informRecipient = {
|
|
77
|
+
id: recipient.id,
|
|
78
|
+
name: recipient.name,
|
|
79
|
+
typeOf: recipient.typeOf
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
else if ((recipient === null || recipient === void 0 ? void 0 : recipient.typeOf) === factory.creativeWorkType.WebApplication) {
|
|
83
|
+
informRecipient = {
|
|
84
|
+
name: recipient.name,
|
|
85
|
+
typeOf: recipient.typeOf
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
let target;
|
|
89
|
+
if (typeOf === factory.actionType.InformAction && typeof id === 'string' && id !== '') {
|
|
90
|
+
// find target from potentialAction(2025-02-06~)
|
|
91
|
+
const potentialInformAction = (yield repos.potentialAction.projectFields({
|
|
92
|
+
limit: 1,
|
|
93
|
+
page: 1,
|
|
94
|
+
id: { $eq: id },
|
|
95
|
+
typeOf: { $eq: typeOf }
|
|
96
|
+
}, ['target', 'recipient'])).shift();
|
|
97
|
+
if (potentialInformAction === undefined) {
|
|
98
|
+
throw new factory.errors.NotFound(factory.actionType.InformAction);
|
|
99
|
+
}
|
|
100
|
+
if (typeof ((_a = potentialInformAction.recipient) === null || _a === void 0 ? void 0 : _a.name) === 'string') {
|
|
101
|
+
informRecipient = { name: potentialInformAction.recipient.name, typeOf: potentialInformAction.recipient.typeOf };
|
|
102
|
+
}
|
|
103
|
+
target = potentialInformAction.target;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
if (((_b = params.target) === null || _b === void 0 ? void 0 : _b.typeOf) === 'EntryPoint') {
|
|
107
|
+
target = params.target;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (informRecipient === undefined) {
|
|
111
|
+
throw new factory.errors.ArgumentNull('recipient');
|
|
112
|
+
}
|
|
113
|
+
if (target === undefined) {
|
|
114
|
+
throw new factory.errors.ArgumentNull('target');
|
|
115
|
+
}
|
|
116
|
+
return Object.assign(Object.assign(Object.assign({ agent: { id: project.id, typeOf: factory.organizationType.Project }, object, project: { id: project.id, typeOf: factory.organizationType.Project }, recipient: informRecipient, typeOf: factory.actionType.InformAction }, (typeof (purpose === null || purpose === void 0 ? void 0 : purpose.typeOf) === 'string') ? { purpose } : undefined), (typeof (about === null || about === void 0 ? void 0 : about.typeOf) === 'string') ? { about } : undefined), (typeof (target === null || target === void 0 ? void 0 : target.typeOf) === 'string') ? { target } : undefined // add(2025-02-06~)
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function signRequest(params) {
|
|
121
|
+
const { requestBody, timestamp, secretKey } = params;
|
|
122
|
+
const payload = `${requestBody}${timestamp.toString()}`;
|
|
123
|
+
return crypto.createHmac('sha256', secretKey)
|
|
124
|
+
.update(payload)
|
|
125
|
+
.digest('hex');
|
|
126
|
+
}
|
|
127
|
+
// tslint:disable-next-line:max-func-body-length
|
|
128
|
+
function processInformAction(params, options) {
|
|
129
|
+
// tslint:disable-next-line:cyclomatic-complexity
|
|
130
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
131
|
+
var _a, _b, _c, _d, _e, _f;
|
|
132
|
+
const timeout = (_a = options === null || options === void 0 ? void 0 : options.triggerWebhook) === null || _a === void 0 ? void 0 : _a.timeout;
|
|
133
|
+
const useFetchAPI = ((_b = options === null || options === void 0 ? void 0 : options.triggerWebhook) === null || _b === void 0 ? void 0 : _b.useFetchAPI) === true;
|
|
134
|
+
const secretKey = (_c = options === null || options === void 0 ? void 0 : options.triggerWebhook) === null || _c === void 0 ? void 0 : _c.secretKey;
|
|
135
|
+
const headerIdentifier = (_d = options === null || options === void 0 ? void 0 : options.triggerWebhook) === null || _d === void 0 ? void 0 : _d.headerIdentifier;
|
|
136
|
+
const { identifier } = params;
|
|
137
|
+
const informActionAttributes = yield createInformActionAttributes(params)(repos);
|
|
138
|
+
const action = yield repos.action.start(informActionAttributes);
|
|
139
|
+
let result = {};
|
|
140
|
+
try {
|
|
141
|
+
const urlTemplate = (_e = informActionAttributes.target) === null || _e === void 0 ? void 0 : _e.urlTemplate;
|
|
142
|
+
if (typeof urlTemplate === 'string') {
|
|
143
|
+
const requestBody = JSON.stringify(Object.assign({ data: informActionAttributes.object, id: action.id }, (typeof identifier === 'string' && identifier !== '')
|
|
144
|
+
? { identifier }
|
|
145
|
+
: undefined));
|
|
146
|
+
const timestamp = action.startDate.valueOf();
|
|
147
|
+
// sign request(2024-10-28~)
|
|
148
|
+
let signature;
|
|
149
|
+
if (typeof secretKey === 'string' && secretKey !== ''
|
|
150
|
+
&& typeof headerIdentifier === 'string' && headerIdentifier !== '') {
|
|
151
|
+
signature = signRequest({ requestBody, timestamp, secretKey });
|
|
152
|
+
}
|
|
153
|
+
if (useFetchAPI) {
|
|
154
|
+
try {
|
|
155
|
+
const headers = new Headers({ 'Content-Type': 'application/json' });
|
|
156
|
+
if (typeof headerIdentifier === 'string' && headerIdentifier !== '') {
|
|
157
|
+
headers.append(`X-${headerIdentifier}-Webhook-Timestamp`, String(timestamp));
|
|
158
|
+
if (typeof signature === 'string') {
|
|
159
|
+
headers.append(`X-${headerIdentifier}-Webhook-Signature`, signature);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const res = yield fetch(urlTemplate, Object.assign({ method: 'POST', headers, body: requestBody }, (typeof timeout === 'number')
|
|
163
|
+
? { signal: AbortSignal.timeout(timeout) }
|
|
164
|
+
: undefined));
|
|
165
|
+
let body;
|
|
166
|
+
try {
|
|
167
|
+
body = yield res.text();
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
// no op
|
|
171
|
+
}
|
|
172
|
+
switch (res.status) {
|
|
173
|
+
case http_status_1.OK:
|
|
174
|
+
case http_status_1.CREATED:
|
|
175
|
+
case http_status_1.ACCEPTED:
|
|
176
|
+
case http_status_1.NO_CONTENT:
|
|
177
|
+
result = {
|
|
178
|
+
statusCode: res.status,
|
|
179
|
+
useFetchAPI
|
|
180
|
+
};
|
|
181
|
+
break;
|
|
182
|
+
default:
|
|
183
|
+
throw new factory.errors.Internal(`statusCode: ${res.status} body: ${body}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
throw err;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
throw new factory.errors.NotImplemented('only useFetchAPI implemented');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
let throwsError = true;
|
|
197
|
+
// プロジェクト固有の特別対応
|
|
198
|
+
if (error.statusCode === http_status_1.INTERNAL_SERVER_ERROR && ((_f = error.body) === null || _f === void 0 ? void 0 : _f.message) === USERNAME_ARGUMENT_REQUIRED_MESSAGE) {
|
|
199
|
+
throwsError = false;
|
|
200
|
+
}
|
|
201
|
+
if (throwsError) {
|
|
202
|
+
try {
|
|
203
|
+
yield repos.action.giveUp({ typeOf: action.typeOf, id: action.id, error });
|
|
204
|
+
}
|
|
205
|
+
catch (__) {
|
|
206
|
+
// 失敗したら仕方ない
|
|
207
|
+
}
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
yield repos.action.completeWithVoid({ typeOf: action.typeOf, id: action.id, result: result });
|
|
212
|
+
});
|
|
213
|
+
}
|
|
@@ -1,42 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import type { MessageRepo } from '../repo/message';
|
|
5
|
-
import type { PotentialActionRepo } from '../repo/potentialAction';
|
|
6
|
-
import type { ProjectRepo } from '../repo/project';
|
|
7
|
-
import type { SettingRepo } from '../repo/setting';
|
|
8
|
-
/**
|
|
9
|
-
* Eメールメッセージを送信する
|
|
10
|
-
* https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html
|
|
11
|
-
*/
|
|
12
|
-
declare function sendEmailMessage(params: factory.task.sendEmailMessage.IActionAttributes & {
|
|
13
|
-
sameAs?: {
|
|
14
|
-
id: string;
|
|
15
|
-
};
|
|
16
|
-
}): (repos: {
|
|
17
|
-
action: ActionRepo;
|
|
18
|
-
message: MessageRepo;
|
|
19
|
-
project: ProjectRepo;
|
|
20
|
-
}, credentials: {
|
|
21
|
-
sendGrid: SendGridCredentials;
|
|
22
|
-
}) => Promise<void>;
|
|
23
|
-
declare function notifyByEmail(params: {
|
|
24
|
-
subject: string;
|
|
25
|
-
content: string;
|
|
26
|
-
logLevel: LineNotifyLogLevel;
|
|
27
|
-
}): (__: {}, credentials: {
|
|
28
|
-
sendGrid: SendGridCredentials;
|
|
29
|
-
}) => Promise<{
|
|
30
|
-
result: import("@chevre/factory/lib/action/transfer/send/message/email").IResult;
|
|
31
|
-
}>;
|
|
32
|
-
type LineNotifyLogLevel = 'log' | 'error' | 'info';
|
|
33
|
-
declare function triggerWebhook(params: factory.task.IData<factory.taskName.TriggerWebhook> & {
|
|
34
|
-
project: {
|
|
35
|
-
id: string;
|
|
36
|
-
};
|
|
37
|
-
}): (repos: {
|
|
38
|
-
action: ActionRepo;
|
|
39
|
-
potentialAction: PotentialActionRepo;
|
|
40
|
-
setting: SettingRepo;
|
|
41
|
-
}) => Promise<void>;
|
|
1
|
+
import { notifyByEmail } from './notification/notifyByEmail';
|
|
2
|
+
import { sendEmailMessage } from './notification/sendEmailMessage';
|
|
3
|
+
import { triggerWebhook } from './notification/triggerWebhook';
|
|
42
4
|
export { notifyByEmail, sendEmailMessage, triggerWebhook };
|
|
@@ -1,515 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.notifyByEmail =
|
|
13
|
-
|
|
14
|
-
exports.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// import * as sgMail from '@sendgrid/mail';
|
|
20
|
-
const crypto = require("crypto");
|
|
21
|
-
const http_status_1 = require("http-status");
|
|
22
|
-
const util = require("util");
|
|
23
|
-
const factory = require("../factory");
|
|
24
|
-
const factory_1 = require("./notification/factory");
|
|
25
|
-
// type ILineNotifyOperation<T> = (
|
|
26
|
-
// repos: undefined,
|
|
27
|
-
// credentials: {
|
|
28
|
-
// lineNotify: LINENotifyCredentials;
|
|
29
|
-
// }
|
|
30
|
-
// ) => Promise<T>;
|
|
31
|
-
function createSendEmailMessageActionAttributes(params) {
|
|
32
|
-
var _a;
|
|
33
|
-
const { agent, object, project, purpose, recipient, typeOf } = params;
|
|
34
|
-
return Object.assign({ agent, object, project, purpose, recipient, typeOf }, (typeof ((_a = params.sameAs) === null || _a === void 0 ? void 0 : _a.id) === 'string') ? { sameAs: { id: params.sameAs.id, typeOf: 'Task' } } : undefined);
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Eメールメッセージを送信する
|
|
38
|
-
* https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html
|
|
39
|
-
*/
|
|
40
|
-
function sendEmailMessage(params) {
|
|
41
|
-
// tslint:disable-next-line:max-func-body-length
|
|
42
|
-
return (repos, credentials) => __awaiter(this, void 0, void 0, function* () {
|
|
43
|
-
var _a, _b, _c, _d, _e;
|
|
44
|
-
const project = yield repos.project.findById({
|
|
45
|
-
id: params.project.id,
|
|
46
|
-
inclusion: ['settings']
|
|
47
|
-
});
|
|
48
|
-
// add recipe(2025-03-12~)
|
|
49
|
-
let recipe;
|
|
50
|
-
let msg;
|
|
51
|
-
const startingAction = createSendEmailMessageActionAttributes(params);
|
|
52
|
-
const action = yield repos.action.start(startingAction);
|
|
53
|
-
let result = {};
|
|
54
|
-
try {
|
|
55
|
-
let apiKey = credentials.sendGrid.apiKey;
|
|
56
|
-
// プロジェクト固有のSendGrid設定があれば、そちらを使用
|
|
57
|
-
if (typeof ((_a = project.settings) === null || _a === void 0 ? void 0 : _a.sendgridApiKey) === 'string' && project.settings.sendgridApiKey.length > 0) {
|
|
58
|
-
apiKey = project.settings.sendgridApiKey;
|
|
59
|
-
}
|
|
60
|
-
if (typeof apiKey !== 'string') {
|
|
61
|
-
throw new factory.errors.Internal('API Key not found');
|
|
62
|
-
}
|
|
63
|
-
// sgMail.setApiKey(apiKey); // fix(2025-03-14~)
|
|
64
|
-
let emailMessage;
|
|
65
|
-
if (typeof params.object.text === 'string') {
|
|
66
|
-
emailMessage = params.object;
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
// メッセージリポジトリに対応(2024-04-29~)
|
|
70
|
-
emailMessage = yield repos.message.findByIdentifier({
|
|
71
|
-
identifier: params.object.identifier,
|
|
72
|
-
project: { id: project.id }
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
const emailMessageFrom = {
|
|
76
|
-
name: emailMessage.sender.name,
|
|
77
|
-
email: emailMessage.sender.email
|
|
78
|
-
};
|
|
79
|
-
// プロジェクト設定対応(2023-08-21~)
|
|
80
|
-
const senderEmailByProjectSettings = (_d = (_c = (_b = project.settings) === null || _b === void 0 ? void 0 : _b.sendEmailMessage) === null || _c === void 0 ? void 0 : _c.sender) === null || _d === void 0 ? void 0 : _d.email;
|
|
81
|
-
if (typeof senderEmailByProjectSettings === 'string' && senderEmailByProjectSettings.length > 0) {
|
|
82
|
-
emailMessageFrom.email = senderEmailByProjectSettings;
|
|
83
|
-
}
|
|
84
|
-
let subject;
|
|
85
|
-
// 互換性維持対応として、String型に対応
|
|
86
|
-
if (typeof emailMessage.about === 'string') {
|
|
87
|
-
if (String(emailMessage.about).length > 0) {
|
|
88
|
-
subject = String(emailMessage.about);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
else if (typeof ((_e = emailMessage.about) === null || _e === void 0 ? void 0 : _e.name) === 'string') {
|
|
92
|
-
if (emailMessage.about.name.length > 0) {
|
|
93
|
-
subject = emailMessage.about.name;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
const emailDatas = (Array.isArray(emailMessage.toRecipient))
|
|
97
|
-
? emailMessage.toRecipient.map((toRecipient) => {
|
|
98
|
-
return {
|
|
99
|
-
name: toRecipient.name,
|
|
100
|
-
email: toRecipient.email
|
|
101
|
-
};
|
|
102
|
-
})
|
|
103
|
-
// Arrayでない時期への互換性維持対応
|
|
104
|
-
: [{
|
|
105
|
-
name: emailMessage.toRecipient.name,
|
|
106
|
-
email: emailMessage.toRecipient.email
|
|
107
|
-
}];
|
|
108
|
-
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), {
|
|
109
|
-
// html: '<strong>and easy to do anywhere, even with Node.js</strong>',
|
|
110
|
-
// categories: ['Transactional', 'My category'],
|
|
111
|
-
// 送信予定を追加することもできるが、タスクの実行予定日時でコントロールする想定
|
|
112
|
-
// sendAt: moment(email.send_at).unix(),
|
|
113
|
-
// 追跡用に通知IDをカスタムフィールドとしてセットする
|
|
114
|
-
customArgs: {
|
|
115
|
-
emailMessage: emailMessage.identifier,
|
|
116
|
-
actionId: action.id,
|
|
117
|
-
projectId: project.id
|
|
118
|
-
} });
|
|
119
|
-
// reimplement using Client(2025-03-14~)
|
|
120
|
-
// const response = await sgMail.sendMultiple(msg);
|
|
121
|
-
const sgClient = new client_1.Client();
|
|
122
|
-
sgClient.setApiKey(apiKey);
|
|
123
|
-
// const response = await sgMail.sendMultiple(msg);
|
|
124
|
-
const response = yield sgClient.request({
|
|
125
|
-
body: {
|
|
126
|
-
content: [{ type: 'text/plain', value: msg.text }],
|
|
127
|
-
from: msg.from,
|
|
128
|
-
personalizations: [{ to: msg.to }],
|
|
129
|
-
subject: msg.subject,
|
|
130
|
-
custom_args: msg.customArgs
|
|
131
|
-
},
|
|
132
|
-
method: 'POST',
|
|
133
|
-
url: '/v3/mail/send'
|
|
134
|
-
});
|
|
135
|
-
// check the response.
|
|
136
|
-
if (response[0].statusCode !== http_status_1.ACCEPTED) {
|
|
137
|
-
throw new factory.errors.Internal(`sendgrid request not accepted. response is ${util.inspect(response)}`);
|
|
138
|
-
}
|
|
139
|
-
const { statusCode } = response[0];
|
|
140
|
-
result = { statusCode };
|
|
141
|
-
recipe = (0, factory_1.createSendEmailMessageRecipe)({
|
|
142
|
-
mailData: msg,
|
|
143
|
-
afterMedia: result,
|
|
144
|
-
project: { id: params.project.id }
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
catch (error) {
|
|
148
|
-
try {
|
|
149
|
-
recipe = (0, factory_1.createSendEmailMessageRecipe)(Object.assign({ project: { id: params.project.id } }, (msg !== undefined) ? { mailData: msg } : undefined));
|
|
150
|
-
yield repos.action.giveUp({ typeOf: action.typeOf, id: action.id, error, recipe });
|
|
151
|
-
}
|
|
152
|
-
catch (__) {
|
|
153
|
-
// 失敗したら仕方ない
|
|
154
|
-
}
|
|
155
|
-
throw error;
|
|
156
|
-
}
|
|
157
|
-
yield repos.action.completeWithVoid({ typeOf: action.typeOf, id: action.id, result: result, recipe });
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
// tslint:disable-next-line:max-func-body-length
|
|
161
|
-
function notifyByEmail(params) {
|
|
162
|
-
// tslint:disable-next-line:cyclomatic-complexity max-func-body-length
|
|
163
|
-
return (__, credentials) => __awaiter(this, void 0, void 0, function* () {
|
|
164
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
165
|
-
const { logLevel } = params;
|
|
166
|
-
const shortSubject = params.subject;
|
|
167
|
-
const message = util.format('\n%s\n%s\n%s\n%s\n%s\n\n%s', `[${logLevel}] ${shortSubject}`, `now:${(new Date()).toISOString()}`, `pid:${process.pid}`, `GAE_APPLICATION:${process.env.GAE_APPLICATION}`,
|
|
168
|
-
// `GAE_INSTANCE:${process.env.GAE_INSTANCE}`,
|
|
169
|
-
`GAE_SERVICE:${process.env.GAE_SERVICE}`, params.content);
|
|
170
|
-
let result = {};
|
|
171
|
-
try {
|
|
172
|
-
const apiKey = credentials.sendGrid.apiKey;
|
|
173
|
-
if (typeof apiKey !== 'string') {
|
|
174
|
-
throw new factory.errors.Internal('API Key not found');
|
|
175
|
-
}
|
|
176
|
-
const senderName = (_b = (_a = credentials.sendGrid.alert) === null || _a === void 0 ? void 0 : _a.sender) === null || _b === void 0 ? void 0 : _b.name;
|
|
177
|
-
const senderEmail = (_d = (_c = credentials.sendGrid.alert) === null || _c === void 0 ? void 0 : _c.sender) === null || _d === void 0 ? void 0 : _d.email;
|
|
178
|
-
const toRecipientEmail = (Array.isArray((_e = credentials.sendGrid.alert) === null || _e === void 0 ? void 0 : _e.toRecipient))
|
|
179
|
-
? (_g = (_f = credentials.sendGrid.alert) === null || _f === void 0 ? void 0 : _f.toRecipient.at(0)) === null || _g === void 0 ? void 0 : _g.email
|
|
180
|
-
: undefined;
|
|
181
|
-
if (typeof senderName !== 'string') {
|
|
182
|
-
throw new factory.errors.Internal('senderName not found');
|
|
183
|
-
}
|
|
184
|
-
if (typeof senderEmail !== 'string') {
|
|
185
|
-
throw new factory.errors.Internal('senderEmail not found');
|
|
186
|
-
}
|
|
187
|
-
if (typeof toRecipientEmail !== 'string') {
|
|
188
|
-
throw new factory.errors.Internal('toRecipientEmail not found');
|
|
189
|
-
}
|
|
190
|
-
const emailMessageFrom = {
|
|
191
|
-
name: senderName,
|
|
192
|
-
email: senderEmail
|
|
193
|
-
};
|
|
194
|
-
const subject = `[${logLevel}] ${shortSubject}`;
|
|
195
|
-
const emailDatas = [{
|
|
196
|
-
name: 'developers',
|
|
197
|
-
email: toRecipientEmail
|
|
198
|
-
}];
|
|
199
|
-
const sgClient = new client_1.Client();
|
|
200
|
-
sgClient.setApiKey(apiKey);
|
|
201
|
-
// const response = await sgMail.sendMultiple(msg);
|
|
202
|
-
const response = yield sgClient.request({
|
|
203
|
-
body: {
|
|
204
|
-
content: [{ type: 'text/plain', value: message }],
|
|
205
|
-
from: emailMessageFrom,
|
|
206
|
-
personalizations: [{ to: emailDatas }],
|
|
207
|
-
subject,
|
|
208
|
-
custom_args: {
|
|
209
|
-
emailMessage: subject
|
|
210
|
-
// actionId: action.id,
|
|
211
|
-
// projectId: project.id
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
method: 'POST',
|
|
215
|
-
url: '/v3/mail/send'
|
|
216
|
-
});
|
|
217
|
-
// check the response.
|
|
218
|
-
if (response[0].statusCode !== http_status_1.ACCEPTED) {
|
|
219
|
-
throw new factory.errors.Internal(`sendgrid request not accepted. response is ${util.inspect(response)}`);
|
|
220
|
-
}
|
|
221
|
-
const { statusCode } = response[0];
|
|
222
|
-
// const statusMessage = response[1];
|
|
223
|
-
result = { statusCode };
|
|
224
|
-
}
|
|
225
|
-
catch (error) {
|
|
226
|
-
throw error;
|
|
227
|
-
}
|
|
228
|
-
return { result };
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
// const MAX_LINE_NOTIFY_SUBJECT_LENGTH = 100;
|
|
232
|
-
// function lineNotify(
|
|
233
|
-
// { subject, content, imageThumbnail, imageFullsize, logLevel }: {
|
|
234
|
-
// subject: string;
|
|
235
|
-
// content: string;
|
|
236
|
-
// imageThumbnail?: string;
|
|
237
|
-
// imageFullsize?: string;
|
|
238
|
-
// logLevel: LineNotifyLogLevel;
|
|
239
|
-
// }
|
|
240
|
-
// ): ILineNotifyOperation<void> {
|
|
241
|
-
// return async (
|
|
242
|
-
// __: undefined,
|
|
243
|
-
// credentials: {
|
|
244
|
-
// lineNotify: LINENotifyCredentials;
|
|
245
|
-
// }
|
|
246
|
-
// ) => {
|
|
247
|
-
// const timeout = 10000;
|
|
248
|
-
// const LINE_NOTIFY_URL = credentials.lineNotify.url;
|
|
249
|
-
// if (typeof LINE_NOTIFY_URL !== 'string') {
|
|
250
|
-
// throw new factory.errors.Internal('Environment variable LINE_NOTIFY_URL not set');
|
|
251
|
-
// }
|
|
252
|
-
// let accessToken: string | undefined;
|
|
253
|
-
// switch (logLevel) {
|
|
254
|
-
// case 'error':
|
|
255
|
-
// accessToken = credentials.lineNotify.accessTokenAlert;
|
|
256
|
-
// break;
|
|
257
|
-
// case 'info':
|
|
258
|
-
// accessToken = credentials.lineNotify.accessTokenInfo;
|
|
259
|
-
// break;
|
|
260
|
-
// default:
|
|
261
|
-
// accessToken = credentials.lineNotify.accessToken;
|
|
262
|
-
// }
|
|
263
|
-
// if (typeof accessToken !== 'string') {
|
|
264
|
-
// throw new factory.errors.Internal('credentials.lineNotify.accessToken not set');
|
|
265
|
-
// }
|
|
266
|
-
// const shortSubject = (subject.length > MAX_LINE_NOTIFY_SUBJECT_LENGTH)
|
|
267
|
-
// ? `${subject.slice(0, MAX_LINE_NOTIFY_SUBJECT_LENGTH)}...`
|
|
268
|
-
// : subject;
|
|
269
|
-
// const message: string = util.format(
|
|
270
|
-
// '\n%s\n%s\n%s\n%s\n%s\n\n%s',
|
|
271
|
-
// `[${logLevel}] ${shortSubject}`,
|
|
272
|
-
// `now:${(new Date()).toISOString()}`,
|
|
273
|
-
// `pid:${process.pid}`,
|
|
274
|
-
// `GAE_APPLICATION:${process.env.GAE_APPLICATION}`,
|
|
275
|
-
// // `GAE_INSTANCE:${process.env.GAE_INSTANCE}`,
|
|
276
|
-
// `GAE_SERVICE:${process.env.GAE_SERVICE}`,
|
|
277
|
-
// content
|
|
278
|
-
// );
|
|
279
|
-
// try {
|
|
280
|
-
// const form = new FormData();
|
|
281
|
-
// form.set('message', message);
|
|
282
|
-
// if (typeof imageThumbnail === 'string') {
|
|
283
|
-
// form.set('imageThumbnail', imageThumbnail);
|
|
284
|
-
// }
|
|
285
|
-
// if (typeof imageFullsize === 'string') {
|
|
286
|
-
// form.set('imageFullsize', imageFullsize);
|
|
287
|
-
// }
|
|
288
|
-
// const res = await fetch(
|
|
289
|
-
// LINE_NOTIFY_URL,
|
|
290
|
-
// {
|
|
291
|
-
// method: 'POST',
|
|
292
|
-
// headers: {
|
|
293
|
-
// Authorization: `Bearer ${accessToken}`
|
|
294
|
-
// },
|
|
295
|
-
// body: form,
|
|
296
|
-
// ...(typeof timeout === 'number')
|
|
297
|
-
// ? { signal: AbortSignal.timeout(timeout) }
|
|
298
|
-
// : undefined
|
|
299
|
-
// }
|
|
300
|
-
// );
|
|
301
|
-
// let body: any;
|
|
302
|
-
// try {
|
|
303
|
-
// body = await res.json();
|
|
304
|
-
// } catch (error) {
|
|
305
|
-
// // no op
|
|
306
|
-
// }
|
|
307
|
-
// switch (res.status) {
|
|
308
|
-
// case OK:
|
|
309
|
-
// break;
|
|
310
|
-
// default:
|
|
311
|
-
// throw new factory.errors.Internal(`${res.status} ${body?.message}`);
|
|
312
|
-
// }
|
|
313
|
-
// } catch (err) {
|
|
314
|
-
// throw err;
|
|
315
|
-
// }
|
|
316
|
-
// };
|
|
317
|
-
// }
|
|
318
|
-
const USERNAME_ARGUMENT_REQUIRED_MESSAGE = 'Missing required key \'Username\' in params';
|
|
319
|
-
function triggerWebhook(params) {
|
|
320
|
-
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
321
|
-
var _a, _b;
|
|
322
|
-
const setting = yield repos.setting.findOne({ project: { id: { $eq: '*' } } }, ['triggerWebhook']);
|
|
323
|
-
const retryCountMax = (_a = setting === null || setting === void 0 ? void 0 : setting.triggerWebhook) === null || _a === void 0 ? void 0 : _a.retryCountMax;
|
|
324
|
-
const retryIntervalInMS = (_b = setting === null || setting === void 0 ? void 0 : setting.triggerWebhook) === null || _b === void 0 ? void 0 : _b.retryIntervalInMS;
|
|
325
|
-
if (typeof retryCountMax !== 'number') {
|
|
326
|
-
throw new factory.errors.NotFound('setting.triggerWebhook.retryCountMax');
|
|
327
|
-
}
|
|
328
|
-
if (typeof retryIntervalInMS !== 'number') {
|
|
329
|
-
throw new factory.errors.NotFound('setting.triggerWebhook.retryIntervalInMS');
|
|
330
|
-
}
|
|
331
|
-
// retryableにする(2023-05-12~)
|
|
332
|
-
let retry = true;
|
|
333
|
-
let numberOfTry = 0;
|
|
334
|
-
while (numberOfTry >= 0) {
|
|
335
|
-
try {
|
|
336
|
-
numberOfTry += 1;
|
|
337
|
-
if (numberOfTry > retryCountMax) {
|
|
338
|
-
retry = false;
|
|
339
|
-
}
|
|
340
|
-
// retryInterval
|
|
341
|
-
if (numberOfTry > 1) {
|
|
342
|
-
yield sleep(retryIntervalInMS * (numberOfTry - 1));
|
|
343
|
-
}
|
|
344
|
-
yield processInformAction(params, setting)(repos);
|
|
345
|
-
break;
|
|
346
|
-
}
|
|
347
|
-
catch (error) {
|
|
348
|
-
if (retry) {
|
|
349
|
-
continue;
|
|
350
|
-
}
|
|
351
|
-
else {
|
|
352
|
-
throw error;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
function sleep(waitTime) {
|
|
359
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
360
|
-
return new Promise((resolve) => {
|
|
361
|
-
setTimeout(() => {
|
|
362
|
-
resolve();
|
|
363
|
-
}, waitTime);
|
|
364
|
-
});
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
function createInformActionAttributes(params) {
|
|
368
|
-
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
369
|
-
var _a, _b;
|
|
370
|
-
const { about, object, purpose, recipient, project, id, typeOf } = params;
|
|
371
|
-
// redefine recipient(2025-02-15~)
|
|
372
|
-
let informRecipient;
|
|
373
|
-
// let informRecipient: factory.action.interact.inform.IRecipient | factory.action.interact.inform.IRecipientDeprecated = {
|
|
374
|
-
// ...recipient
|
|
375
|
-
// // url: target.urlTemplate // discontinue(2025-02-15~)
|
|
376
|
-
// };
|
|
377
|
-
if ((recipient === null || recipient === void 0 ? void 0 : recipient.typeOf) === factory.organizationType.Corporation && typeof recipient.id === 'string') {
|
|
378
|
-
informRecipient = {
|
|
379
|
-
id: recipient.id,
|
|
380
|
-
name: recipient.name,
|
|
381
|
-
typeOf: recipient.typeOf
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
else if ((recipient === null || recipient === void 0 ? void 0 : recipient.typeOf) === factory.creativeWorkType.WebApplication) {
|
|
385
|
-
informRecipient = {
|
|
386
|
-
name: recipient.name,
|
|
387
|
-
typeOf: recipient.typeOf
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
let target;
|
|
391
|
-
if (typeOf === factory.actionType.InformAction && typeof id === 'string' && id !== '') {
|
|
392
|
-
// find target from potentialAction(2025-02-06~)
|
|
393
|
-
const potentialInformAction = (yield repos.potentialAction.projectFields({
|
|
394
|
-
limit: 1,
|
|
395
|
-
page: 1,
|
|
396
|
-
id: { $eq: id },
|
|
397
|
-
typeOf: { $eq: typeOf }
|
|
398
|
-
}, ['target', 'recipient'])).shift();
|
|
399
|
-
if (potentialInformAction === undefined) {
|
|
400
|
-
throw new factory.errors.NotFound(factory.actionType.InformAction);
|
|
401
|
-
}
|
|
402
|
-
if (typeof ((_a = potentialInformAction.recipient) === null || _a === void 0 ? void 0 : _a.name) === 'string') {
|
|
403
|
-
informRecipient = { name: potentialInformAction.recipient.name, typeOf: potentialInformAction.recipient.typeOf };
|
|
404
|
-
}
|
|
405
|
-
target = potentialInformAction.target;
|
|
406
|
-
}
|
|
407
|
-
else {
|
|
408
|
-
if (((_b = params.target) === null || _b === void 0 ? void 0 : _b.typeOf) === 'EntryPoint') {
|
|
409
|
-
target = params.target;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
if (informRecipient === undefined) {
|
|
413
|
-
throw new factory.errors.ArgumentNull('recipient');
|
|
414
|
-
}
|
|
415
|
-
if (target === undefined) {
|
|
416
|
-
throw new factory.errors.ArgumentNull('target');
|
|
417
|
-
}
|
|
418
|
-
return Object.assign(Object.assign(Object.assign({ agent: { id: project.id, typeOf: factory.organizationType.Project }, object, project: { id: project.id, typeOf: factory.organizationType.Project }, recipient: informRecipient, typeOf: factory.actionType.InformAction }, (typeof (purpose === null || purpose === void 0 ? void 0 : purpose.typeOf) === 'string') ? { purpose } : undefined), (typeof (about === null || about === void 0 ? void 0 : about.typeOf) === 'string') ? { about } : undefined), (typeof (target === null || target === void 0 ? void 0 : target.typeOf) === 'string') ? { target } : undefined // add(2025-02-06~)
|
|
419
|
-
);
|
|
420
|
-
});
|
|
421
|
-
}
|
|
422
|
-
function signRequest(params) {
|
|
423
|
-
const { requestBody, timestamp, secretKey } = params;
|
|
424
|
-
const payload = `${requestBody}${timestamp.toString()}`;
|
|
425
|
-
return crypto.createHmac('sha256', secretKey)
|
|
426
|
-
.update(payload)
|
|
427
|
-
.digest('hex');
|
|
428
|
-
}
|
|
429
|
-
// tslint:disable-next-line:max-func-body-length
|
|
430
|
-
function processInformAction(params, options) {
|
|
431
|
-
// tslint:disable-next-line:cyclomatic-complexity
|
|
432
|
-
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
433
|
-
var _a, _b, _c, _d, _e, _f;
|
|
434
|
-
const timeout = (_a = options === null || options === void 0 ? void 0 : options.triggerWebhook) === null || _a === void 0 ? void 0 : _a.timeout;
|
|
435
|
-
const useFetchAPI = ((_b = options === null || options === void 0 ? void 0 : options.triggerWebhook) === null || _b === void 0 ? void 0 : _b.useFetchAPI) === true;
|
|
436
|
-
const secretKey = (_c = options === null || options === void 0 ? void 0 : options.triggerWebhook) === null || _c === void 0 ? void 0 : _c.secretKey;
|
|
437
|
-
const headerIdentifier = (_d = options === null || options === void 0 ? void 0 : options.triggerWebhook) === null || _d === void 0 ? void 0 : _d.headerIdentifier;
|
|
438
|
-
const { identifier } = params;
|
|
439
|
-
const informActionAttributes = yield createInformActionAttributes(params)(repos);
|
|
440
|
-
const action = yield repos.action.start(informActionAttributes);
|
|
441
|
-
let result = {};
|
|
442
|
-
try {
|
|
443
|
-
const urlTemplate = (_e = informActionAttributes.target) === null || _e === void 0 ? void 0 : _e.urlTemplate;
|
|
444
|
-
if (typeof urlTemplate === 'string') {
|
|
445
|
-
const requestBody = JSON.stringify(Object.assign({ data: informActionAttributes.object, id: action.id }, (typeof identifier === 'string' && identifier !== '')
|
|
446
|
-
? { identifier }
|
|
447
|
-
: undefined));
|
|
448
|
-
const timestamp = action.startDate.valueOf();
|
|
449
|
-
// sign request(2024-10-28~)
|
|
450
|
-
let signature;
|
|
451
|
-
if (typeof secretKey === 'string' && secretKey !== ''
|
|
452
|
-
&& typeof headerIdentifier === 'string' && headerIdentifier !== '') {
|
|
453
|
-
signature = signRequest({ requestBody, timestamp, secretKey });
|
|
454
|
-
}
|
|
455
|
-
if (useFetchAPI) {
|
|
456
|
-
try {
|
|
457
|
-
const headers = new Headers({ 'Content-Type': 'application/json' });
|
|
458
|
-
if (typeof headerIdentifier === 'string' && headerIdentifier !== '') {
|
|
459
|
-
headers.append(`X-${headerIdentifier}-Webhook-Timestamp`, String(timestamp));
|
|
460
|
-
if (typeof signature === 'string') {
|
|
461
|
-
headers.append(`X-${headerIdentifier}-Webhook-Signature`, signature);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
const res = yield fetch(urlTemplate, Object.assign({ method: 'POST', headers, body: requestBody }, (typeof timeout === 'number')
|
|
465
|
-
? { signal: AbortSignal.timeout(timeout) }
|
|
466
|
-
: undefined));
|
|
467
|
-
let body;
|
|
468
|
-
try {
|
|
469
|
-
body = yield res.text();
|
|
470
|
-
}
|
|
471
|
-
catch (error) {
|
|
472
|
-
// no op
|
|
473
|
-
}
|
|
474
|
-
switch (res.status) {
|
|
475
|
-
case http_status_1.OK:
|
|
476
|
-
case http_status_1.CREATED:
|
|
477
|
-
case http_status_1.ACCEPTED:
|
|
478
|
-
case http_status_1.NO_CONTENT:
|
|
479
|
-
result = {
|
|
480
|
-
statusCode: res.status,
|
|
481
|
-
useFetchAPI
|
|
482
|
-
};
|
|
483
|
-
break;
|
|
484
|
-
default:
|
|
485
|
-
throw new factory.errors.Internal(`statusCode: ${res.status} body: ${body}`);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
catch (err) {
|
|
489
|
-
throw err;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
else {
|
|
493
|
-
throw new factory.errors.NotImplemented('only useFetchAPI implemented');
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
catch (error) {
|
|
498
|
-
let throwsError = true;
|
|
499
|
-
// プロジェクト固有の特別対応
|
|
500
|
-
if (error.statusCode === http_status_1.INTERNAL_SERVER_ERROR && ((_f = error.body) === null || _f === void 0 ? void 0 : _f.message) === USERNAME_ARGUMENT_REQUIRED_MESSAGE) {
|
|
501
|
-
throwsError = false;
|
|
502
|
-
}
|
|
503
|
-
if (throwsError) {
|
|
504
|
-
try {
|
|
505
|
-
yield repos.action.giveUp({ typeOf: action.typeOf, id: action.id, error });
|
|
506
|
-
}
|
|
507
|
-
catch (__) {
|
|
508
|
-
// 失敗したら仕方ない
|
|
509
|
-
}
|
|
510
|
-
throw error;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
yield repos.action.completeWithVoid({ typeOf: action.typeOf, id: action.id, result: result });
|
|
514
|
-
});
|
|
515
|
-
}
|
|
3
|
+
exports.triggerWebhook = exports.sendEmailMessage = exports.notifyByEmail = void 0;
|
|
4
|
+
const notifyByEmail_1 = require("./notification/notifyByEmail");
|
|
5
|
+
Object.defineProperty(exports, "notifyByEmail", { enumerable: true, get: function () { return notifyByEmail_1.notifyByEmail; } });
|
|
6
|
+
const sendEmailMessage_1 = require("./notification/sendEmailMessage");
|
|
7
|
+
Object.defineProperty(exports, "sendEmailMessage", { enumerable: true, get: function () { return sendEmailMessage_1.sendEmailMessage; } });
|
|
8
|
+
const triggerWebhook_1 = require("./notification/triggerWebhook");
|
|
9
|
+
Object.defineProperty(exports, "triggerWebhook", { enumerable: true, get: function () { return triggerWebhook_1.triggerWebhook; } });
|
package/package.json
CHANGED
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
"@motionpicture/coa-service": "9.6.0",
|
|
17
17
|
"@motionpicture/gmo-service": "5.3.0",
|
|
18
18
|
"@sendgrid/client": "8.1.4",
|
|
19
|
-
"@sendgrid/mail": "6.4.0",
|
|
20
19
|
"@surfrock/sdk": "1.4.0-alpha.1",
|
|
21
20
|
"cdigit": "2.6.7",
|
|
22
21
|
"debug": "^3.2.7",
|
|
@@ -34,6 +33,7 @@
|
|
|
34
33
|
"description": "Chevre Domain Library for Node.js",
|
|
35
34
|
"devDependencies": {
|
|
36
35
|
"@eslint/js": "9.16.0",
|
|
36
|
+
"@sendgrid/helpers": "8.0.0",
|
|
37
37
|
"@types/debug": "0.0.30",
|
|
38
38
|
"@types/google-libphonenumber": "^7.4.19",
|
|
39
39
|
"@types/http-status": "^0.2.30",
|
|
@@ -113,5 +113,5 @@
|
|
|
113
113
|
"postversion": "git push origin --tags",
|
|
114
114
|
"prepublishOnly": "npm run clean && npm run build && npm test && npm run doc"
|
|
115
115
|
},
|
|
116
|
-
"version": "22.9.0-alpha.
|
|
116
|
+
"version": "22.9.0-alpha.85"
|
|
117
117
|
}
|