@dereekb/firebase-server 13.11.18 → 13.12.0
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/index.cjs.js +218 -31
- package/index.esm.js +217 -34
- package/mailgun/package.json +9 -9
- package/mcp/index.cjs.default.js +1 -0
- package/mcp/index.cjs.js +3646 -0
- package/mcp/index.cjs.mjs +2 -0
- package/mcp/index.d.ts +1 -0
- package/mcp/index.esm.js +3609 -0
- package/mcp/package.json +33 -0
- package/mcp/src/index.d.ts +1 -0
- package/mcp/src/lib/controller/index.d.ts +2 -0
- package/mcp/src/lib/controller/mcp.controller.d.ts +19 -0
- package/mcp/src/lib/controller/mcp.wellknown.controller.d.ts +25 -0
- package/mcp/src/lib/index.d.ts +5 -0
- package/mcp/src/lib/mcp.config.d.ts +100 -0
- package/mcp/src/lib/mcp.module.d.ts +49 -0
- package/mcp/src/lib/service/index.d.ts +8 -0
- package/mcp/src/lib/service/mcp.manifest.d.ts +150 -0
- package/mcp/src/lib/service/mcp.response-formatter.d.ts +36 -0
- package/mcp/src/lib/service/mcp.server.factory.d.ts +124 -0
- package/mcp/src/lib/service/mcp.tool-generator.d.ts +235 -0
- package/mcp/src/lib/service/mcp.visibility.d.ts +99 -0
- package/mcp/src/lib/service/tools/mcp.tool.model-decode.d.ts +87 -0
- package/mcp/src/lib/service/tools/mcp.tool.model-get.d.ts +81 -0
- package/mcp/src/lib/service/tools/mcp.tool.model-info.d.ts +84 -0
- package/mcp/src/lib/service/tools/mcp.tool.whoami.d.ts +72 -0
- package/mcp/src/lib/transport/index.d.ts +1 -0
- package/mcp/src/lib/transport/streamable-http.transport.d.ts +21 -0
- package/model/index.cjs.js +639 -266
- package/model/index.esm.js +640 -270
- package/model/package.json +9 -9
- package/model/src/lib/storagefile/extension/compress.pdf.d.ts +29 -1
- package/model/src/lib/storagefile/index.d.ts +1 -0
- package/model/src/lib/storagefile/storagefile.action.server.d.ts +29 -2
- package/model/src/lib/storagefile/storagefile.mcp.d.ts +32 -0
- package/model/src/lib/storagefile/storagefile.module.d.ts +20 -3
- package/oidc/index.cjs.js +322 -147
- package/oidc/index.esm.js +321 -148
- package/oidc/package.json +10 -10
- package/oidc/src/lib/controller/oidc.wellknown.controller.d.ts +6 -15
- package/oidc/src/lib/middleware/oauth-auth.middleware.d.ts +22 -2
- package/oidc/src/lib/middleware/oauth-auth.module.d.ts +57 -0
- package/oidc/src/lib/oidc.config.d.ts +73 -0
- package/oidc/src/lib/oidc.module.d.ts +44 -2
- package/package.json +16 -10
- package/src/lib/auth/auth.service.d.ts +16 -1
- package/src/lib/auth/auth.service.error.util.d.ts +24 -5
- package/src/lib/env/env.config.d.ts +16 -0
- package/src/lib/env/env.service.d.ts +9 -0
- package/src/lib/nest/controller/model/model.api.get.service.d.ts +35 -1
- package/src/lib/nest/env/env.service.d.ts +1 -0
- package/src/lib/nest/model/api.details.d.ts +116 -5
- package/src/lib/nest/model/crud.assert.function.d.ts +1 -1
- package/src/lib/nest/model/index.d.ts +1 -0
- package/src/lib/nest/model/invoke.model.function.d.ts +89 -0
- package/test/package.json +11 -11
- package/twilio/LICENSE +21 -0
- package/twilio/index.cjs.default.js +1 -0
- package/twilio/index.cjs.js +404 -0
- package/twilio/index.cjs.mjs +2 -0
- package/twilio/index.d.ts +1 -0
- package/twilio/index.esm.js +398 -0
- package/twilio/package.json +25 -0
- package/twilio/src/index.d.ts +1 -0
- package/twilio/src/lib/index.d.ts +1 -0
- package/twilio/src/lib/notification.send.service.twilio.d.ts +148 -0
- package/zoho/package.json +9 -9
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import { mapObjectKeysToLowercase, asArray, multiValueMapBuilder, batch, runAsyncTasksForValues, pushArrayItemsIntoArray } from '@dereekb/util';
|
|
2
|
+
|
|
3
|
+
function _array_like_to_array(arr, len) {
|
|
4
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
5
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
6
|
+
return arr2;
|
|
7
|
+
}
|
|
8
|
+
function _array_with_holes(arr) {
|
|
9
|
+
if (Array.isArray(arr)) return arr;
|
|
10
|
+
}
|
|
11
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
12
|
+
try {
|
|
13
|
+
var info = gen[key](arg);
|
|
14
|
+
var value = info.value;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
reject(error);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (info.done) {
|
|
20
|
+
resolve(value);
|
|
21
|
+
} else {
|
|
22
|
+
Promise.resolve(value).then(_next, _throw);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function _async_to_generator(fn) {
|
|
26
|
+
return function() {
|
|
27
|
+
var self = this, args = arguments;
|
|
28
|
+
return new Promise(function(resolve, reject) {
|
|
29
|
+
var gen = fn.apply(self, args);
|
|
30
|
+
function _next(value) {
|
|
31
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
32
|
+
}
|
|
33
|
+
function _throw(err) {
|
|
34
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
35
|
+
}
|
|
36
|
+
_next(undefined);
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function _iterable_to_array_limit(arr, i) {
|
|
41
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
42
|
+
if (_i == null) return;
|
|
43
|
+
var _arr = [];
|
|
44
|
+
var _n = true;
|
|
45
|
+
var _d = false;
|
|
46
|
+
var _s, _e;
|
|
47
|
+
try {
|
|
48
|
+
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
49
|
+
_arr.push(_s.value);
|
|
50
|
+
if (i && _arr.length === i) break;
|
|
51
|
+
}
|
|
52
|
+
} catch (err) {
|
|
53
|
+
_d = true;
|
|
54
|
+
_e = err;
|
|
55
|
+
} finally{
|
|
56
|
+
try {
|
|
57
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
58
|
+
} finally{
|
|
59
|
+
if (_d) throw _e;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return _arr;
|
|
63
|
+
}
|
|
64
|
+
function _non_iterable_rest() {
|
|
65
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
66
|
+
}
|
|
67
|
+
function _sliced_to_array(arr, i) {
|
|
68
|
+
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
69
|
+
}
|
|
70
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
71
|
+
if (!o) return;
|
|
72
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
73
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
74
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
75
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
76
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
77
|
+
}
|
|
78
|
+
function _ts_generator(thisArg, body) {
|
|
79
|
+
var f, y, t, _ = {
|
|
80
|
+
label: 0,
|
|
81
|
+
sent: function() {
|
|
82
|
+
if (t[0] & 1) throw t[1];
|
|
83
|
+
return t[1];
|
|
84
|
+
},
|
|
85
|
+
trys: [],
|
|
86
|
+
ops: []
|
|
87
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
|
|
88
|
+
return d(g, "next", {
|
|
89
|
+
value: verb(0)
|
|
90
|
+
}), d(g, "throw", {
|
|
91
|
+
value: verb(1)
|
|
92
|
+
}), d(g, "return", {
|
|
93
|
+
value: verb(2)
|
|
94
|
+
}), typeof Symbol === "function" && d(g, Symbol.iterator, {
|
|
95
|
+
value: function() {
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
}), g;
|
|
99
|
+
function verb(n) {
|
|
100
|
+
return function(v) {
|
|
101
|
+
return step([
|
|
102
|
+
n,
|
|
103
|
+
v
|
|
104
|
+
]);
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function step(op) {
|
|
108
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
109
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
110
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
111
|
+
if (y = 0, t) op = [
|
|
112
|
+
op[0] & 2,
|
|
113
|
+
t.value
|
|
114
|
+
];
|
|
115
|
+
switch(op[0]){
|
|
116
|
+
case 0:
|
|
117
|
+
case 1:
|
|
118
|
+
t = op;
|
|
119
|
+
break;
|
|
120
|
+
case 4:
|
|
121
|
+
_.label++;
|
|
122
|
+
return {
|
|
123
|
+
value: op[1],
|
|
124
|
+
done: false
|
|
125
|
+
};
|
|
126
|
+
case 5:
|
|
127
|
+
_.label++;
|
|
128
|
+
y = op[1];
|
|
129
|
+
op = [
|
|
130
|
+
0
|
|
131
|
+
];
|
|
132
|
+
continue;
|
|
133
|
+
case 7:
|
|
134
|
+
op = _.ops.pop();
|
|
135
|
+
_.trys.pop();
|
|
136
|
+
continue;
|
|
137
|
+
default:
|
|
138
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
139
|
+
_ = 0;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
143
|
+
_.label = op[1];
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
147
|
+
_.label = t[1];
|
|
148
|
+
t = op;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
if (t && _.label < t[2]) {
|
|
152
|
+
_.label = t[2];
|
|
153
|
+
_.ops.push(op);
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
if (t[2]) _.ops.pop();
|
|
157
|
+
_.trys.pop();
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
op = body.call(thisArg, _);
|
|
161
|
+
} catch (e) {
|
|
162
|
+
op = [
|
|
163
|
+
6,
|
|
164
|
+
e
|
|
165
|
+
];
|
|
166
|
+
y = 0;
|
|
167
|
+
} finally{
|
|
168
|
+
f = t = 0;
|
|
169
|
+
}
|
|
170
|
+
if (op[0] & 5) throw op[1];
|
|
171
|
+
return {
|
|
172
|
+
value: op[0] ? op[1] : void 0,
|
|
173
|
+
done: true
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Default max-batch-size used by {@link twilioNotificationTextSendService}.
|
|
179
|
+
*/ var DEFAULT_TWILIO_NOTIFICATION_TEXT_SEND_SERVICE_MAX_BATCH_SIZE_PER_REQUEST = 50;
|
|
180
|
+
/**
|
|
181
|
+
* Sentinel template name used when a message has no `sendTemplateName`. Routed to the
|
|
182
|
+
* built-in default builder unless the consumer overrides it.
|
|
183
|
+
*/ var DEFAULT_TWILIO_NOTIFICATION_TEMPLATE_NAME = '_twilio_default';
|
|
184
|
+
/**
|
|
185
|
+
* Maximum SMS body length we send to Twilio. Twilio itself can accept up to 1600 characters
|
|
186
|
+
* per request and will segment as needed; bodies are truncated past this length.
|
|
187
|
+
*/ var TWILIO_NOTIFICATION_BODY_MAX_LENGTH = 1600;
|
|
188
|
+
/**
|
|
189
|
+
* Default {@link TwilioNotificationTextSendServiceTemplateBuilder} that builds one SMS per
|
|
190
|
+
* recipient using the message's `textContent.openingMessage` (falling back to `content.title`)
|
|
191
|
+
* as the body.
|
|
192
|
+
*
|
|
193
|
+
* Messages without a recipient phone number are skipped here; the calling service routes them
|
|
194
|
+
* to `ignored` in the final result.
|
|
195
|
+
*
|
|
196
|
+
* @param input - Builder input containing the messages and shared defaults.
|
|
197
|
+
* @param input.messages - Notification messages to convert to SMS inputs.
|
|
198
|
+
* @param input.defaults - Shared sender/callback defaults applied to each built SMS.
|
|
199
|
+
* @returns Array of {@link TwilioSendSmsInput} ready for dispatch.
|
|
200
|
+
*/ var defaultTwilioNotificationTextSendServiceTemplateBuilder = function defaultTwilioNotificationTextSendServiceTemplateBuilder(param) {
|
|
201
|
+
var messages = param.messages, defaults = param.defaults;
|
|
202
|
+
var inputs = [];
|
|
203
|
+
messages.forEach(function(message) {
|
|
204
|
+
var phone = message.inputContext.recipient.t;
|
|
205
|
+
if (phone) {
|
|
206
|
+
var _message_textContent;
|
|
207
|
+
var body = bodyFromNotificationMessageContent((_message_textContent = message.textContent) !== null && _message_textContent !== void 0 ? _message_textContent : message.content);
|
|
208
|
+
if (body) {
|
|
209
|
+
inputs.push({
|
|
210
|
+
to: phone,
|
|
211
|
+
body: body,
|
|
212
|
+
from: defaults.defaultFrom,
|
|
213
|
+
messagingServiceSid: defaults.messagingServiceSid,
|
|
214
|
+
statusCallback: defaults.statusCallback
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
return inputs;
|
|
220
|
+
};
|
|
221
|
+
/**
|
|
222
|
+
* Creates a {@link NotificationTextSendService} that dispatches notification SMS through Twilio.
|
|
223
|
+
*
|
|
224
|
+
* Groups messages by their `sendTemplateName`, batches them (up to `maxBatchSizePerRequest`),
|
|
225
|
+
* converts each batch to {@link TwilioSendSmsInput}s via the matching template builder
|
|
226
|
+
* (or the built-in default), and dispatches them through {@link TwilioService.sendBulkSms}.
|
|
227
|
+
*
|
|
228
|
+
* Messages missing a recipient phone are routed to `ignored` in the result.
|
|
229
|
+
*
|
|
230
|
+
* @param config - Service configuration including the Twilio service, template builders, and batch size.
|
|
231
|
+
* @returns A {@link NotificationTextSendService} that batches and sends SMS through Twilio.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* const textService = twilioNotificationTextSendService({ twilioService });
|
|
236
|
+
*
|
|
237
|
+
* const sendInstance = await textService.buildSendInstanceForTextNotificationMessages(messages);
|
|
238
|
+
* const result = await sendInstance();
|
|
239
|
+
* // result.success/failed/ignored are E164PhoneNumber arrays
|
|
240
|
+
* ```
|
|
241
|
+
*/ function twilioNotificationTextSendService(config) {
|
|
242
|
+
var twilioService = config.twilioService, defaultFrom = config.defaultFrom, messagingServiceSid = config.messagingServiceSid, statusCallbackUrl = config.statusCallbackUrl, inputMaxBatchSizePerRequest = config.maxBatchSizePerRequest, inputMessageBuilders = config.messageBuilders, inputDefaultMessageBuilder = config.defaultMessageBuilder;
|
|
243
|
+
var defaultBuilder = inputDefaultMessageBuilder !== null && inputDefaultMessageBuilder !== void 0 ? inputDefaultMessageBuilder : defaultTwilioNotificationTextSendServiceTemplateBuilder;
|
|
244
|
+
var lowercaseKeysMessageBuilders = inputMessageBuilders ? mapObjectKeysToLowercase(inputMessageBuilders) : undefined;
|
|
245
|
+
var maxBatchSizePerRequest = inputMaxBatchSizePerRequest !== null && inputMaxBatchSizePerRequest !== void 0 ? inputMaxBatchSizePerRequest : DEFAULT_TWILIO_NOTIFICATION_TEXT_SEND_SERVICE_MAX_BATCH_SIZE_PER_REQUEST;
|
|
246
|
+
var defaults = {
|
|
247
|
+
defaultFrom: defaultFrom,
|
|
248
|
+
messagingServiceSid: messagingServiceSid,
|
|
249
|
+
statusCallback: statusCallbackUrl
|
|
250
|
+
};
|
|
251
|
+
var sendService = {
|
|
252
|
+
buildSendInstanceForTextNotificationMessages: function buildSendInstanceForTextNotificationMessages(notificationMessages) {
|
|
253
|
+
return _async_to_generator(function() {
|
|
254
|
+
var groupedMessages, messageSendBatches, buildInputArrays, sendInputs, sendFn;
|
|
255
|
+
return _ts_generator(this, function(_state) {
|
|
256
|
+
switch(_state.label){
|
|
257
|
+
case 0:
|
|
258
|
+
groupedMessages = multiValueMapBuilder();
|
|
259
|
+
// Messages without a recipient phone number are dropped here — there is nothing for
|
|
260
|
+
// Twilio to do with them, and the result is keyed by E164 phone so we cannot record
|
|
261
|
+
// them in `ignored` either.
|
|
262
|
+
notificationMessages.forEach(function(message) {
|
|
263
|
+
var phone = message.inputContext.recipient.t;
|
|
264
|
+
if (phone) {
|
|
265
|
+
var _ref, _ref1;
|
|
266
|
+
var _message_textContent;
|
|
267
|
+
var sendTemplateName = (_ref = (_ref1 = (_message_textContent = message.textContent) === null || _message_textContent === void 0 ? void 0 : _message_textContent.sendTemplateName) !== null && _ref1 !== void 0 ? _ref1 : message.content.sendTemplateName) !== null && _ref !== void 0 ? _ref : DEFAULT_TWILIO_NOTIFICATION_TEMPLATE_NAME;
|
|
268
|
+
groupedMessages.add(sendTemplateName, message);
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
messageSendBatches = groupedMessages.entries().flatMap(function(param) {
|
|
272
|
+
var _param = _sliced_to_array(param, 2), templateType = _param[0], messages = _param[1];
|
|
273
|
+
return batch(messages, maxBatchSizePerRequest).map(function(x) {
|
|
274
|
+
return [
|
|
275
|
+
templateType,
|
|
276
|
+
x
|
|
277
|
+
];
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
return [
|
|
281
|
+
4,
|
|
282
|
+
Promise.all(messageSendBatches.map(function(param) {
|
|
283
|
+
var _param = _sliced_to_array(param, 2), sendTemplateName = _param[0], messages = _param[1];
|
|
284
|
+
return _async_to_generator(function() {
|
|
285
|
+
var _ref, builder;
|
|
286
|
+
return _ts_generator(this, function(_state) {
|
|
287
|
+
builder = (_ref = lowercaseKeysMessageBuilders === null || lowercaseKeysMessageBuilders === void 0 ? void 0 : lowercaseKeysMessageBuilders[sendTemplateName.toLowerCase()]) !== null && _ref !== void 0 ? _ref : defaultBuilder;
|
|
288
|
+
return [
|
|
289
|
+
2,
|
|
290
|
+
builder({
|
|
291
|
+
twilioService: twilioService,
|
|
292
|
+
sendTemplateName: sendTemplateName,
|
|
293
|
+
messages: messages,
|
|
294
|
+
defaults: defaults
|
|
295
|
+
})
|
|
296
|
+
];
|
|
297
|
+
});
|
|
298
|
+
})();
|
|
299
|
+
}))
|
|
300
|
+
];
|
|
301
|
+
case 1:
|
|
302
|
+
buildInputArrays = _state.sent();
|
|
303
|
+
sendInputs = buildInputArrays.flatMap(function(x) {
|
|
304
|
+
return asArray(x);
|
|
305
|
+
});
|
|
306
|
+
sendFn = function sendFn() {
|
|
307
|
+
return _async_to_generator(function() {
|
|
308
|
+
var success, failed, ignored, result;
|
|
309
|
+
return _ts_generator(this, function(_state) {
|
|
310
|
+
switch(_state.label){
|
|
311
|
+
case 0:
|
|
312
|
+
success = [];
|
|
313
|
+
failed = [];
|
|
314
|
+
ignored = [];
|
|
315
|
+
return [
|
|
316
|
+
4,
|
|
317
|
+
runAsyncTasksForValues(batch(sendInputs, maxBatchSizePerRequest), function(inputBatch) {
|
|
318
|
+
return _async_to_generator(function() {
|
|
319
|
+
var results;
|
|
320
|
+
return _ts_generator(this, function(_state) {
|
|
321
|
+
switch(_state.label){
|
|
322
|
+
case 0:
|
|
323
|
+
return [
|
|
324
|
+
4,
|
|
325
|
+
twilioService.sendBulkSms(inputBatch)
|
|
326
|
+
];
|
|
327
|
+
case 1:
|
|
328
|
+
results = _state.sent();
|
|
329
|
+
results.forEach(function(result) {
|
|
330
|
+
if (result.error || result.status === 'failed' || result.status === 'undelivered') {
|
|
331
|
+
pushArrayItemsIntoArray(failed, [
|
|
332
|
+
result.to
|
|
333
|
+
]);
|
|
334
|
+
} else if (result.sandboxed) {
|
|
335
|
+
pushArrayItemsIntoArray(ignored, [
|
|
336
|
+
result.to
|
|
337
|
+
]);
|
|
338
|
+
} else {
|
|
339
|
+
pushArrayItemsIntoArray(success, [
|
|
340
|
+
result.to
|
|
341
|
+
]);
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
return [
|
|
345
|
+
2
|
|
346
|
+
];
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
})();
|
|
350
|
+
}, {
|
|
351
|
+
maxParallelTasks: 3
|
|
352
|
+
})
|
|
353
|
+
];
|
|
354
|
+
case 1:
|
|
355
|
+
_state.sent();
|
|
356
|
+
result = {
|
|
357
|
+
success: success,
|
|
358
|
+
failed: failed,
|
|
359
|
+
ignored: ignored
|
|
360
|
+
};
|
|
361
|
+
return [
|
|
362
|
+
2,
|
|
363
|
+
result
|
|
364
|
+
];
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
})();
|
|
368
|
+
};
|
|
369
|
+
return [
|
|
370
|
+
2,
|
|
371
|
+
sendFn
|
|
372
|
+
];
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
})();
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
return sendService;
|
|
379
|
+
}
|
|
380
|
+
function bodyFromNotificationMessageContent(content) {
|
|
381
|
+
var parts = [];
|
|
382
|
+
if (content.title) {
|
|
383
|
+
parts.push(content.title);
|
|
384
|
+
}
|
|
385
|
+
if (content.openingMessage) {
|
|
386
|
+
parts.push(content.openingMessage);
|
|
387
|
+
}
|
|
388
|
+
if (content.closingMessage) {
|
|
389
|
+
parts.push(content.closingMessage);
|
|
390
|
+
}
|
|
391
|
+
if (content.actionUrl) {
|
|
392
|
+
parts.push(content.actionUrl);
|
|
393
|
+
}
|
|
394
|
+
var joined = parts.join('\n').trim();
|
|
395
|
+
return joined.length > TWILIO_NOTIFICATION_BODY_MAX_LENGTH ? joined.slice(0, TWILIO_NOTIFICATION_BODY_MAX_LENGTH) : joined;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export { DEFAULT_TWILIO_NOTIFICATION_TEMPLATE_NAME, DEFAULT_TWILIO_NOTIFICATION_TEXT_SEND_SERVICE_MAX_BATCH_SIZE_PER_REQUEST, TWILIO_NOTIFICATION_BODY_MAX_LENGTH, defaultTwilioNotificationTextSendServiceTemplateBuilder, twilioNotificationTextSendService };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dereekb/firebase-server/twilio",
|
|
3
|
+
"version": "13.12.0",
|
|
4
|
+
"peerDependencies": {
|
|
5
|
+
"@dereekb/date": "13.12.0",
|
|
6
|
+
"@dereekb/firebase": "13.12.0",
|
|
7
|
+
"@dereekb/firebase-server": "13.12.0",
|
|
8
|
+
"@dereekb/model": "13.12.0",
|
|
9
|
+
"@dereekb/nestjs": "13.12.0",
|
|
10
|
+
"@dereekb/rxjs": "13.12.0",
|
|
11
|
+
"@dereekb/util": "13.12.0"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
"./package.json": "./package.json",
|
|
15
|
+
".": {
|
|
16
|
+
"module": "./index.esm.js",
|
|
17
|
+
"types": "./index.d.ts",
|
|
18
|
+
"import": "./index.cjs.mjs",
|
|
19
|
+
"default": "./index.cjs.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"module": "./index.esm.js",
|
|
23
|
+
"main": "./index.cjs.js",
|
|
24
|
+
"types": "./index.d.ts"
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './notification.send.service.twilio';
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { type ArrayOrValue, type Maybe, type PromiseOrValue } from '@dereekb/util';
|
|
2
|
+
import { type NotificationMessage, type NotificationSendMessageTemplateName, type NotificationSendTextMessagesResult } from '@dereekb/firebase';
|
|
3
|
+
import { type TwilioMessagingServiceSid, type TwilioPhoneNumber, type TwilioSendSmsInput, type TwilioService, type TwilioStatusCallbackUrl } from '@dereekb/nestjs/twilio';
|
|
4
|
+
/**
|
|
5
|
+
* Structural mirror of `@dereekb/firebase-server/model`'s `NotificationSendMessagesInstance`.
|
|
6
|
+
*
|
|
7
|
+
* Declared locally so this package can be built without pulling the firebase-server/model
|
|
8
|
+
* subpackage's source through path aliases (which trips the rollup-typescript plugin's
|
|
9
|
+
* `rootDir` restriction). The shape matches the upstream definition exactly, so values
|
|
10
|
+
* produced here are assignment-compatible with consumers that import the real type.
|
|
11
|
+
*/
|
|
12
|
+
export type NotificationSendMessagesInstance<R> = () => Promise<R>;
|
|
13
|
+
/**
|
|
14
|
+
* Structural mirror of `@dereekb/firebase-server/model`'s `NotificationTextSendService`.
|
|
15
|
+
*
|
|
16
|
+
* See the note on {@link NotificationSendMessagesInstance} for why this is re-declared
|
|
17
|
+
* locally instead of imported.
|
|
18
|
+
*/
|
|
19
|
+
export interface NotificationTextSendService {
|
|
20
|
+
buildSendInstanceForTextNotificationMessages(notificationMessages: NotificationMessage[]): Promise<NotificationSendMessagesInstance<NotificationSendTextMessagesResult>>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Default max-batch-size used by {@link twilioNotificationTextSendService}.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEFAULT_TWILIO_NOTIFICATION_TEXT_SEND_SERVICE_MAX_BATCH_SIZE_PER_REQUEST = 50;
|
|
26
|
+
/**
|
|
27
|
+
* Sentinel template name used when a message has no `sendTemplateName`. Routed to the
|
|
28
|
+
* built-in default builder unless the consumer overrides it.
|
|
29
|
+
*/
|
|
30
|
+
export declare const DEFAULT_TWILIO_NOTIFICATION_TEMPLATE_NAME: NotificationSendMessageTemplateName;
|
|
31
|
+
/**
|
|
32
|
+
* Maximum SMS body length we send to Twilio. Twilio itself can accept up to 1600 characters
|
|
33
|
+
* per request and will segment as needed; bodies are truncated past this length.
|
|
34
|
+
*/
|
|
35
|
+
export declare const TWILIO_NOTIFICATION_BODY_MAX_LENGTH = 1600;
|
|
36
|
+
/**
|
|
37
|
+
* Input passed to a {@link TwilioNotificationTextSendServiceTemplateBuilder}.
|
|
38
|
+
*/
|
|
39
|
+
export interface TwilioNotificationTextSendServiceTemplateBuilderInput {
|
|
40
|
+
/**
|
|
41
|
+
* The Twilio service that will dispatch built SMS inputs.
|
|
42
|
+
*/
|
|
43
|
+
readonly twilioService: TwilioService;
|
|
44
|
+
/**
|
|
45
|
+
* The resolved template name for this batch.
|
|
46
|
+
*/
|
|
47
|
+
readonly sendTemplateName: NotificationSendMessageTemplateName;
|
|
48
|
+
/**
|
|
49
|
+
* Notification messages assigned to this template.
|
|
50
|
+
*/
|
|
51
|
+
readonly messages: NotificationMessage[];
|
|
52
|
+
/**
|
|
53
|
+
* Defaults to apply to built SMS inputs when the builder does not specify them.
|
|
54
|
+
*/
|
|
55
|
+
readonly defaults: TwilioNotificationDefaults;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Sender / callback defaults applied to built SMS inputs unless the template builder
|
|
59
|
+
* overrides them.
|
|
60
|
+
*/
|
|
61
|
+
export interface TwilioNotificationDefaults {
|
|
62
|
+
readonly defaultFrom?: Maybe<TwilioPhoneNumber>;
|
|
63
|
+
readonly messagingServiceSid?: Maybe<TwilioMessagingServiceSid>;
|
|
64
|
+
readonly statusCallback?: Maybe<TwilioStatusCallbackUrl>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Function that converts a group of notification messages into zero or more
|
|
68
|
+
* {@link TwilioSendSmsInput} values.
|
|
69
|
+
*/
|
|
70
|
+
export type TwilioNotificationTextSendServiceTemplateBuilder = (input: TwilioNotificationTextSendServiceTemplateBuilderInput) => PromiseOrValue<ArrayOrValue<TwilioSendSmsInput>>;
|
|
71
|
+
/**
|
|
72
|
+
* Configuration for {@link twilioNotificationTextSendService}.
|
|
73
|
+
*/
|
|
74
|
+
export interface TwilioNotificationTextSendServiceConfig {
|
|
75
|
+
/**
|
|
76
|
+
* The Twilio service used to dispatch outbound SMS.
|
|
77
|
+
*/
|
|
78
|
+
readonly twilioService: TwilioService;
|
|
79
|
+
/**
|
|
80
|
+
* Sender phone number applied to messages that do not have an explicit `from` set by a builder.
|
|
81
|
+
* When omitted, the value configured on the underlying {@link TwilioServiceConfig} is used.
|
|
82
|
+
*/
|
|
83
|
+
readonly defaultFrom?: Maybe<TwilioPhoneNumber>;
|
|
84
|
+
/**
|
|
85
|
+
* Twilio Messaging Service SID applied when no `from` is provided.
|
|
86
|
+
*/
|
|
87
|
+
readonly messagingServiceSid?: Maybe<TwilioMessagingServiceSid>;
|
|
88
|
+
/**
|
|
89
|
+
* Status callback URL applied to outbound messages built without an explicit callback.
|
|
90
|
+
*/
|
|
91
|
+
readonly statusCallbackUrl?: Maybe<TwilioStatusCallbackUrl>;
|
|
92
|
+
/**
|
|
93
|
+
* Maximum number of SMS sends issued in a single batch. Defaults to
|
|
94
|
+
* {@link DEFAULT_TWILIO_NOTIFICATION_TEXT_SEND_SERVICE_MAX_BATCH_SIZE_PER_REQUEST}.
|
|
95
|
+
*/
|
|
96
|
+
readonly maxBatchSizePerRequest?: Maybe<number>;
|
|
97
|
+
/**
|
|
98
|
+
* Custom template builders keyed by send-template name. When omitted (or when no builder
|
|
99
|
+
* matches a message's `sendTemplateName`), the built-in default builder is used to build
|
|
100
|
+
* a single SMS per recipient from the message's `textContent`/`content`.
|
|
101
|
+
*/
|
|
102
|
+
readonly messageBuilders?: Maybe<Record<NotificationSendMessageTemplateName, TwilioNotificationTextSendServiceTemplateBuilder>>;
|
|
103
|
+
/**
|
|
104
|
+
* Optional override of the built-in default builder. If unset, a built-in implementation is
|
|
105
|
+
* used that maps `textContent.openingMessage ?? content.title` to the SMS body.
|
|
106
|
+
*/
|
|
107
|
+
readonly defaultMessageBuilder?: Maybe<TwilioNotificationTextSendServiceTemplateBuilder>;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Twilio-backed implementation of {@link NotificationTextSendService}.
|
|
111
|
+
*/
|
|
112
|
+
export type TwilioNotificationTextSendService = NotificationTextSendService;
|
|
113
|
+
/**
|
|
114
|
+
* Default {@link TwilioNotificationTextSendServiceTemplateBuilder} that builds one SMS per
|
|
115
|
+
* recipient using the message's `textContent.openingMessage` (falling back to `content.title`)
|
|
116
|
+
* as the body.
|
|
117
|
+
*
|
|
118
|
+
* Messages without a recipient phone number are skipped here; the calling service routes them
|
|
119
|
+
* to `ignored` in the final result.
|
|
120
|
+
*
|
|
121
|
+
* @param input - Builder input containing the messages and shared defaults.
|
|
122
|
+
* @param input.messages - Notification messages to convert to SMS inputs.
|
|
123
|
+
* @param input.defaults - Shared sender/callback defaults applied to each built SMS.
|
|
124
|
+
* @returns Array of {@link TwilioSendSmsInput} ready for dispatch.
|
|
125
|
+
*/
|
|
126
|
+
export declare const defaultTwilioNotificationTextSendServiceTemplateBuilder: TwilioNotificationTextSendServiceTemplateBuilder;
|
|
127
|
+
/**
|
|
128
|
+
* Creates a {@link NotificationTextSendService} that dispatches notification SMS through Twilio.
|
|
129
|
+
*
|
|
130
|
+
* Groups messages by their `sendTemplateName`, batches them (up to `maxBatchSizePerRequest`),
|
|
131
|
+
* converts each batch to {@link TwilioSendSmsInput}s via the matching template builder
|
|
132
|
+
* (or the built-in default), and dispatches them through {@link TwilioService.sendBulkSms}.
|
|
133
|
+
*
|
|
134
|
+
* Messages missing a recipient phone are routed to `ignored` in the result.
|
|
135
|
+
*
|
|
136
|
+
* @param config - Service configuration including the Twilio service, template builders, and batch size.
|
|
137
|
+
* @returns A {@link NotificationTextSendService} that batches and sends SMS through Twilio.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```ts
|
|
141
|
+
* const textService = twilioNotificationTextSendService({ twilioService });
|
|
142
|
+
*
|
|
143
|
+
* const sendInstance = await textService.buildSendInstanceForTextNotificationMessages(messages);
|
|
144
|
+
* const result = await sendInstance();
|
|
145
|
+
* // result.success/failed/ignored are E164PhoneNumber arrays
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export declare function twilioNotificationTextSendService(config: TwilioNotificationTextSendServiceConfig): TwilioNotificationTextSendService;
|
package/zoho/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/zoho",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.12.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
-
"@dereekb/analytics": "13.
|
|
6
|
-
"@dereekb/date": "13.
|
|
7
|
-
"@dereekb/model": "13.
|
|
8
|
-
"@dereekb/nestjs": "13.
|
|
9
|
-
"@dereekb/rxjs": "13.
|
|
10
|
-
"@dereekb/firebase": "13.
|
|
11
|
-
"@dereekb/util": "13.
|
|
12
|
-
"@dereekb/zoho": "13.
|
|
5
|
+
"@dereekb/analytics": "13.12.0",
|
|
6
|
+
"@dereekb/date": "13.12.0",
|
|
7
|
+
"@dereekb/model": "13.12.0",
|
|
8
|
+
"@dereekb/nestjs": "13.12.0",
|
|
9
|
+
"@dereekb/rxjs": "13.12.0",
|
|
10
|
+
"@dereekb/firebase": "13.12.0",
|
|
11
|
+
"@dereekb/util": "13.12.0",
|
|
12
|
+
"@dereekb/zoho": "13.12.0"
|
|
13
13
|
},
|
|
14
14
|
"exports": {
|
|
15
15
|
"./package.json": "./package.json",
|