@dbx-tools/email 0.6.53 → 0.6.55

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.
@@ -22,7 +22,7 @@
22
22
  * @module
23
23
  */
24
24
  import { ConfigurationError, ExecutionError, ValidationError, } from "@databricks/appkit";
25
- import { execution, log, object } from "@dbx-tools/shared-core";
25
+ import { execution, log } from "@dbx-tools/shared-core";
26
26
  import nodemailer from "nodemailer";
27
27
  import { resolveEmailConfig } from "./config.js";
28
28
  import { EMAIL_SEND_SETTINGS, MAX_ATTACHMENT_BYTES, MAX_ATTACHMENT_COUNT, MAX_ATTACHMENTS_TOTAL_BYTES, MAX_BODY_CHARS, } from "./defaults.js";
@@ -242,7 +242,7 @@ async function dispatch(message, from, signal, options) {
242
242
  const recipient = recipientEcho(message.to);
243
243
  signal?.throwIfAborted();
244
244
  if (config.mode === "file") {
245
- const path = await writeOutboxEmail(message, from, config.outDir, config.brand, options);
245
+ const path = await writeOutboxEmail(message, from, config.outDir, config.brand);
246
246
  return { sent: true, recipient, from, messageId: path };
247
247
  }
248
248
  if (!transporter) {
@@ -253,13 +253,16 @@ async function dispatch(message, from, signal, options) {
253
253
  subject: message.subject,
254
254
  body: message.body,
255
255
  brand: config.brand,
256
- ...object.optional("trailer", options?.trailer),
257
256
  });
258
257
  const info = await abortable(transporter.sendMail({
259
258
  from,
260
259
  to: message.to,
261
260
  subject: message.subject,
262
- text: rendered.text,
261
+ // A caller-supplied plain-text part WINS over the generated one. Both parts
262
+ // still come from the same content; this only lets a caller control the
263
+ // text alternative's exact line layout, which some clients parse (see
264
+ // `SendEmailOptions.text`).
265
+ text: options?.text ?? rendered.text,
263
266
  html: rendered.html,
264
267
  ...(message.cc && message.cc.length > 0 ? { cc: message.cc } : {}),
265
268
  ...(message.bcc && message.bcc.length > 0 ? { bcc: message.bcc } : {}),
@@ -295,4 +298,4 @@ export async function sendEmail(message, from, signal, options) {
295
298
  assertSenderAllowed(from, getEmailRuntime().config.allowedSenders);
296
299
  return executeWrite("send", EMAIL_SEND_SETTINGS, (executeSignal) => dispatch(message, from, executeSignal, options), signal);
297
300
  }
298
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNwb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3RyYW5zcG9ydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUVILE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsY0FBYyxFQUNkLGVBQWUsR0FFaEIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVoRSxPQUFPLFVBQXNELE1BQU0sWUFBWSxDQUFDO0FBQ2hGLE9BQU8sRUFBRSxrQkFBa0IsRUFBb0QsTUFBTSxhQUFhLENBQUM7QUFDbkcsT0FBTyxFQUNMLG1CQUFtQixFQUNuQixvQkFBb0IsRUFDcEIsb0JBQW9CLEVBQ3BCLDJCQUEyQixFQUMzQixjQUFjLEdBRWYsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMvQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFbEQsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBb0I3Qzs7OztHQUlHO0FBQ0gsTUFBTSxhQUFhLEdBQUcsU0FBUyxDQUFDLGNBQWMsRUFBMEIsQ0FBQztBQUV6RSxJQUFJLE9BQWlDLENBQUM7QUFFdEM7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUFDLFNBQTZCO0lBQzNELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE1BQU0sTUFBTSxHQUFHLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzdDLE9BQU8sR0FBRztZQUNSLE1BQU07WUFDTixPQUFPLEVBQUUsYUFBYTtZQUN0QixHQUFH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LE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3RFLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUN4QyxDQUFDLEVBQ0YsTUFBTSxDQUNQLENBQUM7SUFDRixPQUFPO1FBQ0wsSUFBSSxFQUFFLElBQUk7UUFDVixTQUFTO1FBQ1QsSUFBSTtRQUNKLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUN6RCxDQUFDO0FBQ0osQ0FBQztBQW9CRDs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsU0FBUyxDQUM3QixPQUFxQixFQUNyQixJQUFZLEVBQ1osTUFBb0IsRUFDcEIsT0FBMEI7SUFFMUIsSUFBSSxPQUFPLENBQUMsRUFBRSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUM1QixNQUFNLGVBQWUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUNELHVCQUF1QixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pDLG1CQUFtQixDQUFDLElBQUksRUFBRSxlQUFlLEVBQUUsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDbkUsT0FBTyxZQUFZLENBQ2pCLE1BQU0sRUFDTixtQkFBbUIsRUFDbkIsQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxPQUFPLENBQUMsRUFDbEUsTUFBTSxDQUNQLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgZW1haWwgcnVudGltZTogYSBsYXppbHktYnVpbHQsIHByb2Nlc3Mtd2lkZSBkaXNwYXRjaGVyIHBsdXMgaXRzXG4gKiByZXNvbHZlZCBjb25maWcsIGFuZCB7QGxpbmsgc2VuZEVtYWlsfSB3aGljaCBzZW5kcyBvbmVcbiAqIHtAbGluayBFbWFpbE1lc3NhZ2V9IHRocm91Z2ggaXQuIEluIFNNVFAgbW9kZSB0aGUgcnVudGltZSBob2xkcyBhXG4gKiBtZW1vaXplZCBub2RlbWFpbGVyIHRyYW5zcG9ydCAoc2hhcmVkIGJ5IHRoZSBwbHVnaW4ncyBzZXR1cCBhbmQgdGhlXG4gKiBhZ2VudCB0b29sLCBzbyB0aGV5IHJldXNlIG9uZSBjb25uZWN0aW9uIHBvb2wpOyBpbiBmaWxlL291dGJveCBtb2RlIGl0XG4gKiBob2xkcyBubyB0cmFuc3BvcnQgYW5kIHtAbGluayBzZW5kRW1haWx9IHdyaXRlcyBIVE1MIHRvIGRpc2sgaW5zdGVhZC5cbiAqIFRoZSBmaXJzdCBjYWxsZXIgKG5vcm1hbGx5IHRoZSBwbHVnaW4gYXQgc2V0dXApIHByaW1lcyBpdCB3aXRoIHRoZVxuICogcGx1Z2luJ3MgY29uZmlnOyBsYXRlciBjYWxsZXJzIHJldXNlIGl0LlxuICpcbiAqIFRoZSBydW50aW1lIGFsc28gY2FycmllcyB0aGUge0BsaW5rIEVtYWlsRXhlY3V0b3J9IGV2ZXJ5IG91dGJvdW5kIHNlbmQgcnVuc1xuICogdGhyb3VnaC4gVGhlIHBsdWdpbiBpbnN0YWxscyBpdHMgb3duIGBleGVjdXRlKClgIHRoZXJlIGF0IHNldHVwLCB3aGljaCBpc1xuICogaG93IHRoZSBNYXN0cmEgdG9vbCAtIGEgcGxhaW4gZnVuY3Rpb24gd2l0aCBubyBwbHVnaW4gaW5zdGFuY2UgaW4gc2NvcGUgLVxuICogc3RpbGwgZ2V0cyBBcHBLaXQncyByZXRyeSAvIHRpbWVvdXQgLyB0ZWxlbWV0cnkgY2hhaW4uIFdpdGhvdXQgYSByZWdpc3RlcmVkXG4gKiBwbHVnaW4gKGEgZGlyZWN0IGNhbGwgZnJvbSBhIHNjcmlwdCBvciBhIHRlc3QpIHRoZSBzZW5kIHN0aWxsIHJ1bnMsIGp1c3RcbiAqIHdpdGhvdXQgaW50ZXJjZXB0b3JzLlxuICpcbiAqIEV2ZXJ5IGVudHJ5IHBvaW50IHRha2VzIGFuIG9wdGlvbmFsIHtAbGluayBBYm9ydFNpZ25hbH0gc28gdGhlIHBsdWdpbidzXG4gKiBgZXhlY3V0ZSgpYCB0aW1lb3V0IGFuZCBhIGNsaWVudCBkaXNjb25uZWN0IGJvdGggc3RvcCB0aGUgY2FsbGVyIHdhaXRpbmdcbiAqIG9uIFNNVFAuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7XG4gIENvbmZpZ3VyYXRpb25FcnJvcixcbiAgRXhlY3V0aW9uRXJyb3IsXG4gIFZhbGlkYXRpb25FcnJvcixcbiAgdHlwZSBFeGVjdXRpb25SZXN1bHQsXG59IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGV4ZWN1dGlvbiwgbG9nLCBvYmplY3QgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBFbWFpbEF0dGFjaG1lbnQsIEVtYWlsTWVzc2FnZSwgRW1haWxSZXN1bHQgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtZW1haWxcIjtcbmltcG9ydCBub2RlbWFpbGVyLCB7IHR5cGUgU2VuZE1haWxPcHRpb25zLCB0eXBlIFRyYW5zcG9ydGVyIH0gZnJvbSBcIm5vZGVtYWlsZXJcIjtcbmltcG9ydCB7IHJlc29sdmVFbWFpbENvbmZpZywgdHlwZSBFbWFpbFBsdWdpbkNvbmZpZywgdHlwZSBSZXNvbHZlZEVtYWlsQ29uZmlnIH0gZnJvbSBcIi4vY29uZmlnLnRzXCI7XG5pbXBvcnQge1xuICBFTUFJTF9TRU5EX1NFVFRJTkdTLFxuICBNQVhfQVRUQUNITUVOVF9CWVRFUyxcbiAgTUFYX0FUVEFDSE1FTlRfQ09VTlQsXG4gIE1BWF9BVFRBQ0hNRU5UU19UT1RBTF9CWVRFUyxcbiAgTUFYX0JPRFlfQ0hBUlMsXG4gIHR5cGUgRW1haWxFeGVjdXRpb25TZXR0aW5ncyxcbn0gZnJvbSBcIi4vZGVmYXVsdHMudHNcIjtcbmltcG9ydCB7IHJlbmRlckVtYWlsIH0gZnJvbSBcIi4vZW1haWwtaHRtbC50c1wiO1xuaW1wb3J0IHsgd3JpdGVPdXRib3hFbWFpbCB9IGZyb20gXCIuL291dGJveC50c1wiO1xuaW1wb3J0IHsgYXNzZXJ0U2VuZGVyQWxsb3dlZCB9IGZyb20gXCIuL3NlbmRlci50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiZW1haWwvdHJhbnNwb3J0XCIpO1xuXG4vKipcbiAqIFJ1bnMgb25lIG91dGJvdW5kIHNlbmQgdGhyb3VnaCBBcHBLaXQncyBpbnRlcmNlcHRvciBjaGFpbi4gTWF0Y2hlc1xuICogYFBsdWdpbi5leGVjdXRlKClgLCB3aGljaCBuZXZlciB0aHJvd3M6IGEgZmFpbHVyZSBjb21lcyBiYWNrIGFzXG4gKiBgeyBvazogZmFsc2UgfWAuXG4gKi9cbmV4cG9ydCB0eXBlIEVtYWlsRXhlY3V0b3IgPSA8VD4oXG4gIGZuOiAoc2lnbmFsPzogQWJvcnRTaWduYWwpID0+IFByb21pc2U8VD4sXG4gIHNldHRpbmdzOiBFbWFpbEV4ZWN1dGlvblNldHRpbmdzLFxuKSA9PiBQcm9taXNlPEV4ZWN1dGlvblJlc3VsdDxUPj47XG5cbi8qKiBUaGUgc2hhcmVkIGRpc3BhdGNoZXIsIGl0cyByZXNvbHZlZCBjb25maWcsIGFuZCB0aGUgc2VuZCBleGVjdXRvci4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRW1haWxSdW50aW1lIHtcbiAgLyoqIFByZXNlbnQgb25seSBpbiBTTVRQIG1vZGUuICovXG4gIHRyYW5zcG9ydGVyPzogVHJhbnNwb3J0ZXI7XG4gIGNvbmZpZzogUmVzb2x2ZWRFbWFpbENvbmZpZztcbiAgZXhlY3V0ZTogRW1haWxFeGVjdXRvcjtcbn1cblxuLyoqXG4gKiBFeGVjdXRvciB1c2VkIHVudGlsIChvciB1bmxlc3MpIHRoZSBwbHVnaW4gaW5zdGFsbHMgaXRzIG93bjogcnVuIHRoZSBzZW5kXG4gKiBkaXJlY3RseSwgbWFwcGluZyBhIHRocm93IG9udG8gdGhlIHNhbWUge0BsaW5rIEV4ZWN1dGlvblJlc3VsdH0gc2hhcGUgc29cbiAqIGNhbGwgc2l0ZXMgYnJhbmNoIG9uIGBva2AgZWl0aGVyIHdheS5cbiAqL1xuY29uc3QgZGlyZWN0RXhlY3V0ZSA9IGV4ZWN1dGlvbi5kaXJlY3RFeGVjdXRvcjxFbWFpbEV4ZWN1dGlvblNldHRpbmdzPigpO1xuXG5sZXQgcnVudGltZTogRW1haWxSdW50aW1lIHwgdW5kZWZpbmVkO1xuXG4vKipcbiAqIFJldHVybiB0aGUgc2hhcmVkIHJ1bnRpbWUsIGJ1aWxkaW5nIGl0IG9uIGZpcnN0IHVzZSBieSByZXNvbHZpbmdcbiAqIGBvdmVycmlkZXNgIG92ZXIgdGhlIGVudmlyb25tZW50IChgU01UUF9IT1NUYCwgYFNNVFBfUE9SVGAsXG4gKiBgU01UUF9TRUNVUkVgLCBgU01UUF9VU0VSYCwgYFNNVFBfUEFTU1dPUkRgLCBgRU1BSUxfRE9NQUlOYCxcbiAqIGBFTUFJTF9GUk9NYCwgYEVNQUlMX0FMTE9XRURfU0VOREVSU2AsIGBFTUFJTF9TRU5ERVJfUE9MSUNZYCxcbiAqIGBFTUFJTF9PVVRCT1hfTU9ERWAsIGBFTUFJTF9PVVRCT1hfRElSYCkgdGhyb3VnaFxuICoge0BsaW5rIHJlc29sdmVFbWFpbENvbmZpZ30uIFdpdGggU01UUCBjcmVkZW50aWFscyBwcmVzZW50IGl0IGhvbGRzIGFcbiAqIG5vZGVtYWlsZXIgdHJhbnNwb3J0IGFuZCBpdHMgY29ubmVjdGlvbiBwb29sOyBvdGhlcndpc2UgaXQgaXMgaW5cbiAqIGZpbGUvb3V0Ym94IG1vZGUgYW5kIGhvbGRzIG5vbmUuXG4gKlxuICogYG92ZXJyaWRlc2AgaXMgcmVhZCBvbmx5IG9uIHRoZSBjYWxsIHRoYXQgYnVpbGRzIHRoZSBydW50aW1lLCBzbyBwcmltZSBpdFxuICogZnJvbSB0aGUgcGx1Z2luJ3MgY29uZmlnIGF0IHNldHVwOyBsYXRlciBjYWxsZXJzICh0aGUgdG9vbCdzIGBleGVjdXRlYCxcbiAqIHRoZSBzZW5kZXItb3B0aW9ucyByb3V0ZSkgcGFzcyBub3RoaW5nIGFuZCBnZXQgdGhlIHNhbWUgaW5zdGFuY2UuIFRocm93c1xuICogd2hhdGV2ZXIge0BsaW5rIHJlc29sdmVFbWFpbENvbmZpZ30gdGhyb3dzIGZvciBhbiB1bnVzYWJsZSBjb25maWd1cmF0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RW1haWxSdW50aW1lKG92ZXJyaWRlcz86IEVtYWlsUGx1Z2luQ29uZmlnKTogRW1haWxSdW50aW1lIHtcbiAgaWYgKCFydW50aW1lKSB7XG4gICAgY29uc3QgY29uZmlnID0gcmVzb2x2ZUVtYWlsQ29uZmlnKG92ZXJyaWRlcyk7XG4gICAgcnVudGltZSA9IHtcbiAgICAgIGNvbmZpZyxcbiAgICAgIGV4ZWN1dGU6IGRpcmVjdEV4ZWN1dGUsXG4gICAgICAuLi4oY29uZmlnLm1vZGUgPT09IFwic210cFwiXG4gICAgICAgID8ge1xuICAgICAgICAgICAgdHJhbnNwb3J0ZXI6IG5vZGVtYWlsZXIuY3JlYXRlVHJhbnNwb3J0KHtcbiAgICAgICAgICAgICAgaG9zdDogY29uZmlnLmhvc3QsXG4gICAgICAgICAgICAgIHBvcnQ6IGNvbmZpZy5wb3J0LFxuICAgICAgICAgICAgICBzZWN1cmU6IGNvbmZpZy5zZWN1cmUsXG4gICAgICAgICAgICAgIGF1dGg6IGNvbmZpZy5hdXRoLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfVxuICAgICAgICA6IHt9KSxcbiAgICB9O1xuICB9XG4gIHJldHVybiBydW50aW1lO1xufVxuXG4vKipcbiAqIEluc3RhbGwgdGhlIGV4ZWN1dG9yIG91dGJvdW5kIHNlbmRzIHJ1biB0aHJvdWdoLiBUaGUgcGx1Z2luIGNhbGxzIHRoaXMgYXRcbiAqIHNldHVwIHdpdGggaXRzIG93biBgZXhlY3V0ZSgpYDsgYSBzZWNvbmQgY2FsbCByZXBsYWNlcyB0aGUgcHJldmlvdXMgb25lLCBzb1xuICogYSByZS1yZWdpc3RlcmVkIHBsdWdpbiBkb2VzIG5vdCBsZWF2ZSB0aGUgdG9vbHMgYm91bmQgdG8gYSBkZWFkIGluc3RhbmNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0RW1haWxFeGVjdXRvcihleGVjdXRlOiBFbWFpbEV4ZWN1dG9yKTogdm9pZCB7XG4gIGdldEVtYWlsUnVudGltZSgpLmV4ZWN1dGUgPSBleGVjdXRlO1xufVxuXG4vKipcbiAqIERyb3AgdGhlIG1lbW9pemVkIHJ1bnRpbWUsIGNsb3NpbmcgdGhlIFNNVFAgY29ubmVjdGlvbiBwb29sLCBzbyB0aGUgbmV4dFxuICoge0BsaW5rIGdldEVtYWlsUnVudGltZX0gcmVidWlsZHMgaXQgZnJvbSBmcmVzaCBjb25maWcgYW5kIHN0b3BzIGNhbGxpbmdcbiAqIHRocm91Z2ggYSB0b3JuLWRvd24gcGx1Z2luJ3MgYGV4ZWN1dGUoKWAuIElkZW1wb3RlbnQsIGFuZCB0aGUgcGx1Z2luJ3NcbiAqIGBzaHV0ZG93bigpYCBob29rLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzZXRFbWFpbFJ1bnRpbWUoKTogdm9pZCB7XG4gIHJ1bnRpbWU/LnRyYW5zcG9ydGVyPy5jbG9zZSgpO1xuICBydW50aW1lID0gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJ1biBvbmUgbm9uLWlkZW1wb3RlbnQgd3JpdGUgdGhyb3VnaCB0aGUgc2hhcmVkIGV4ZWN1dG9yIGFuZCB1bndyYXAgaXQuXG4gKlxuICogYGV4ZWN1dGUoKWAgbmV2ZXIgdGhyb3dzLCBzbyBhIGZhaWxlZCBzZW5kIGFycml2ZXMgYXMgYHsgb2s6IGZhbHNlIH1gIHdpdGggYVxuICogc3RhdHVzIHRoZSBpbnRlcmNlcHRvcnMgYWxyZWFkeSBzYW5pdGl6ZWQ7IGl0IGlzIGxvZ2dlZCBoZXJlIGFuZCByZS1yYWlzZWRcbiAqIGFzIGEgc3RhYmxlIHtAbGluayBFeGVjdXRpb25FcnJvcn0gc28gYW4gdXBzdHJlYW0gbWVzc2FnZSBuZXZlciBiZWNvbWVzIHRoZVxuICogY2FsbGVyJ3MgZXJyb3IgdGV4dC4gYHNpZ25hbGAgaXMgdGhlIGNhbGxlcidzIG93biBjYW5jZWxsYXRpb24gKGFuIGFnZW50XG4gKiBydW4sIGEgcmVxdWVzdCB0ZWFyZG93bik7IGl0IGlzIG1lcmdlZCB3aXRoIHRoZSBzaWduYWwgdGhlIHRpbWVvdXRcbiAqIGludGVyY2VwdG9yIHN1cHBsaWVzIHNvIGVpdGhlciBvbmUgdW53aW5kcyB0aGUgSS9PLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXhlY3V0ZVdyaXRlPFQ+KFxuICBvcGVyYXRpb246IHN0cmluZyxcbiAgc2V0dGluZ3M6IEVtYWlsRXhlY3V0aW9uU2V0dGluZ3MsXG4gIGZuOiAoc2lnbmFsPzogQWJvcnRTaWduYWwpID0+IFByb21pc2U8VD4sXG4gIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuKTogUHJvbWlzZTxUPiB7XG4gIGNvbnN0IHsgZXhlY3V0ZSB9ID0gZ2V0RW1haWxSdW50aW1lKCk7XG4gIHJldHVybiBleGVjdXRpb24ucnVuKHtcbiAgICBvcGVyYXRpb24sXG4gICAgc2V0dGluZ3MsXG4gICAgZXhlY3V0ZSxcbiAgICBmbixcbiAgICBzaWduYWwsXG4gICAgY2FuY2VsZWQ6IEV4ZWN1dGlvbkVycm9yLmNhbmNlbGVkLFxuICAgIGZhaWxlZDogKGZhaWx1cmUpID0+IHtcbiAgICAgIGxvZ2dlci53YXJuKFwiZXhlY3V0aW9uLWZhaWxlZFwiLCB7XG4gICAgICAgIG9wZXJhdGlvbjogZmFpbHVyZS5vcGVyYXRpb24sXG4gICAgICAgIHN0YXR1czogZmFpbHVyZS5zdGF0dXMsXG4gICAgICAgIGVycm9yOiBmYWlsdXJlLm1lc3NhZ2UsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBuZXcgRXhlY3V0aW9uRXJyb3IoYGVtYWlsOiAke2ZhaWx1cmUub3BlcmF0aW9ufSBmYWlsZWRgLCB7XG4gICAgICAgIGNvbnRleHQ6IHsgb3BlcmF0aW9uOiBmYWlsdXJlLm9wZXJhdGlvbiwgc3RhdHVzOiBmYWlsdXJlLnN0YXR1cyB9LFxuICAgICAgfSk7XG4gICAgfSxcbiAgfSk7XG59XG5cbi8qKlxuICogT3BlbiBhbmQgdGVhciBkb3duIG9uZSBTTVRQIGNvbm5lY3Rpb24gdG8gcHJvdmUgdGhlIGhvc3QsIHBvcnQsIGFuZFxuICogY3JlZGVudGlhbHMgd29yay4gQ2FsbGVkIGF0IHBsdWdpbiBzZXR1cCBzbyBhIGJhZCByZWxheSBzaG93cyB1cCBpbiB0aGVcbiAqIGJvb3QgbG9ncyByYXRoZXIgdGhhbiBvbiB0aGUgZmlyc3QgYXBwcm92ZWQgc2VuZC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHZlcmlmeUVtYWlsVHJhbnNwb3J0KFxuICB0cmFuc3BvcnRlcjogVHJhbnNwb3J0ZXIgfCB1bmRlZmluZWQsXG4gIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmICghdHJhbnNwb3J0ZXIpIHtcbiAgICB0aHJvdyBDb25maWd1cmF0aW9uRXJyb3IuaW52YWxpZENvbm5lY3Rpb24oXG4gICAgICBcIlNNVFBcIixcbiAgICAgIFwiVGhlIHJ1bnRpbWUgcmVzb2x2ZWQgdG8gb3V0Ym94IG1vZGUsIHNvIHRoZXJlIGlzIG5vIHRyYW5zcG9ydCB0byB2ZXJpZnkuXCIsXG4gICAgKTtcbiAgfVxuICBhd2FpdCBhYm9ydGFibGUodHJhbnNwb3J0ZXIudmVyaWZ5KCksIHNpZ25hbCk7XG59XG5cbi8qKlxuICogU3RvcCBhd2FpdGluZyBgcHJvbWlzZWAgYXMgc29vbiBhcyBgc2lnbmFsYCBhYm9ydHMuIG5vZGVtYWlsZXIgZXhwb3NlcyBub1xuICogY2FuY2VsbGF0aW9uIGhvb2ssIHNvIHRoZSBTTVRQIGNvbnZlcnNhdGlvbiBpdHNlbGYgZmluaXNoZXMgb24gaXRzIG93blxuICogY29ubmVjdGlvbjsgd2hhdCB1bndpbmRzIGlzIHRoZSBjYWxsZXIgYW5kIGV2ZXJ5dGhpbmcgZG93bnN0cmVhbSBvZiBpdC5cbiAqL1xuZnVuY3Rpb24gYWJvcnRhYmxlPFQ+KHByb21pc2U6IFByb21pc2U8VD4sIHNpZ25hbDogQWJvcnRTaWduYWwgfCB1bmRlZmluZWQpOiBQcm9taXNlPFQ+IHtcbiAgaWYgKCFzaWduYWwpIHJldHVybiBwcm9taXNlO1xuICBzaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgLy8gVGhlIGxpc3RlbmVyIGlzIGRldGFjaGVkIG9uY2UgdGhlIHJhY2Ugc2V0dGxlcyBzbyBhIGxvbmctbGl2ZWQgcnVuIHNpZ25hbFxuICAvLyBkb2VzIG5vdCBhY2N1bXVsYXRlIG9uZSBwZXIgc2VuZC5cbiAgY29uc3QgbGlzdGVuZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIGNvbnN0IGFib3J0ZWQgPSBuZXcgUHJvbWlzZTxuZXZlcj4oKF8sIHJlamVjdCkgPT4ge1xuICAgIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgKCkgPT4gcmVqZWN0KHNpZ25hbC5yZWFzb24pLCB7XG4gICAgICBvbmNlOiB0cnVlLFxuICAgICAgc2lnbmFsOiBsaXN0ZW5lci5zaWduYWwsXG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gUHJvbWlzZS5yYWNlKFtwcm9taXNlLCBhYm9ydGVkXSkuZmluYWxseSgoKSA9PiBsaXN0ZW5lci5hYm9ydCgpKTtcbn1cblxuLyoqIFRoZSBjb21tYS1qb2luZWQgcmVjaXBpZW50IHN0cmluZyBlY2hvZWQgYmFjayBpbiB7QGxpbmsgRW1haWxSZXN1bHR9LiAqL1xuZnVuY3Rpb24gcmVjaXBpZW50RWNobyh0bzogc3RyaW5nW10pOiBzdHJpbmcge1xuICByZXR1cm4gdG8uam9pbihcIiwgXCIpO1xufVxuXG4vKipcbiAqIE5vZGUgYnVmZmVyIGVuY29kaW5ncyBhIHdpcmUgYXR0YWNobWVudCBtYXkgbmFtZSBmb3IgaXRzIGlubGluZSBgY29udGVudGAuXG4gKiBBbnl0aGluZyBlbHNlIGlzIG1lYXN1cmVkIGFzIFVURi04LCB3aGljaCBvdmVyLWNvdW50cyByYXRoZXIgdGhhbiBsZXR0aW5nXG4gKiBhbiB1bnJlY29nbml6ZWQgZW5jb2Rpbmcgc2xpcCBwYXN0IHRoZSBzaXplIGNhcC5cbiAqL1xuY29uc3QgQ09OVEVOVF9FTkNPRElOR1M6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KFtcbiAgXCJhc2NpaVwiLFxuICBcImJhc2U2NFwiLFxuICBcImJhc2U2NHVybFwiLFxuICBcImJpbmFyeVwiLFxuICBcImhleFwiLFxuICBcImxhdGluMVwiLFxuICBcInVjczJcIixcbiAgXCJ1Y3MtMlwiLFxuICBcInV0ZjhcIixcbiAgXCJ1dGYtOFwiLFxuICBcInV0ZjE2bGVcIixcbiAgXCJ1dGYtMTZsZVwiLFxuXSk7XG5cbi8qKlxuICogRGVjb2RlZCBieXRlIHNpemUgb2Ygb25lIGF0dGFjaG1lbnQncyBpbmxpbmUgY29udGVudC4gQSBgcGF0aGAgYXR0YWNobWVudFxuICogY29udHJpYnV0ZXMgbm90aGluZzogbm9kZW1haWxlciBzdHJlYW1zIGl0LCBzbyBpdHMgYnl0ZXMgbmV2ZXIgc2l0IGluIHRoaXNcbiAqIHByb2Nlc3MgYW5kIGNhbm5vdCBiZSBtZWFzdXJlZCBoZXJlLlxuICovXG5mdW5jdGlvbiBhdHRhY2htZW50Qnl0ZXMoYXR0YWNobWVudDogRW1haWxBdHRhY2htZW50KTogbnVtYmVyIHtcbiAgY29uc3QgeyBjb250ZW50LCBlbmNvZGluZyB9ID0gYXR0YWNobWVudDtcbiAgaWYgKGNvbnRlbnQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIDA7XG4gIGNvbnN0IGRlY2xhcmVkID0gZW5jb2Rpbmc/LnRvTG93ZXJDYXNlKCk7XG4gIGNvbnN0IHJlc29sdmVkID1cbiAgICBkZWNsYXJlZCAmJiBDT05URU5UX0VOQ09ESU5HUy5oYXMoZGVjbGFyZWQpID8gKGRlY2xhcmVkIGFzIEJ1ZmZlckVuY29kaW5nKSA6IFwidXRmOFwiO1xuICByZXR1cm4gQnVmZmVyLmJ5dGVMZW5ndGgoY29udGVudCwgcmVzb2x2ZWQpO1xufVxuXG4vKipcbiAqIFJlamVjdCBhIG1lc3NhZ2Ugd2hvc2UgYm9keSBvciBhdHRhY2htZW50cyBleGNlZWQgdGhlIHBsdWdpbidzIGNhcHMuIFRoZVxuICogYm9keSBhbmQgYXR0YWNobWVudCBsaXN0IGFycml2ZSBmcm9tIGEgbW9kZWwsIHNvIHRoZXkgYXJlIHVuYm91bmRlZCB1bnRpbFxuICogc29tZXRoaW5nIGJvdW5kcyB0aGVtOyBtb3N0IFNNVFAgcmVsYXlzIGFsc28gcmVqZWN0IGFuIG92ZXJzaXplZCBtZXNzYWdlXG4gKiBvbmx5IGFmdGVyIHRoZSB3aG9sZSBwYXlsb2FkIGhhcyBiZWVuIHVwbG9hZGVkLlxuICovXG5mdW5jdGlvbiBhc3NlcnRNZXNzYWdlV2l0aGluQ2FwcyhtZXNzYWdlOiBFbWFpbE1lc3NhZ2UpOiB2b2lkIHtcbiAgaWYgKG1lc3NhZ2UuYm9keS5sZW5ndGggPiBNQVhfQk9EWV9DSEFSUykge1xuICAgIHRocm93IFZhbGlkYXRpb25FcnJvci5pbnZhbGlkVmFsdWUoXG4gICAgICBcImJvZHlcIixcbiAgICAgIG1lc3NhZ2UuYm9keS5sZW5ndGgsXG4gICAgICBgYXQgbW9zdCAke01BWF9CT0RZX0NIQVJTfSBjaGFyYWN0ZXJzYCxcbiAgICApO1xuICB9XG4gIGNvbnN0IGF0dGFjaG1lbnRzID0gbWVzc2FnZS5hdHRhY2htZW50cyA/PyBbXTtcbiAgaWYgKGF0dGFjaG1lbnRzLmxlbmd0aCA+IE1BWF9BVFRBQ0hNRU5UX0NPVU5UKSB7XG4gICAgdGhyb3cgVmFsaWRhdGlvbkVycm9yLmludmFsaWRWYWx1ZShcbiAgICAgIFwiYXR0YWNobWVudHNcIixcbiAgICAgIGF0dGFjaG1lbnRzLmxlbmd0aCxcbiAgICAgIGBhdCBtb3N0ICR7TUFYX0FUVEFDSE1FTlRfQ09VTlR9IGZpbGVzYCxcbiAgICApO1xuICB9XG4gIGxldCB0b3RhbCA9IDA7XG4gIGZvciAoY29uc3QgYXR0YWNobWVudCBvZiBhdHRhY2htZW50cykge1xuICAgIGNvbnN0IGJ5dGVzID0gYXR0YWNobWVudEJ5dGVzKGF0dGFjaG1lbnQpO1xuICAgIGlmIChieXRlcyA+IE1BWF9BVFRBQ0hNRU5UX0JZVEVTKSB7XG4gICAgICB0aHJvdyBWYWxpZGF0aW9uRXJyb3IuaW52YWxpZFZhbHVlKFxuICAgICAgICBcImF0dGFjaG1lbnRzW10uY29udGVudFwiLFxuICAgICAgICBieXRlcyxcbiAgICAgICAgYGF0IG1vc3QgJHtNQVhfQVRUQUNITUVOVF9CWVRFU30gYnl0ZXMgcGVyIGZpbGVgLFxuICAgICAgKTtcbiAgICB9XG4gICAgdG90YWwgKz0gYnl0ZXM7XG4gIH1cbiAgaWYgKHRvdGFsID4gTUFYX0FUVEFDSE1FTlRTX1RPVEFMX0JZVEVTKSB7XG4gICAgdGhyb3cgVmFsaWRhdGlvbkVycm9yLmludmFsaWRWYWx1ZShcbiAgICAgIFwiYXR0YWNobWVudHNcIixcbiAgICAgIHRvdGFsLFxuICAgICAgYGF0IG1vc3QgJHtNQVhfQVRUQUNITUVOVFNfVE9UQUxfQllURVN9IGJ5dGVzIGFjcm9zcyBhbGwgZmlsZXNgLFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBNYXAgdGhlIHdpcmUtZm9ybWF0IHtAbGluayBFbWFpbEF0dGFjaG1lbnR9cyBvbnRvIG5vZGVtYWlsZXInc1xuICogYXR0YWNobWVudCBzaGFwZSwgZHJvcHBpbmcgdW5zZXQgb3B0aW9uYWwga2V5cyBzbyBub2RlbWFpbGVyIGFwcGxpZXNcbiAqIGl0cyBvd24gZGVmYXVsdHMgKHV0Zi04IGVuY29kaW5nLCBmaWxlbmFtZS1pbmZlcnJlZCBjb250ZW50IHR5cGUpLiBUaGVcbiAqIHdpcmUgZmllbGRzIGFyZSBhIGRlbGliZXJhdGUgc3Vic2V0IG9mIG5vZGVtYWlsZXIncywgc28gdGhpcyBpcyBhXG4gKiBzdHJhaWdodCBzdHJ1Y3R1cmFsIHBhc3MtdGhyb3VnaC5cbiAqL1xuZnVuY3Rpb24gdG9NYWlsQXR0YWNobWVudHMoXG4gIGF0dGFjaG1lbnRzOiBFbWFpbEF0dGFjaG1lbnRbXSB8IHVuZGVmaW5lZCxcbik6IFNlbmRNYWlsT3B0aW9uc1tcImF0dGFjaG1lbnRzXCJdIHtcbiAgaWYgKCFhdHRhY2htZW50cyB8fCBhdHRhY2htZW50cy5sZW5ndGggPT09IDApIHJldHVybiB1bmRlZmluZWQ7XG4gIHJldHVybiBhdHRhY2htZW50cy5tYXAoKGF0dCkgPT4gKHtcbiAgICBmaWxlbmFtZTogYXR0LmZpbGVuYW1lLFxuICAgIC4uLihhdHQuY29udGVudCAhPT0gdW5kZWZpbmVkID8geyBjb250ZW50OiBhdHQuY29udGVudCB9IDoge30pLFxuICAgIC4uLihhdHQuZW5jb2RpbmcgIT09IHVuZGVmaW5lZCA/IHsgZW5jb2Rpbmc6IGF0dC5lbmNvZGluZyB9IDoge30pLFxuICAgIC4uLihhdHQucGF0aCAhPT0gdW5kZWZpbmVkID8geyBwYXRoOiBhdHQucGF0aCB9IDoge30pLFxuICAgIC4uLihhdHQuY29udGVudFR5cGUgIT09IHVuZGVmaW5lZCA/IHsgY29udGVudFR5cGU6IGF0dC5jb250ZW50VHlwZSB9IDoge30pLFxuICB9KSk7XG59XG5cbi8qKlxuICogSGFuZCBvbmUgYWxyZWFkeS12YWxpZGF0ZWQgbWVzc2FnZSB0byBTTVRQLCBvciB3cml0ZSBpdCB0byB0aGUgb3V0Ym94IHdoZW5cbiAqIG5vIGNyZWRlbnRpYWxzIGFyZSBjb25maWd1cmVkLiBUaGUgaGFsZiBvZiBhIHNlbmQgdGhhdCBwZXJmb3JtcyBJL08sIHNvIGl0XG4gKiBpcyB3aGF0IHJ1bnMgaW5zaWRlIHRoZSBpbnRlcmNlcHRvciBjaGFpbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGlzcGF0Y2goXG4gIG1lc3NhZ2U6IEVtYWlsTWVzc2FnZSxcbiAgZnJvbTogc3RyaW5nLFxuICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgb3B0aW9ucz86IFNlbmRFbWFpbE9wdGlvbnMsXG4pOiBQcm9taXNlPEVtYWlsUmVzdWx0PiB7XG4gIGNvbnN0IHsgY29uZmlnLCB0cmFuc3BvcnRlciB9ID0gZ2V0RW1haWxSdW50aW1lKCk7XG4gIGNvbnN0IHJlY2lwaWVudCA9IHJlY2lwaWVudEVjaG8obWVzc2FnZS50byk7XG4gIHNpZ25hbD8udGhyb3dJZkFib3J0ZWQoKTtcblxuICBpZiAoY29uZmlnLm1vZGUgPT09IFwiZmlsZVwiKSB7XG4gICAgY29uc3QgcGF0aCA9IGF3YWl0IHdyaXRlT3V0Ym94RW1haWwobWVzc2FnZSwgZnJvbSwgY29uZmlnLm91dERpciwgY29uZmlnLmJyYW5kLCBvcHRpb25zKTtcbiAgICByZXR1cm4geyBzZW50OiB0cnVlLCByZWNpcGllbnQsIGZyb20sIG1lc3NhZ2VJZDogcGF0aCB9O1xuICB9XG5cbiAgaWYgKCF0cmFuc3BvcnRlcikge1xuICAgIHRocm93IENvbmZpZ3VyYXRpb25FcnJvci5pbnZhbGlkQ29ubmVjdGlvbihcbiAgICAgIFwiU01UUFwiLFxuICAgICAgXCJObyB0cmFuc3BvcnQgd2FzIGJ1aWx0IGZvciB0aGUgcmVzb2x2ZWQgY29uZmlndXJhdGlvbi5cIixcbiAgICApO1xuICB9XG4gIGNvbnN0IGF0dGFjaG1lbnRzID0gdG9NYWlsQXR0YWNobWVudHMobWVzc2FnZS5hdHRhY2htZW50cyk7XG4gIGNvbnN0IHJlbmRlcmVkID0gYXdhaXQgcmVuZGVyRW1haWwoe1xuICAgIHN1YmplY3Q6IG1lc3NhZ2Uuc3ViamVjdCxcbiAgICBib2R5OiBtZXNzYWdlLmJvZHksXG4gICAgYnJhbmQ6IGNvbmZpZy5icmFuZCxcbiAgICAuLi5vYmplY3Qub3B0aW9uYWwoXCJ0cmFpbGVyXCIsIG9wdGlvbnM/LnRyYWlsZXIpLFxuICB9KTtcbiAgY29uc3QgaW5mbyA9IGF3YWl0IGFib3J0YWJsZShcbiAgICB0cmFuc3BvcnRlci5zZW5kTWFpbCh7XG4gICAgICBmcm9tLFxuICAgICAgdG86IG1lc3NhZ2UudG8sXG4gICAgICBzdWJqZWN0OiBtZXNzYWdlLnN1YmplY3QsXG4gICAgICB0ZXh0OiByZW5kZXJlZC50ZXh0LFxuICAgICAgaHRtbDogcmVuZGVyZWQuaHRtbCxcbiAgICAgIC4uLihtZXNzYWdlLmNjICYmIG1lc3NhZ2UuY2MubGVuZ3RoID4gMCA/IHsgY2M6IG1lc3NhZ2UuY2MgfSA6IHt9KSxcbiAgICAgIC4uLihtZXNzYWdlLmJjYyAmJiBtZXNzYWdlLmJjYy5sZW5ndGggPiAwID8geyBiY2M6IG1lc3NhZ2UuYmNjIH0gOiB7fSksXG4gICAgICAuLi4oYXR0YWNobWVudHMgPyB7IGF0dGFjaG1lbnRzIH0gOiB7fSksXG4gICAgfSksXG4gICAgc2lnbmFsLFxuICApO1xuICByZXR1cm4ge1xuICAgIHNlbnQ6IHRydWUsXG4gICAgcmVjaXBpZW50LFxuICAgIGZyb20sXG4gICAgLi4uKGluZm8ubWVzc2FnZUlkID8geyBtZXNzYWdlSWQ6IGluZm8ubWVzc2FnZUlkIH0gOiB7fSksXG4gIH07XG59XG5cbi8qKlxuICogRGVsaXZlcnktdGltZSBvcHRpb25zIHRoYXQgYXJlIE5PVCBwYXJ0IG9mIHRoZSBtZXNzYWdlIGEgbW9kZWwgY29tcG9zZXMuXG4gKlxuICogRGVsaWJlcmF0ZWx5IHNlcGFyYXRlIGZyb20ge0BsaW5rIEVtYWlsTWVzc2FnZX06IHRoYXQgc2NoZW1hIGlzIHRoZSBhZ2VudFxuICogdG9vbCdzIGlucHV0LCBzbyBhbnl0aGluZyBhZGRlZCB0byBpdCBiZWNvbWVzIGEgZmllbGQgYSBtb2RlbCBjYW4gc2V0LiBBXG4gKiB0cmFpbGVyIGlzIGEgcHJvcGVydHkgb2YgaG93IHRoZSBtZXNzYWdlIGlzIERFTElWRVJFRCAoaXQgbXVzdCBiZSB0aGUgZmluYWxcbiAqIGxpbmUsIGFuZCBpdHMgY29udGVudCBpcyBkZXJpdmVkIGZyb20gdGhlIGRlcGxveW1lbnQncyBvd24gZG9tYWluKSwgc28gaXQgaXNcbiAqIHRoZSBjYWxsZXIncyB0byBzdXBwbHksIG5ldmVyIHRoZSBtb2RlbCdzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNlbmRFbWFpbE9wdGlvbnMge1xuICAvKipcbiAgICogQSBtYWNoaW5lLXJlYWQgZmluYWwgbGluZSwgYWZ0ZXIgdGhlIGJyYW5kZWQgZm9vdGVyIC0gQXBwbGUncyBkb21haW4tYm91bmRcbiAgICogb25lLXRpbWUtY29kZSBBdXRvRmlsbCB0cmFpbGVyLiBCdWlsZCBpdCB3aXRoXG4gICAqIGBzaGFyZWRFbWFpbFRlbXBsYXRlLmF1dG9maWxsVHJhaWxlcihkb21haW4sIGNvZGUpYC5cbiAgICovXG4gIHRyYWlsZXI/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogU2VuZCAoU01UUCBtb2RlKSBvciBwZXJzaXN0IChmaWxlL291dGJveCBtb2RlKSBvbmUgbWVzc2FnZSBmcm9tIHRoZVxuICogcmVzb2x2ZWQgYGZyb21gIGFkZHJlc3MuIGB0b2AgKGFuZCBvcHRpb25hbCBgY2NgIC8gYGJjY2ApIGVhY2ggYWNjZXB0XG4gKiBvbmUgb3IgbW9yZSBhZGRyZXNzZXMsIGFuZCBgYXR0YWNobWVudHNgIGFyZSBmb3J3YXJkZWQgYXMgZmlsZXMuIFRoZVxuICogYm9keSBpcyByZW5kZXJlZCBieSBSZWFjdCBFbWFpbCBpbnRvIG1hdGNoaW5nIHBsYWluLXRleHQgYW5kIEhUTUwgTUlNRVxuICogYWx0ZXJuYXRpdmVzLCBhbmQgdGhlIG91dGJveCBlbWJlZHMgdGhlXG4gKiByZW5kZXJlZCBIVE1MIGluIGEgZG9jdW1lbnQuIEluIGZpbGUgbW9kZSB0aGUgcmV0dXJuZWQgYG1lc3NhZ2VJZGAgaXNcbiAqIHRoZSBwYXRoIHdyaXR0ZW4uIFRocm93cyB3aGVuIGB0b2AgY2FycmllcyBubyByZWNpcGllbnQsIHdoZW4gdGhlIGJvZHlcbiAqIG9yIGF0dGFjaG1lbnRzIGV4Y2VlZCB0aGUgcGx1Z2luJ3MgY2Fwcywgb3Igd2hlbiBgZnJvbWAgaXMgbm90IHBlcm1pdHRlZFxuICogYnkgdGhlIGVmZmVjdGl2ZSBzZW5kZXIgYWxsb3ctbGlzdC5cbiAqXG4gKiBUaGUgcmVjaXBpZW50LCBjYXAsIGFuZCBzZW5kZXIgY2hlY2tzIHJ1biBiZWZvcmUgdGhlIGludGVyY2VwdG9yIGNoYWluIHNvXG4gKiB0aGVpciBzcGVjaWZpYyBzdGF0dXMgYW5kIGFjdGlvbmFibGUgbWVzc2FnZSByZWFjaCB0aGUgY2FsbGVyIGluc3RlYWQgb2ZcbiAqIHRoZSBjaGFpbidzIHN0YWJsZSBmYWlsdXJlIHRleHQuIGBzaWduYWxgIGNhbmNlbHMgdGhlIHNlbmQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kRW1haWwoXG4gIG1lc3NhZ2U6IEVtYWlsTWVzc2FnZSxcbiAgZnJvbTogc3RyaW5nLFxuICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgb3B0aW9ucz86IFNlbmRFbWFpbE9wdGlvbnMsXG4pOiBQcm9taXNlPEVtYWlsUmVzdWx0PiB7XG4gIGlmIChtZXNzYWdlLnRvLmxlbmd0aCA9PT0gMCkge1xuICAgIHRocm93IFZhbGlkYXRpb25FcnJvci5taXNzaW5nRmllbGQoXCJ0b1wiKTtcbiAgfVxuICBhc3NlcnRNZXNzYWdlV2l0aGluQ2FwcyhtZXNzYWdlKTtcbiAgYXNzZXJ0U2VuZGVyQWxsb3dlZChmcm9tLCBnZXRFbWFpbFJ1bnRpbWUoKS5jb25maWcuYWxsb3dlZFNlbmRlcnMpO1xuICByZXR1cm4gZXhlY3V0ZVdyaXRlKFxuICAgIFwic2VuZFwiLFxuICAgIEVNQUlMX1NFTkRfU0VUVElOR1MsXG4gICAgKGV4ZWN1dGVTaWduYWwpID0+IGRpc3BhdGNoKG1lc3NhZ2UsIGZyb20sIGV4ZWN1dGVTaWduYWwsIG9wdGlvbnMpLFxuICAgIHNpZ25hbCxcbiAgKTtcbn1cbiJdfQ==
301
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNwb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3RyYW5zcG9ydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUVILE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsY0FBYyxFQUNkLGVBQWUsR0FFaEIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRXhELE9BQU8sVUFBc0QsTUFBTSxZQUFZLENBQUM7QUFDaEYsT0FBTyxFQUFFLGtCQUFrQixFQUFvRCxNQUFNLGFBQWEsQ0FBQztBQUNuRyxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLG9CQUFvQixFQUNwQixvQkFBb0IsRUFDcEIsMkJBQTJCLEVBQzNCLGNBQWMsR0FFZixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQy9DLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVsRCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7QUFvQjdDOzs7O0dBSUc7QUFDSCxNQUFNLGFBQWEsR0FBRyxTQUFTLENBQUMsY0FBYyxFQUEwQixDQUFDO0FBRXpFLElBQUksT0FBaUMsQ0FBQztBQUV0Qzs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsU0FBNkI7SUFDM0QsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2IsTUFBTSxNQUFNLEdBQUcsa0JBQWtCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDN0MsT0FBTyxHQUFHO1lBQ1IsTUFBTTtZQUNOLE9BQU8sRUFBRSxhQUFhO1lBQ3RCLEdBQUcsQ0FBQyxNQUFN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QyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3RFLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUN4QyxDQUFDLEVBQ0YsTUFBTSxDQUNQLENBQUM7SUFDRixPQUFPO1FBQ0wsSUFBSSxFQUFFLElBQUk7UUFDVixTQUFTO1FBQ1QsSUFBSTtRQUNKLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUN6RCxDQUFDO0FBQ0osQ0FBQztBQThCRDs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsU0FBUyxDQUM3QixPQUFxQixFQUNyQixJQUFZLEVBQ1osTUFBb0IsRUFDcEIsT0FBMEI7SUFFMUIsSUFBSSxPQUFPLENBQUMsRUFBRSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUM1QixNQUFNLGVBQWUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUNELHVCQUF1QixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pDLG1CQUFtQixDQUFDLElBQUksRUFBRSxlQUFlLEVBQUUsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDbkUsT0FBTyxZQUFZLENBQ2pCLE1BQU0sRUFDTixtQkFBbUIsRUFDbkIsQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxPQUFPLENBQUMsRUFDbEUsTUFBTSxDQUNQLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgZW1haWwgcnVudGltZTogYSBsYXppbHktYnVpbHQsIHByb2Nlc3Mtd2lkZSBkaXNwYXRjaGVyIHBsdXMgaXRzXG4gKiByZXNvbHZlZCBjb25maWcsIGFuZCB7QGxpbmsgc2VuZEVtYWlsfSB3aGljaCBzZW5kcyBvbmVcbiAqIHtAbGluayBFbWFpbE1lc3NhZ2V9IHRocm91Z2ggaXQuIEluIFNNVFAgbW9kZSB0aGUgcnVudGltZSBob2xkcyBhXG4gKiBtZW1vaXplZCBub2RlbWFpbGVyIHRyYW5zcG9ydCAoc2hhcmVkIGJ5IHRoZSBwbHVnaW4ncyBzZXR1cCBhbmQgdGhlXG4gKiBhZ2VudCB0b29sLCBzbyB0aGV5IHJldXNlIG9uZSBjb25uZWN0aW9uIHBvb2wpOyBpbiBmaWxlL291dGJveCBtb2RlIGl0XG4gKiBob2xkcyBubyB0cmFuc3BvcnQgYW5kIHtAbGluayBzZW5kRW1haWx9IHdyaXRlcyBIVE1MIHRvIGRpc2sgaW5zdGVhZC5cbiAqIFRoZSBmaXJzdCBjYWxsZXIgKG5vcm1hbGx5IHRoZSBwbHVnaW4gYXQgc2V0dXApIHByaW1lcyBpdCB3aXRoIHRoZVxuICogcGx1Z2luJ3MgY29uZmlnOyBsYXRlciBjYWxsZXJzIHJldXNlIGl0LlxuICpcbiAqIFRoZSBydW50aW1lIGFsc28gY2FycmllcyB0aGUge0BsaW5rIEVtYWlsRXhlY3V0b3J9IGV2ZXJ5IG91dGJvdW5kIHNlbmQgcnVuc1xuICogdGhyb3VnaC4gVGhlIHBsdWdpbiBpbnN0YWxscyBpdHMgb3duIGBleGVjdXRlKClgIHRoZXJlIGF0IHNldHVwLCB3aGljaCBpc1xuICogaG93IHRoZSBNYXN0cmEgdG9vbCAtIGEgcGxhaW4gZnVuY3Rpb24gd2l0aCBubyBwbHVnaW4gaW5zdGFuY2UgaW4gc2NvcGUgLVxuICogc3RpbGwgZ2V0cyBBcHBLaXQncyByZXRyeSAvIHRpbWVvdXQgLyB0ZWxlbWV0cnkgY2hhaW4uIFdpdGhvdXQgYSByZWdpc3RlcmVkXG4gKiBwbHVnaW4gKGEgZGlyZWN0IGNhbGwgZnJvbSBhIHNjcmlwdCBvciBhIHRlc3QpIHRoZSBzZW5kIHN0aWxsIHJ1bnMsIGp1c3RcbiAqIHdpdGhvdXQgaW50ZXJjZXB0b3JzLlxuICpcbiAqIEV2ZXJ5IGVudHJ5IHBvaW50IHRha2VzIGFuIG9wdGlvbmFsIHtAbGluayBBYm9ydFNpZ25hbH0gc28gdGhlIHBsdWdpbidzXG4gKiBgZXhlY3V0ZSgpYCB0aW1lb3V0IGFuZCBhIGNsaWVudCBkaXNjb25uZWN0IGJvdGggc3RvcCB0aGUgY2FsbGVyIHdhaXRpbmdcbiAqIG9uIFNNVFAuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7XG4gIENvbmZpZ3VyYXRpb25FcnJvcixcbiAgRXhlY3V0aW9uRXJyb3IsXG4gIFZhbGlkYXRpb25FcnJvcixcbiAgdHlwZSBFeGVjdXRpb25SZXN1bHQsXG59IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGV4ZWN1dGlvbiwgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHsgRW1haWxBdHRhY2htZW50LCBFbWFpbE1lc3NhZ2UsIEVtYWlsUmVzdWx0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWVtYWlsXCI7XG5pbXBvcnQgbm9kZW1haWxlciwgeyB0eXBlIFNlbmRNYWlsT3B0aW9ucywgdHlwZSBUcmFuc3BvcnRlciB9IGZyb20gXCJub2RlbWFpbGVyXCI7XG5pbXBvcnQgeyByZXNvbHZlRW1haWxDb25maWcsIHR5cGUgRW1haWxQbHVnaW5Db25maWcsIHR5cGUgUmVzb2x2ZWRFbWFpbENvbmZpZyB9IGZyb20gXCIuL2NvbmZpZy50c1wiO1xuaW1wb3J0IHtcbiAgRU1BSUxfU0VORF9TRVRUSU5HUyxcbiAgTUFYX0FUVEFDSE1FTlRfQllURVMsXG4gIE1BWF9BVFRBQ0hNRU5UX0NPVU5ULFxuICBNQVhfQVRUQUNITUVOVFNfVE9UQUxfQllURVMsXG4gIE1BWF9CT0RZX0NIQVJTLFxuICB0eXBlIEVtYWlsRXhlY3V0aW9uU2V0dGluZ3MsXG59IGZyb20gXCIuL2RlZmF1bHRzLnRzXCI7XG5pbXBvcnQgeyByZW5kZXJFbWFpbCB9IGZyb20gXCIuL2VtYWlsLWh0bWwudHNcIjtcbmltcG9ydCB7IHdyaXRlT3V0Ym94RW1haWwgfSBmcm9tIFwiLi9vdXRib3gudHNcIjtcbmltcG9ydCB7IGFzc2VydFNlbmRlckFsbG93ZWQgfSBmcm9tIFwiLi9zZW5kZXIudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImVtYWlsL3RyYW5zcG9ydFwiKTtcblxuLyoqXG4gKiBSdW5zIG9uZSBvdXRib3VuZCBzZW5kIHRocm91Z2ggQXBwS2l0J3MgaW50ZXJjZXB0b3IgY2hhaW4uIE1hdGNoZXNcbiAqIGBQbHVnaW4uZXhlY3V0ZSgpYCwgd2hpY2ggbmV2ZXIgdGhyb3dzOiBhIGZhaWx1cmUgY29tZXMgYmFjayBhc1xuICogYHsgb2s6IGZhbHNlIH1gLlxuICovXG5leHBvcnQgdHlwZSBFbWFpbEV4ZWN1dG9yID0gPFQ+KFxuICBmbjogKHNpZ25hbD86IEFib3J0U2lnbmFsKSA9PiBQcm9taXNlPFQ+LFxuICBzZXR0aW5nczogRW1haWxFeGVjdXRpb25TZXR0aW5ncyxcbikgPT4gUHJvbWlzZTxFeGVjdXRpb25SZXN1bHQ8VD4+O1xuXG4vKiogVGhlIHNoYXJlZCBkaXNwYXRjaGVyLCBpdHMgcmVzb2x2ZWQgY29uZmlnLCBhbmQgdGhlIHNlbmQgZXhlY3V0b3IuICovXG5leHBvcnQgaW50ZXJmYWNlIEVtYWlsUnVudGltZSB7XG4gIC8qKiBQcmVzZW50IG9ubHkgaW4gU01UUCBtb2RlLiAqL1xuICB0cmFuc3BvcnRlcj86IFRyYW5zcG9ydGVyO1xuICBjb25maWc6IFJlc29sdmVkRW1haWxDb25maWc7XG4gIGV4ZWN1dGU6IEVtYWlsRXhlY3V0b3I7XG59XG5cbi8qKlxuICogRXhlY3V0b3IgdXNlZCB1bnRpbCAob3IgdW5sZXNzKSB0aGUgcGx1Z2luIGluc3RhbGxzIGl0cyBvd246IHJ1biB0aGUgc2VuZFxuICogZGlyZWN0bHksIG1hcHBpbmcgYSB0aHJvdyBvbnRvIHRoZSBzYW1lIHtAbGluayBFeGVjdXRpb25SZXN1bHR9IHNoYXBlIHNvXG4gKiBjYWxsIHNpdGVzIGJyYW5jaCBvbiBgb2tgIGVpdGhlciB3YXkuXG4gKi9cbmNvbnN0IGRpcmVjdEV4ZWN1dGUgPSBleGVjdXRpb24uZGlyZWN0RXhlY3V0b3I8RW1haWxFeGVjdXRpb25TZXR0aW5ncz4oKTtcblxubGV0IHJ1bnRpbWU6IEVtYWlsUnVudGltZSB8IHVuZGVmaW5lZDtcblxuLyoqXG4gKiBSZXR1cm4gdGhlIHNoYXJlZCBydW50aW1lLCBidWlsZGluZyBpdCBvbiBmaXJzdCB1c2UgYnkgcmVzb2x2aW5nXG4gKiBgb3ZlcnJpZGVzYCBvdmVyIHRoZSBlbnZpcm9ubWVudCAoYFNNVFBfSE9TVGAsIGBTTVRQX1BPUlRgLFxuICogYFNNVFBfU0VDVVJFYCwgYFNNVFBfVVNFUmAsIGBTTVRQX1BBU1NXT1JEYCwgYEVNQUlMX0RPTUFJTmAsXG4gKiBgRU1BSUxfRlJPTWAsIGBFTUFJTF9BTExPV0VEX1NFTkRFUlNgLCBgRU1BSUxfU0VOREVSX1BPTElDWWAsXG4gKiBgRU1BSUxfT1VUQk9YX01PREVgLCBgRU1BSUxfT1VUQk9YX0RJUmApIHRocm91Z2hcbiAqIHtAbGluayByZXNvbHZlRW1haWxDb25maWd9LiBXaXRoIFNNVFAgY3JlZGVudGlhbHMgcHJlc2VudCBpdCBob2xkcyBhXG4gKiBub2RlbWFpbGVyIHRyYW5zcG9ydCBhbmQgaXRzIGNvbm5lY3Rpb24gcG9vbDsgb3RoZXJ3aXNlIGl0IGlzIGluXG4gKiBmaWxlL291dGJveCBtb2RlIGFuZCBob2xkcyBub25lLlxuICpcbiAqIGBvdmVycmlkZXNgIGlzIHJlYWQgb25seSBvbiB0aGUgY2FsbCB0aGF0IGJ1aWxkcyB0aGUgcnVudGltZSwgc28gcHJpbWUgaXRcbiAqIGZyb20gdGhlIHBsdWdpbidzIGNvbmZpZyBhdCBzZXR1cDsgbGF0ZXIgY2FsbGVycyAodGhlIHRvb2wncyBgZXhlY3V0ZWAsXG4gKiB0aGUgc2VuZGVyLW9wdGlvbnMgcm91dGUpIHBhc3Mgbm90aGluZyBhbmQgZ2V0IHRoZSBzYW1lIGluc3RhbmNlLiBUaHJvd3NcbiAqIHdoYXRldmVyIHtAbGluayByZXNvbHZlRW1haWxDb25maWd9IHRocm93cyBmb3IgYW4gdW51c2FibGUgY29uZmlndXJhdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEVtYWlsUnVudGltZShvdmVycmlkZXM/OiBFbWFpbFBsdWdpbkNvbmZpZyk6IEVtYWlsUnVudGltZSB7XG4gIGlmICghcnVudGltZSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHJlc29sdmVFbWFpbENvbmZpZyhvdmVycmlkZXMpO1xuICAgIHJ1bnRpbWUgPSB7XG4gICAgICBjb25maWcsXG4gICAgICBleGVjdXRlOiBkaXJlY3RFeGVjdXRlLFxuICAgICAgLi4uKGNvbmZpZy5tb2RlID09PSBcInNtdHBcIlxuICAgICAgICA/IHtcbiAgICAgICAgICAgIHRyYW5zcG9ydGVyOiBub2RlbWFpbGVyLmNyZWF0ZVRyYW5zcG9ydCh7XG4gICAgICAgICAgICAgIGhvc3Q6IGNvbmZpZy5ob3N0LFxuICAgICAgICAgICAgICBwb3J0OiBjb25maWcucG9ydCxcbiAgICAgICAgICAgICAgc2VjdXJlOiBjb25maWcuc2VjdXJlLFxuICAgICAgICAgICAgICBhdXRoOiBjb25maWcuYXV0aCxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB7fSksXG4gICAgfTtcbiAgfVxuICByZXR1cm4gcnVudGltZTtcbn1cblxuLyoqXG4gKiBJbnN0YWxsIHRoZSBleGVjdXRvciBvdXRib3VuZCBzZW5kcyBydW4gdGhyb3VnaC4gVGhlIHBsdWdpbiBjYWxscyB0aGlzIGF0XG4gKiBzZXR1cCB3aXRoIGl0cyBvd24gYGV4ZWN1dGUoKWA7IGEgc2Vjb25kIGNhbGwgcmVwbGFjZXMgdGhlIHByZXZpb3VzIG9uZSwgc29cbiAqIGEgcmUtcmVnaXN0ZXJlZCBwbHVnaW4gZG9lcyBub3QgbGVhdmUgdGhlIHRvb2xzIGJvdW5kIHRvIGEgZGVhZCBpbnN0YW5jZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldEVtYWlsRXhlY3V0b3IoZXhlY3V0ZTogRW1haWxFeGVjdXRvcik6IHZvaWQge1xuICBnZXRFbWFpbFJ1bnRpbWUoKS5leGVjdXRlID0gZXhlY3V0ZTtcbn1cblxuLyoqXG4gKiBEcm9wIHRoZSBtZW1vaXplZCBydW50aW1lLCBjbG9zaW5nIHRoZSBTTVRQIGNvbm5lY3Rpb24gcG9vbCwgc28gdGhlIG5leHRcbiAqIHtAbGluayBnZXRFbWFpbFJ1bnRpbWV9IHJlYnVpbGRzIGl0IGZyb20gZnJlc2ggY29uZmlnIGFuZCBzdG9wcyBjYWxsaW5nXG4gKiB0aHJvdWdoIGEgdG9ybi1kb3duIHBsdWdpbidzIGBleGVjdXRlKClgLiBJZGVtcG90ZW50LCBhbmQgdGhlIHBsdWdpbidzXG4gKiBgc2h1dGRvd24oKWAgaG9vay5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc2V0RW1haWxSdW50aW1lKCk6IHZvaWQge1xuICBydW50aW1lPy50cmFuc3BvcnRlcj8uY2xvc2UoKTtcbiAgcnVudGltZSA9IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSdW4gb25lIG5vbi1pZGVtcG90ZW50IHdyaXRlIHRocm91Z2ggdGhlIHNoYXJlZCBleGVjdXRvciBhbmQgdW53cmFwIGl0LlxuICpcbiAqIGBleGVjdXRlKClgIG5ldmVyIHRocm93cywgc28gYSBmYWlsZWQgc2VuZCBhcnJpdmVzIGFzIGB7IG9rOiBmYWxzZSB9YCB3aXRoIGFcbiAqIHN0YXR1cyB0aGUgaW50ZXJjZXB0b3JzIGFscmVhZHkgc2FuaXRpemVkOyBpdCBpcyBsb2dnZWQgaGVyZSBhbmQgcmUtcmFpc2VkXG4gKiBhcyBhIHN0YWJsZSB7QGxpbmsgRXhlY3V0aW9uRXJyb3J9IHNvIGFuIHVwc3RyZWFtIG1lc3NhZ2UgbmV2ZXIgYmVjb21lcyB0aGVcbiAqIGNhbGxlcidzIGVycm9yIHRleHQuIGBzaWduYWxgIGlzIHRoZSBjYWxsZXIncyBvd24gY2FuY2VsbGF0aW9uIChhbiBhZ2VudFxuICogcnVuLCBhIHJlcXVlc3QgdGVhcmRvd24pOyBpdCBpcyBtZXJnZWQgd2l0aCB0aGUgc2lnbmFsIHRoZSB0aW1lb3V0XG4gKiBpbnRlcmNlcHRvciBzdXBwbGllcyBzbyBlaXRoZXIgb25lIHVud2luZHMgdGhlIEkvTy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGV4ZWN1dGVXcml0ZTxUPihcbiAgb3BlcmF0aW9uOiBzdHJpbmcsXG4gIHNldHRpbmdzOiBFbWFpbEV4ZWN1dGlvblNldHRpbmdzLFxuICBmbjogKHNpZ25hbD86IEFib3J0U2lnbmFsKSA9PiBQcm9taXNlPFQ+LFxuICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbik6IFByb21pc2U8VD4ge1xuICBjb25zdCB7IGV4ZWN1dGUgfSA9IGdldEVtYWlsUnVudGltZSgpO1xuICByZXR1cm4gZXhlY3V0aW9uLnJ1bih7XG4gICAgb3BlcmF0aW9uLFxuICAgIHNldHRpbmdzLFxuICAgIGV4ZWN1dGUsXG4gICAgZm4sXG4gICAgc2lnbmFsLFxuICAgIGNhbmNlbGVkOiBFeGVjdXRpb25FcnJvci5jYW5jZWxlZCxcbiAgICBmYWlsZWQ6IChmYWlsdXJlKSA9PiB7XG4gICAgICBsb2dnZXIud2FybihcImV4ZWN1dGlvbi1mYWlsZWRcIiwge1xuICAgICAgICBvcGVyYXRpb246IGZhaWx1cmUub3BlcmF0aW9uLFxuICAgICAgICBzdGF0dXM6IGZhaWx1cmUuc3RhdHVzLFxuICAgICAgICBlcnJvcjogZmFpbHVyZS5tZXNzYWdlLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gbmV3IEV4ZWN1dGlvbkVycm9yKGBlbWFpbDogJHtmYWlsdXJlLm9wZXJhdGlvbn0gZmFpbGVkYCwge1xuICAgICAgICBjb250ZXh0OiB7IG9wZXJhdGlvbjogZmFpbHVyZS5vcGVyYXRpb24sIHN0YXR1czogZmFpbHVyZS5zdGF0dXMgfSxcbiAgICAgIH0pO1xuICAgIH0sXG4gIH0pO1xufVxuXG4vKipcbiAqIE9wZW4gYW5kIHRlYXIgZG93biBvbmUgU01UUCBjb25uZWN0aW9uIHRvIHByb3ZlIHRoZSBob3N0LCBwb3J0LCBhbmRcbiAqIGNyZWRlbnRpYWxzIHdvcmsuIENhbGxlZCBhdCBwbHVnaW4gc2V0dXAgc28gYSBiYWQgcmVsYXkgc2hvd3MgdXAgaW4gdGhlXG4gKiBib290IGxvZ3MgcmF0aGVyIHRoYW4gb24gdGhlIGZpcnN0IGFwcHJvdmVkIHNlbmQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2ZXJpZnlFbWFpbFRyYW5zcG9ydChcbiAgdHJhbnNwb3J0ZXI6IFRyYW5zcG9ydGVyIHwgdW5kZWZpbmVkLFxuICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbik6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoIXRyYW5zcG9ydGVyKSB7XG4gICAgdGhyb3cgQ29uZmlndXJhdGlvbkVycm9yLmludmFsaWRDb25uZWN0aW9uKFxuICAgICAgXCJTTVRQXCIsXG4gICAgICBcIlRoZSBydW50aW1lIHJlc29sdmVkIHRvIG91dGJveCBtb2RlLCBzbyB0aGVyZSBpcyBubyB0cmFuc3BvcnQgdG8gdmVyaWZ5LlwiLFxuICAgICk7XG4gIH1cbiAgYXdhaXQgYWJvcnRhYmxlKHRyYW5zcG9ydGVyLnZlcmlmeSgpLCBzaWduYWwpO1xufVxuXG4vKipcbiAqIFN0b3AgYXdhaXRpbmcgYHByb21pc2VgIGFzIHNvb24gYXMgYHNpZ25hbGAgYWJvcnRzLiBub2RlbWFpbGVyIGV4cG9zZXMgbm9cbiAqIGNhbmNlbGxhdGlvbiBob29rLCBzbyB0aGUgU01UUCBjb252ZXJzYXRpb24gaXRzZWxmIGZpbmlzaGVzIG9uIGl0cyBvd25cbiAqIGNvbm5lY3Rpb247IHdoYXQgdW53aW5kcyBpcyB0aGUgY2FsbGVyIGFuZCBldmVyeXRoaW5nIGRvd25zdHJlYW0gb2YgaXQuXG4gKi9cbmZ1bmN0aW9uIGFib3J0YWJsZTxUPihwcm9taXNlOiBQcm9taXNlPFQ+LCBzaWduYWw6IEFib3J0U2lnbmFsIHwgdW5kZWZpbmVkKTogUHJvbWlzZTxUPiB7XG4gIGlmICghc2lnbmFsKSByZXR1cm4gcHJvbWlzZTtcbiAgc2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gIC8vIFRoZSBsaXN0ZW5lciBpcyBkZXRhY2hlZCBvbmNlIHRoZSByYWNlIHNldHRsZXMgc28gYSBsb25nLWxpdmVkIHJ1biBzaWduYWxcbiAgLy8gZG9lcyBub3QgYWNjdW11bGF0ZSBvbmUgcGVyIHNlbmQuXG4gIGNvbnN0IGxpc3RlbmVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICBjb25zdCBhYm9ydGVkID0gbmV3IFByb21pc2U8bmV2ZXI+KChfLCByZWplY3QpID0+IHtcbiAgICBzaWduYWwuYWRkRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsICgpID0+IHJlamVjdChzaWduYWwucmVhc29uKSwge1xuICAgICAgb25jZTogdHJ1ZSxcbiAgICAgIHNpZ25hbDogbGlzdGVuZXIuc2lnbmFsLFxuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIFByb21pc2UucmFjZShbcHJvbWlzZSwgYWJvcnRlZF0pLmZpbmFsbHkoKCkgPT4gbGlzdGVuZXIuYWJvcnQoKSk7XG59XG5cbi8qKiBUaGUgY29tbWEtam9pbmVkIHJlY2lwaWVudCBzdHJpbmcgZWNob2VkIGJhY2sgaW4ge0BsaW5rIEVtYWlsUmVzdWx0fS4gKi9cbmZ1bmN0aW9uIHJlY2lwaWVudEVjaG8odG86IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgcmV0dXJuIHRvLmpvaW4oXCIsIFwiKTtcbn1cblxuLyoqXG4gKiBOb2RlIGJ1ZmZlciBlbmNvZGluZ3MgYSB3aXJlIGF0dGFjaG1lbnQgbWF5IG5hbWUgZm9yIGl0cyBpbmxpbmUgYGNvbnRlbnRgLlxuICogQW55dGhpbmcgZWxzZSBpcyBtZWFzdXJlZCBhcyBVVEYtOCwgd2hpY2ggb3Zlci1jb3VudHMgcmF0aGVyIHRoYW4gbGV0dGluZ1xuICogYW4gdW5yZWNvZ25pemVkIGVuY29kaW5nIHNsaXAgcGFzdCB0aGUgc2l6ZSBjYXAuXG4gKi9cbmNvbnN0IENPTlRFTlRfRU5DT0RJTkdTOiBSZWFkb25seVNldDxzdHJpbmc+ID0gbmV3IFNldChbXG4gIFwiYXNjaWlcIixcbiAgXCJiYXNlNjRcIixcbiAgXCJiYXNlNjR1cmxcIixcbiAgXCJiaW5hcnlcIixcbiAgXCJoZXhcIixcbiAgXCJsYXRpbjFcIixcbiAgXCJ1Y3MyXCIsXG4gIFwidWNzLTJcIixcbiAgXCJ1dGY4XCIsXG4gIFwidXRmLThcIixcbiAgXCJ1dGYxNmxlXCIsXG4gIFwidXRmLTE2bGVcIixcbl0pO1xuXG4vKipcbiAqIERlY29kZWQgYnl0ZSBzaXplIG9mIG9uZSBhdHRhY2htZW50J3MgaW5saW5lIGNvbnRlbnQuIEEgYHBhdGhgIGF0dGFjaG1lbnRcbiAqIGNvbnRyaWJ1dGVzIG5vdGhpbmc6IG5vZGVtYWlsZXIgc3RyZWFtcyBpdCwgc28gaXRzIGJ5dGVzIG5ldmVyIHNpdCBpbiB0aGlzXG4gKiBwcm9jZXNzIGFuZCBjYW5ub3QgYmUgbWVhc3VyZWQgaGVyZS5cbiAqL1xuZnVuY3Rpb24gYXR0YWNobWVudEJ5dGVzKGF0dGFjaG1lbnQ6IEVtYWlsQXR0YWNobWVudCk6IG51bWJlciB7XG4gIGNvbnN0IHsgY29udGVudCwgZW5jb2RpbmcgfSA9IGF0dGFjaG1lbnQ7XG4gIGlmIChjb250ZW50ID09PSB1bmRlZmluZWQpIHJldHVybiAwO1xuICBjb25zdCBkZWNsYXJlZCA9IGVuY29kaW5nPy50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCByZXNvbHZlZCA9XG4gICAgZGVjbGFyZWQgJiYgQ09OVEVOVF9FTkNPRElOR1MuaGFzKGRlY2xhcmVkKSA/IChkZWNsYXJlZCBhcyBCdWZmZXJFbmNvZGluZykgOiBcInV0ZjhcIjtcbiAgcmV0dXJuIEJ1ZmZlci5ieXRlTGVuZ3RoKGNvbnRlbnQsIHJlc29sdmVkKTtcbn1cblxuLyoqXG4gKiBSZWplY3QgYSBtZXNzYWdlIHdob3NlIGJvZHkgb3IgYXR0YWNobWVudHMgZXhjZWVkIHRoZSBwbHVnaW4ncyBjYXBzLiBUaGVcbiAqIGJvZHkgYW5kIGF0dGFjaG1lbnQgbGlzdCBhcnJpdmUgZnJvbSBhIG1vZGVsLCBzbyB0aGV5IGFyZSB1bmJvdW5kZWQgdW50aWxcbiAqIHNvbWV0aGluZyBib3VuZHMgdGhlbTsgbW9zdCBTTVRQIHJlbGF5cyBhbHNvIHJlamVjdCBhbiBvdmVyc2l6ZWQgbWVzc2FnZVxuICogb25seSBhZnRlciB0aGUgd2hvbGUgcGF5bG9hZCBoYXMgYmVlbiB1cGxvYWRlZC5cbiAqL1xuZnVuY3Rpb24gYXNzZXJ0TWVzc2FnZVdpdGhpbkNhcHMobWVzc2FnZTogRW1haWxNZXNzYWdlKTogdm9pZCB7XG4gIGlmIChtZXNzYWdlLmJvZHkubGVuZ3RoID4gTUFYX0JPRFlfQ0hBUlMpIHtcbiAgICB0aHJvdyBWYWxpZGF0aW9uRXJyb3IuaW52YWxpZFZhbHVlKFxuICAgICAgXCJib2R5XCIsXG4gICAgICBtZXNzYWdlLmJvZHkubGVuZ3RoLFxuICAgICAgYGF0IG1vc3QgJHtNQVhfQk9EWV9DSEFSU30gY2hhcmFjdGVyc2AsXG4gICAgKTtcbiAgfVxuICBjb25zdCBhdHRhY2htZW50cyA9IG1lc3NhZ2UuYXR0YWNobWVudHMgPz8gW107XG4gIGlmIChhdHRhY2htZW50cy5sZW5ndGggPiBNQVhfQVRUQUNITUVOVF9DT1VOVCkge1xuICAgIHRocm93IFZhbGlkYXRpb25FcnJvci5pbnZhbGlkVmFsdWUoXG4gICAgICBcImF0dGFjaG1lbnRzXCIsXG4gICAgICBhdHRhY2htZW50cy5sZW5ndGgsXG4gICAgICBgYXQgbW9zdCAke01BWF9BVFRBQ0hNRU5UX0NPVU5UfSBmaWxlc2AsXG4gICAgKTtcbiAgfVxuICBsZXQgdG90YWwgPSAwO1xuICBmb3IgKGNvbnN0IGF0dGFjaG1lbnQgb2YgYXR0YWNobWVudHMpIHtcbiAgICBjb25zdCBieXRlcyA9IGF0dGFjaG1lbnRCeXRlcyhhdHRhY2htZW50KTtcbiAgICBpZiAoYnl0ZXMgPiBNQVhfQVRUQUNITUVOVF9CWVRFUykge1xuICAgICAgdGhyb3cgVmFsaWRhdGlvbkVycm9yLmludmFsaWRWYWx1ZShcbiAgICAgICAgXCJhdHRhY2htZW50c1tdLmNvbnRlbnRcIixcbiAgICAgICAgYnl0ZXMsXG4gICAgICAgIGBhdCBtb3N0ICR7TUFYX0FUVEFDSE1FTlRfQllURVN9IGJ5dGVzIHBlciBmaWxlYCxcbiAgICAgICk7XG4gICAgfVxuICAgIHRvdGFsICs9IGJ5dGVzO1xuICB9XG4gIGlmICh0b3RhbCA+IE1BWF9BVFRBQ0hNRU5UU19UT1RBTF9CWVRFUykge1xuICAgIHRocm93IFZhbGlkYXRpb25FcnJvci5pbnZhbGlkVmFsdWUoXG4gICAgICBcImF0dGFjaG1lbnRzXCIsXG4gICAgICB0b3RhbCxcbiAgICAgIGBhdCBtb3N0ICR7TUFYX0FUVEFDSE1FTlRTX1RPVEFMX0JZVEVTfSBieXRlcyBhY3Jvc3MgYWxsIGZpbGVzYCxcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogTWFwIHRoZSB3aXJlLWZvcm1hdCB7QGxpbmsgRW1haWxBdHRhY2htZW50fXMgb250byBub2RlbWFpbGVyJ3NcbiAqIGF0dGFjaG1lbnQgc2hhcGUsIGRyb3BwaW5nIHVuc2V0IG9wdGlvbmFsIGtleXMgc28gbm9kZW1haWxlciBhcHBsaWVzXG4gKiBpdHMgb3duIGRlZmF1bHRzICh1dGYtOCBlbmNvZGluZywgZmlsZW5hbWUtaW5mZXJyZWQgY29udGVudCB0eXBlKS4gVGhlXG4gKiB3aXJlIGZpZWxkcyBhcmUgYSBkZWxpYmVyYXRlIHN1YnNldCBvZiBub2RlbWFpbGVyJ3MsIHNvIHRoaXMgaXMgYVxuICogc3RyYWlnaHQgc3RydWN0dXJhbCBwYXNzLXRocm91Z2guXG4gKi9cbmZ1bmN0aW9uIHRvTWFpbEF0dGFjaG1lbnRzKFxuICBhdHRhY2htZW50czogRW1haWxBdHRhY2htZW50W10gfCB1bmRlZmluZWQsXG4pOiBTZW5kTWFpbE9wdGlvbnNbXCJhdHRhY2htZW50c1wiXSB7XG4gIGlmICghYXR0YWNobWVudHMgfHwgYXR0YWNobWVudHMubGVuZ3RoID09PSAwKSByZXR1cm4gdW5kZWZpbmVkO1xuICByZXR1cm4gYXR0YWNobWVudHMubWFwKChhdHQpID0+ICh7XG4gICAgZmlsZW5hbWU6IGF0dC5maWxlbmFtZSxcbiAgICAuLi4oYXR0LmNvbnRlbnQgIT09IHVuZGVmaW5lZCA/IHsgY29udGVudDogYXR0LmNvbnRlbnQgfSA6IHt9KSxcbiAgICAuLi4oYXR0LmVuY29kaW5nICE9PSB1bmRlZmluZWQgPyB7IGVuY29kaW5nOiBhdHQuZW5jb2RpbmcgfSA6IHt9KSxcbiAgICAuLi4oYXR0LnBhdGggIT09IHVuZGVmaW5lZCA/IHsgcGF0aDogYXR0LnBhdGggfSA6IHt9KSxcbiAgICAuLi4oYXR0LmNvbnRlbnRUeXBlICE9PSB1bmRlZmluZWQgPyB7IGNvbnRlbnRUeXBlOiBhdHQuY29udGVudFR5cGUgfSA6IHt9KSxcbiAgfSkpO1xufVxuXG4vKipcbiAqIEhhbmQgb25lIGFscmVhZHktdmFsaWRhdGVkIG1lc3NhZ2UgdG8gU01UUCwgb3Igd3JpdGUgaXQgdG8gdGhlIG91dGJveCB3aGVuXG4gKiBubyBjcmVkZW50aWFscyBhcmUgY29uZmlndXJlZC4gVGhlIGhhbGYgb2YgYSBzZW5kIHRoYXQgcGVyZm9ybXMgSS9PLCBzbyBpdFxuICogaXMgd2hhdCBydW5zIGluc2lkZSB0aGUgaW50ZXJjZXB0b3IgY2hhaW4uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGRpc3BhdGNoKFxuICBtZXNzYWdlOiBFbWFpbE1lc3NhZ2UsXG4gIGZyb206IHN0cmluZyxcbiAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4gIG9wdGlvbnM/OiBTZW5kRW1haWxPcHRpb25zLFxuKTogUHJvbWlzZTxFbWFpbFJlc3VsdD4ge1xuICBjb25zdCB7IGNvbmZpZywgdHJhbnNwb3J0ZXIgfSA9IGdldEVtYWlsUnVudGltZSgpO1xuICBjb25zdCByZWNpcGllbnQgPSByZWNpcGllbnRFY2hvKG1lc3NhZ2UudG8pO1xuICBzaWduYWw/LnRocm93SWZBYm9ydGVkKCk7XG5cbiAgaWYgKGNvbmZpZy5tb2RlID09PSBcImZpbGVcIikge1xuICAgIGNvbnN0IHBhdGggPSBhd2FpdCB3cml0ZU91dGJveEVtYWlsKG1lc3NhZ2UsIGZyb20sIGNvbmZpZy5vdXREaXIsIGNvbmZpZy5icmFuZCk7XG4gICAgcmV0dXJuIHsgc2VudDogdHJ1ZSwgcmVjaXBpZW50LCBmcm9tLCBtZXNzYWdlSWQ6IHBhdGggfTtcbiAgfVxuXG4gIGlmICghdHJhbnNwb3J0ZXIpIHtcbiAgICB0aHJvdyBDb25maWd1cmF0aW9uRXJyb3IuaW52YWxpZENvbm5lY3Rpb24oXG4gICAgICBcIlNNVFBcIixcbiAgICAgIFwiTm8gdHJhbnNwb3J0IHdhcyBidWlsdCBmb3IgdGhlIHJlc29sdmVkIGNvbmZpZ3VyYXRpb24uXCIsXG4gICAgKTtcbiAgfVxuICBjb25zdCBhdHRhY2htZW50cyA9IHRvTWFpbEF0dGFjaG1lbnRzKG1lc3NhZ2UuYXR0YWNobWVudHMpO1xuICBjb25zdCByZW5kZXJlZCA9IGF3YWl0IHJlbmRlckVtYWlsKHtcbiAgICBzdWJqZWN0OiBtZXNzYWdlLnN1YmplY3QsXG4gICAgYm9keTogbWVzc2FnZS5ib2R5LFxuICAgIGJyYW5kOiBjb25maWcuYnJhbmQsXG4gIH0pO1xuICBjb25zdCBpbmZvID0gYXdhaXQgYWJvcnRhYmxlKFxuICAgIHRyYW5zcG9ydGVyLnNlbmRNYWlsKHtcbiAgICAgIGZyb20sXG4gICAgICB0bzogbWVzc2FnZS50byxcbiAgICAgIHN1YmplY3Q6IG1lc3NhZ2Uuc3ViamVjdCxcbiAgICAgIC8vIEEgY2FsbGVyLXN1cHBsaWVkIHBsYWluLXRleHQgcGFydCBXSU5TIG92ZXIgdGhlIGdlbmVyYXRlZCBvbmUuIEJvdGggcGFydHNcbiAgICAgIC8vIHN0aWxsIGNvbWUgZnJvbSB0aGUgc2FtZSBjb250ZW50OyB0aGlzIG9ubHkgbGV0cyBhIGNhbGxlciBjb250cm9sIHRoZVxuICAgICAgLy8gdGV4dCBhbHRlcm5hdGl2ZSdzIGV4YWN0IGxpbmUgbGF5b3V0LCB3aGljaCBzb21lIGNsaWVudHMgcGFyc2UgKHNlZVxuICAgICAgLy8gYFNlbmRFbWFpbE9wdGlvbnMudGV4dGApLlxuICAgICAgdGV4dDogb3B0aW9ucz8udGV4dCA/PyByZW5kZXJlZC50ZXh0LFxuICAgICAgaHRtbDogcmVuZGVyZWQuaHRtbCxcbiAgICAgIC4uLihtZXNzYWdlLmNjICYmIG1lc3NhZ2UuY2MubGVuZ3RoID4gMCA/IHsgY2M6IG1lc3NhZ2UuY2MgfSA6IHt9KSxcbiAgICAgIC4uLihtZXNzYWdlLmJjYyAmJiBtZXNzYWdlLmJjYy5sZW5ndGggPiAwID8geyBiY2M6IG1lc3NhZ2UuYmNjIH0gOiB7fSksXG4gICAgICAuLi4oYXR0YWNobWVudHMgPyB7IGF0dGFjaG1lbnRzIH0gOiB7fSksXG4gICAgfSksXG4gICAgc2lnbmFsLFxuICApO1xuICByZXR1cm4ge1xuICAgIHNlbnQ6IHRydWUsXG4gICAgcmVjaXBpZW50LFxuICAgIGZyb20sXG4gICAgLi4uKGluZm8ubWVzc2FnZUlkID8geyBtZXNzYWdlSWQ6IGluZm8ubWVzc2FnZUlkIH0gOiB7fSksXG4gIH07XG59XG5cbi8qKlxuICogRGVsaXZlcnktdGltZSBvcHRpb25zIHRoYXQgYXJlIE5PVCBwYXJ0IG9mIHRoZSBtZXNzYWdlIGEgbW9kZWwgY29tcG9zZXMuXG4gKlxuICogRGVsaWJlcmF0ZWx5IHNlcGFyYXRlIGZyb20ge0BsaW5rIEVtYWlsTWVzc2FnZX06IHRoYXQgc2NoZW1hIGlzIHRoZSBhZ2VudFxuICogdG9vbCdzIGlucHV0LCBzbyBhbnl0aGluZyBhZGRlZCB0byBpdCBiZWNvbWVzIGEgZmllbGQgYSBtb2RlbCBjYW4gc2V0LiBUaGVzZVxuICogZGVzY3JpYmUgaG93IGEgbWVzc2FnZSBpcyBERUxJVkVSRUQsIHNvIHRoZXkgYXJlIHRoZSBjYWxsZXIncyB0byBzdXBwbHkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2VuZEVtYWlsT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBBbiBleHBsaWNpdCBgdGV4dC9wbGFpbmAgYWx0ZXJuYXRpdmUsIHJlcGxhY2luZyB0aGUgb25lIGdlbmVyYXRlZCBmcm9tIHRoZVxuICAgKiBSZWFjdCBFbWFpbCB0cmVlLiBUaGUgSFRNTCBwYXJ0IGlzIHVudG91Y2hlZCwgc28gdGhlIHJlY2lwaWVudCBzdGlsbCBnZXRzIHRoZVxuICAgKiBmdWxsIGJyYW5kZWQgdGVtcGxhdGUuXG4gICAqXG4gICAqIFRoaXMgZXhpc3RzIGJlY2F1c2UgdGhlIGdlbmVyYXRlZCB0ZXh0IHBhcnQgaXMgYSBSRU5ERVJJTkcgb2YgdGhlIEhUTUw6IGl0XG4gICAqIGNhcnJpZXMgdGhlIGJyYW5kIGhlYWRlciBhbmQgZm9vdGVyLCBhbmQgaXQgdHVybnMgQ1NTIG1hcmdpbiBpbnRvIGJsYW5rXG4gICAqIGxpbmVzLiBUaGF0IGlzIGZpbmUgZm9yIHByb3NlIGFuZCB3cm9uZyBmb3IgY29udGVudCBhIG1hY2hpbmUgcGFyc2VzLiBBXG4gICAqIG9uZS10aW1lLWNvZGUgZW1haWwgaXMgdGhlIGNhc2UgaW4gcG9pbnQgLSBjbGllbnRzIGxvb2sgZm9yIHRoZSBjb2RlIG9uIHRoZVxuICAgKiBsaW5lIGltbWVkaWF0ZWx5IGFmdGVyIHRoZSBwcm9tcHQsIGFuZCBhIHN0eWxlZCBgPGgyPmAgY29kZSBsYW5kcyB0d28gYmxhbmtcbiAgICogbGluZXMgYmVsb3cgaXQsIHNvIGF1dG9maWxsIHN0b3BzIGJlaW5nIG9mZmVyZWQgZXZlbiB0aG91Z2ggdGhlIEhUTUwgbG9va3NcbiAgICogcGVyZmVjdC4gU3VwcGx5aW5nIHRoZSB0ZXh0IHBhcnQgZGlyZWN0bHkga2VlcHMgdGhlIG5pY2UgdGVtcGxhdGUgQU5EIHRoZVxuICAgKiBsYXlvdXQgdGhvc2UgY2xpZW50cyBleHBlY3QuXG4gICAqXG4gICAqIEtlZXAgdGhlIHNhbWUgaW5mb3JtYXRpb24gaW4gYm90aCBwYXJ0czsgYSB0ZXh0IGFsdGVybmF0aXZlIHRoYXQgZGlzYWdyZWVzXG4gICAqIHdpdGggdGhlIEhUTUwgcmVhZHMgYXMgcGhpc2hpbmcgdG8gc3BhbSBmaWx0ZXJzLlxuICAgKi9cbiAgdGV4dD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBTZW5kIChTTVRQIG1vZGUpIG9yIHBlcnNpc3QgKGZpbGUvb3V0Ym94IG1vZGUpIG9uZSBtZXNzYWdlIGZyb20gdGhlXG4gKiByZXNvbHZlZCBgZnJvbWAgYWRkcmVzcy4gYHRvYCAoYW5kIG9wdGlvbmFsIGBjY2AgLyBgYmNjYCkgZWFjaCBhY2NlcHRcbiAqIG9uZSBvciBtb3JlIGFkZHJlc3NlcywgYW5kIGBhdHRhY2htZW50c2AgYXJlIGZvcndhcmRlZCBhcyBmaWxlcy4gVGhlXG4gKiBib2R5IGlzIHJlbmRlcmVkIGJ5IFJlYWN0IEVtYWlsIGludG8gbWF0Y2hpbmcgcGxhaW4tdGV4dCBhbmQgSFRNTCBNSU1FXG4gKiBhbHRlcm5hdGl2ZXMsIGFuZCB0aGUgb3V0Ym94IGVtYmVkcyB0aGVcbiAqIHJlbmRlcmVkIEhUTUwgaW4gYSBkb2N1bWVudC4gSW4gZmlsZSBtb2RlIHRoZSByZXR1cm5lZCBgbWVzc2FnZUlkYCBpc1xuICogdGhlIHBhdGggd3JpdHRlbi4gVGhyb3dzIHdoZW4gYHRvYCBjYXJyaWVzIG5vIHJlY2lwaWVudCwgd2hlbiB0aGUgYm9keVxuICogb3IgYXR0YWNobWVudHMgZXhjZWVkIHRoZSBwbHVnaW4ncyBjYXBzLCBvciB3aGVuIGBmcm9tYCBpcyBub3QgcGVybWl0dGVkXG4gKiBieSB0aGUgZWZmZWN0aXZlIHNlbmRlciBhbGxvdy1saXN0LlxuICpcbiAqIFRoZSByZWNpcGllbnQsIGNhcCwgYW5kIHNlbmRlciBjaGVja3MgcnVuIGJlZm9yZSB0aGUgaW50ZXJjZXB0b3IgY2hhaW4gc29cbiAqIHRoZWlyIHNwZWNpZmljIHN0YXR1cyBhbmQgYWN0aW9uYWJsZSBtZXNzYWdlIHJlYWNoIHRoZSBjYWxsZXIgaW5zdGVhZCBvZlxuICogdGhlIGNoYWluJ3Mgc3RhYmxlIGZhaWx1cmUgdGV4dC4gYHNpZ25hbGAgY2FuY2VscyB0aGUgc2VuZC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlbmRFbWFpbChcbiAgbWVzc2FnZTogRW1haWxNZXNzYWdlLFxuICBmcm9tOiBzdHJpbmcsXG4gIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICBvcHRpb25zPzogU2VuZEVtYWlsT3B0aW9ucyxcbik6IFByb21pc2U8RW1haWxSZXN1bHQ+IHtcbiAgaWYgKG1lc3NhZ2UudG8ubGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgVmFsaWRhdGlvbkVycm9yLm1pc3NpbmdGaWVsZChcInRvXCIpO1xuICB9XG4gIGFzc2VydE1lc3NhZ2VXaXRoaW5DYXBzKG1lc3NhZ2UpO1xuICBhc3NlcnRTZW5kZXJBbGxvd2VkKGZyb20sIGdldEVtYWlsUnVudGltZSgpLmNvbmZpZy5hbGxvd2VkU2VuZGVycyk7XG4gIHJldHVybiBleGVjdXRlV3JpdGUoXG4gICAgXCJzZW5kXCIsXG4gICAgRU1BSUxfU0VORF9TRVRUSU5HUyxcbiAgICAoZXhlY3V0ZVNpZ25hbCkgPT4gZGlzcGF0Y2gobWVzc2FnZSwgZnJvbSwgZXhlY3V0ZVNpZ25hbCwgb3B0aW9ucyksXG4gICAgc2lnbmFsLFxuICApO1xufVxuIl19
package/package.json CHANGED
@@ -27,9 +27,9 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@databricks/appkit": "^0.43.0",
30
- "@dbx-tools/shared-core": "0.6.53",
31
- "@dbx-tools/shared-email": "0.6.53",
32
- "@dbx-tools/shared-email-template": "0.6.53",
30
+ "@dbx-tools/shared-core": "0.6.55",
31
+ "@dbx-tools/shared-email": "0.6.55",
32
+ "@dbx-tools/shared-email-template": "0.6.55",
33
33
  "@mastra/core": "^1.47.0",
34
34
  "@react-email/render": "^2.1.0",
35
35
  "nodemailer": "^7.0.13",
@@ -50,7 +50,7 @@
50
50
  "./package.json": "./package.json"
51
51
  }
52
52
  },
53
- "version": "0.6.53",
53
+ "version": "0.6.55",
54
54
  "types": "./lib/index.d.ts",
55
55
  "type": "module",
56
56
  "exports": {
package/src/config.ts CHANGED
@@ -18,6 +18,7 @@
18
18
  * to a single SMTP server (e.g. SMTP2GO): `SMTP_HOST`, `SMTP_PORT`,
19
19
  * `SMTP_SECURE`, `SMTP_USER`, `SMTP_PASSWORD`, plus `EMAIL_DOMAIN` for
20
20
  * the derived sender's domain, `EMAIL_FROM` for an explicit override,
21
+ * `EMAIL_SYSTEM_FROM` for the do-not-reply address system mail sends from,
21
22
  * `EMAIL_SENDER_POLICY` for the sender restriction mode, and
22
23
  * `EMAIL_OUTBOX_DIR` for the outbox directory.
23
24
  *
@@ -28,7 +29,7 @@ import { ConfigurationError, ValidationError, type BasePluginConfig } from "@dat
28
29
  import { env, object } from "@dbx-tools/shared-core";
29
30
  import type { JSONSchema7 } from "json-schema";
30
31
  import { defaultEmailBrand, type EmailBrand } from "./brand.ts";
31
- import { parseAllowedSenders } from "./sender.ts";
32
+ import { isSenderAllowed, parseAllowedSenders, systemSenderAddress } from "./sender.ts";
32
33
 
33
34
  /** SMTP submission port used when none is configured. */
34
35
  export const DEFAULT_SMTP_PORT = 587;
@@ -80,10 +81,24 @@ export interface EmailPluginConfig extends BasePluginConfig {
80
81
  */
81
82
  domain?: string;
82
83
  /**
83
- * Explicit `From` address. When set, the sender is used verbatim and
84
- * the per-user derivation is skipped. Falls back to `EMAIL_FROM`.
84
+ * Explicit `From` address, OPTIONAL. When set, the sender is used verbatim
85
+ * and the per-user derivation is skipped. Falls back to `EMAIL_FROM`.
86
+ *
87
+ * Leave it unset in most deployments: {@link domain} alone is enough, and
88
+ * mail then comes from the address of the person who caused it, which is what
89
+ * a recipient expects to be able to reply to.
85
90
  */
86
91
  from?: string;
92
+ /**
93
+ * `From` for SYSTEM mail - a send with no on-behalf-of user, such as a
94
+ * sign-in code or a password reset. Falls back to `EMAIL_SYSTEM_FROM`, then
95
+ * to `no-reply@<domain>`, then to {@link from}.
96
+ *
97
+ * Machine mail gets a do-not-reply address by default because a reply to it
98
+ * reaches nobody. Set this to route those replies somewhere real (a monitored
99
+ * `support@`) or to spell the local part differently (`donotreply@`).
100
+ */
101
+ systemFrom?: string;
87
102
  /**
88
103
  * Directory for the file/outbox fallback. Falls back to
89
104
  * `EMAIL_OUTBOX_DIR`, then `<cwd>/tmp`. Only used when SMTP
@@ -116,11 +131,16 @@ export interface EmailPluginConfig extends BasePluginConfig {
116
131
  }
117
132
 
118
133
  /** Config shared by both resolved modes. */
119
- interface ResolvedSender {
134
+ export interface ResolvedSender {
120
135
  /** Sender domain; present whenever {@link from} is absent. */
121
136
  domain?: string;
122
137
  /** Explicit sender override; present skips per-user derivation. */
123
138
  from?: string;
139
+ /**
140
+ * Explicit do-not-reply sender for system mail. Absent means it is derived -
141
+ * see {@link systemSenderAddress}.
142
+ */
143
+ systemFrom?: string;
124
144
  /**
125
145
  * Effective sender allow-list: the configured patterns when any were
126
146
  * given, else the patterns implied by the sender source under an
@@ -184,7 +204,13 @@ export const EMAIL_CONFIG_SCHEMA: JSONSchema7 = {
184
204
  },
185
205
  from: {
186
206
  type: "string",
187
- description: "Explicit From address; skips per-user derivation. Falls back to EMAIL_FROM.",
207
+ description:
208
+ "Optional explicit From address; skips per-user derivation. Falls back to EMAIL_FROM.",
209
+ },
210
+ systemFrom: {
211
+ type: "string",
212
+ description:
213
+ "From for system mail (no on-behalf-of user, e.g. a sign-in code). Falls back to EMAIL_SYSTEM_FROM, then no-reply@<domain>, then from.",
188
214
  },
189
215
  outDir: {
190
216
  type: "string",
@@ -262,10 +288,21 @@ function resolveSenderPolicy(policy: SenderPolicy | undefined): SenderPolicy {
262
288
  * which only happens in outbox mode (where the sender falls back to the
263
289
  * on-behalf-of user's own address and cannot be enumerated up front).
264
290
  */
265
- function impliedSenderPatterns(domain: string | undefined, from: string | undefined): string[] {
291
+ function impliedSenderPatterns(sender: {
292
+ domain?: string;
293
+ from?: string;
294
+ systemFrom?: string;
295
+ }): string[] {
266
296
  const patterns: string[] = [];
267
- if (from) patterns.push(from.trim().toLowerCase());
268
- if (domain) patterns.push(`*@${domain.trim().toLowerCase()}`);
297
+ if (sender.from) patterns.push(sender.from.trim().toLowerCase());
298
+ if (sender.domain) patterns.push(`*@${sender.domain.trim().toLowerCase()}`);
299
+ // The system sender too, when the patterns above do not already cover it: it
300
+ // is an address this app SENDS from, so a list derived from the sender source
301
+ // has to permit it, or the very policy meant to describe the app's own senders
302
+ // denies its sign-in mail. Usually redundant (`*@domain` already matches
303
+ // `no-reply@domain`) - it matters for a `systemFrom` on another domain.
304
+ const system = systemSenderAddress(sender)?.toLowerCase();
305
+ if (system && !isSenderAllowed(system, patterns)) patterns.push(system);
269
306
  return patterns;
270
307
  }
271
308
 
@@ -290,8 +327,9 @@ function missingSmtpFields(
290
327
  * Resolve plugin config over environment defaults.
291
328
  *
292
329
  * When SMTP host + user + password are all present, returns `mode:
293
- * "smtp"` for real delivery (and throws if no sender source - domain or
294
- * from - is configured, since SMTP can't derive one from nothing).
330
+ * "smtp"` for real delivery (and throws if no sender source - domain,
331
+ * from, or systemFrom - is configured, since SMTP can't derive one from
332
+ * nothing; `domain` alone is the intended minimum).
295
333
  * When all three are absent and `EMAIL_OUTBOX_MODE` is enabled, returns
296
334
  * `mode: "file"` so the runtime writes messages to the outbox directory
297
335
  * for local testing; in that mode a sender source is optional (the
@@ -311,6 +349,7 @@ export function resolveEmailConfig(config: EmailPluginConfig = {}): ResolvedEmai
311
349
  const pass = env.string(smtp.password, "SMTP_PASSWORD") ?? undefined;
312
350
  const domain = env.string(config.domain, "EMAIL_DOMAIN") ?? undefined;
313
351
  const from = env.string(config.from, "EMAIL_FROM") ?? undefined;
352
+ const systemFrom = env.string(config.systemFrom, "EMAIL_SYSTEM_FROM") ?? undefined;
314
353
  const senderPolicy = resolveSenderPolicy(config.senderPolicy);
315
354
  const configuredSenders = parseAllowedSenders(
316
355
  config.allowedSenders ?? env.text("EMAIL_ALLOWED_SENDERS") ?? undefined,
@@ -318,10 +357,11 @@ export function resolveEmailConfig(config: EmailPluginConfig = {}): ResolvedEmai
318
357
  const allowedSenders =
319
358
  configuredSenders.length > 0 || senderPolicy === "unrestricted"
320
359
  ? configuredSenders
321
- : impliedSenderPatterns(domain, from);
360
+ : impliedSenderPatterns({ domain, from, systemFrom });
322
361
  const sender: ResolvedSender = {
323
362
  ...object.optional("domain", domain),
324
363
  ...object.optional("from", from),
364
+ ...object.optional("systemFrom", systemFrom),
325
365
  allowedSenders,
326
366
  senderPolicy,
327
367
  brand: config.brand ?? defaultEmailBrand,
@@ -335,10 +375,10 @@ export function resolveEmailConfig(config: EmailPluginConfig = {}): ResolvedEmai
335
375
  }
336
376
 
337
377
  if (hasAllSmtp) {
338
- if (!domain && !from) {
378
+ if (!domain && !from && !systemFrom) {
339
379
  throw ConfigurationError.resourceNotFound(
340
380
  "Email sender source",
341
- "Set EMAIL_DOMAIN to derive <user-local-part>@<domain>, or EMAIL_FROM for a fixed address.",
381
+ "Set EMAIL_DOMAIN to derive <user-local-part>@<domain> (and no-reply@<domain> for system mail), or EMAIL_FROM for a fixed address.",
342
382
  );
343
383
  }
344
384
  const port = env.positiveInt(smtp.port, "SMTP_PORT", DEFAULT_SMTP_PORT);
package/src/outbox.ts CHANGED
@@ -55,7 +55,6 @@ export async function writeOutboxEmail(
55
55
  from: string,
56
56
  dir: string,
57
57
  brand?: EmailBrand,
58
- options?: { trailer?: string },
59
58
  ): Promise<string> {
60
59
  const folder = resolve(dir, from);
61
60
  await mkdir(folder, { recursive: true });
@@ -66,9 +65,6 @@ export async function writeOutboxEmail(
66
65
  body: message.body,
67
66
  footer: "Local outbox preview - written to disk, not sent (no SMTP credentials configured).",
68
67
  ...(brand ? { brand } : {}),
69
- // Preserved so the preview shows the trailer in the same place a real send
70
- // puts it - the whole point being that it is the LAST line.
71
- ...(options?.trailer ? { trailer: options.trailer } : {}),
72
68
  });
73
69
  await writeFile(path, html, "utf8");
74
70
  return path;
package/src/plugin.ts CHANGED
@@ -243,11 +243,6 @@ export class EmailPlugin extends Plugin<EmailPluginConfig> implements ToolProvid
243
243
  * Send a message immediately from `from` through the shared
244
244
  * transport, bypassing the approval flow. For agent-driven sends
245
245
  * use {@link emailTool} instead.
246
- *
247
- * `options` carries delivery-time concerns that are deliberately NOT part of
248
- * the message schema an agent fills in - see {@link SendEmailOptions}. The
249
- * agent tool path never supplies them, which is the point: a trailer is
250
- * derived from the deployment's own domain, not from model output.
251
246
  */
252
247
  sendEmail: (
253
248
  message: EmailMessage,
@@ -282,10 +277,6 @@ export class EmailPlugin extends Plugin<EmailPluginConfig> implements ToolProvid
282
277
  * `from` is not pinned. The interceptor chain is applied inside
283
278
  * {@link sendEmail} through the executor installed at setup, so this must
284
279
  * not wrap it again.
285
- *
286
- * `options` is forwarded untouched so every caller of this plugin reaches the
287
- * same shared template features the module-level {@link sendEmail} does; the
288
- * agent tool path simply omits it.
289
280
  */
290
281
  private async send(
291
282
  message: EmailMessage,
package/src/sender.ts CHANGED
@@ -5,9 +5,15 @@
5
5
  * The default `From` re-homes the local part (everything before `@`) of
6
6
  * the OBO email on the configured sending domain, so `alice@databricks.com`
7
7
  * through a domain of `mail.example.com` goes out as
8
- * `alice@mail.example.com`. An explicit `from` short-circuits that; the
9
- * file/outbox fallback (no domain) keeps the user's address verbatim so
10
- * test artifacts land under a recognizable folder.
8
+ * `alice@mail.example.com`. Nothing has to be configured for that beyond the
9
+ * domain: a fixed `from` is an OVERRIDE, not a requirement. The file/outbox
10
+ * fallback (no domain) keeps the user's address verbatim so test artifacts land
11
+ * under a recognizable folder.
12
+ *
13
+ * A send with NO user in scope is SYSTEM mail - a sign-in code, a password
14
+ * reset, an alert - and goes from the do-not-reply address instead
15
+ * ({@link resolveSystemSenderAddress}), because a recipient cannot usefully
16
+ * reply to a machine and a human's address on machine mail invites them to try.
11
17
  *
12
18
  * The resolved `From` is then constrained to the effective allow-list: a
13
19
  * pattern is either an exact address (`user@domain.com`), a domain wildcard
@@ -22,15 +28,16 @@
22
28
  */
23
29
 
24
30
  import { ConfigurationError, ValidationError } from "@databricks/appkit";
25
- import { log, net } from "@dbx-tools/shared-core";
31
+ import { log, net, string } from "@dbx-tools/shared-core";
26
32
 
27
- import type { ResolvedEmailConfig } from "./config.ts";
33
+ import type { ResolvedEmailConfig, ResolvedSender } from "./config.ts";
28
34
 
29
35
  const logger = log.logger("email/sender");
30
36
 
31
37
  /**
32
- * Re-home the OBO user's local part on `domain`. Throws when no usable
33
- * local part is available (e.g. a service-context call with no user).
38
+ * Re-home a user's local part on `domain`. Throws when no usable local part is
39
+ * available; callers with no user in scope want
40
+ * {@link resolveSystemSenderAddress} instead of a fixed `from`.
34
41
  */
35
42
  export function deriveSenderAddress(userEmail: string | undefined, domain: string): string {
36
43
  const local = userEmail?.split("@")[0]?.trim();
@@ -101,25 +108,68 @@ export function assertSenderAllowed(from: string, patterns: string[]): void {
101
108
  );
102
109
  }
103
110
 
111
+ /**
112
+ * Local part of the default do-not-reply sender, used for mail that no user
113
+ * asked for and nobody can reply to.
114
+ */
115
+ export const SYSTEM_SENDER_LOCAL_PART = "no-reply";
116
+
117
+ /** The sender fields {@link systemSenderAddress} reads, resolved or raw. */
118
+ type SenderSource = Pick<ResolvedSender, "systemFrom" | "domain" | "from">;
119
+
120
+ /**
121
+ * The address SYSTEM mail sends from, or undefined when nothing configured
122
+ * yields one: an explicit {@link ResolvedSender.systemFrom} wins, else
123
+ * `no-reply@<domain>`, else the fixed `from`.
124
+ *
125
+ * `no-reply@<domain>` outranks a configured `from` on purpose. A fixed `from` is
126
+ * typically a person or a team address chosen for mail a HUMAN sent, and a
127
+ * verification code arriving from it invites a reply nobody reads. Set
128
+ * `systemFrom` / EMAIL_SYSTEM_FROM to name the address explicitly (a monitored
129
+ * `support@`, a differently-spelled `donotreply@`).
130
+ *
131
+ * Returns undefined rather than throwing so config resolution can fold the
132
+ * result into the sender allow-list before any send happens.
133
+ */
134
+ export function systemSenderAddress(source: SenderSource): string | undefined {
135
+ const explicit = string.trimToNull(source.systemFrom);
136
+ if (explicit) return explicit;
137
+ const domain = string.trimToNull(source.domain);
138
+ if (domain) return `${SYSTEM_SENDER_LOCAL_PART}@${domain}`;
139
+ return string.trimToNull(source.from) ?? undefined;
140
+ }
141
+
142
+ /**
143
+ * The `From` for a send with no user in scope. Throws when no sender source is
144
+ * configured at all, which in SMTP mode {@link resolveEmailConfig} has already
145
+ * ruled out - so this only fires for an outbox with nothing configured.
146
+ */
147
+ export function resolveSystemSenderAddress(config: ResolvedEmailConfig): string {
148
+ const address = systemSenderAddress(config);
149
+ if (address) return address;
150
+ throw ConfigurationError.resourceNotFound(
151
+ "Email sender address",
152
+ "Set `domain` / EMAIL_DOMAIN to send system mail as no-reply@<domain>, or `systemFrom` / EMAIL_SYSTEM_FROM to name the address.",
153
+ );
154
+ }
155
+
104
156
  /**
105
157
  * Resolve the `From` address for a send from the resolved config and the
106
- * current OBO user: explicit `from` wins, then `<local>@<domain>`, then
107
- * (file/outbox mode only) the user's email verbatim. Throws when none of
108
- * those yield an address.
158
+ * current OBO user.
159
+ *
160
+ * With a user in scope: an explicit `from` wins, then `<local>@<domain>`, then
161
+ * (file/outbox mode only) the user's email verbatim. With NO user the send is
162
+ * system mail, so it goes from {@link resolveSystemSenderAddress}. Throws when
163
+ * none of those yield an address.
109
164
  */
110
165
  export function resolveSenderAddress(
111
166
  config: ResolvedEmailConfig,
112
167
  userEmail: string | undefined,
113
168
  ): string {
169
+ const email = string.trimToNull(userEmail);
170
+ if (!email) return resolveSystemSenderAddress(config);
114
171
  if (config.from) return config.from;
115
- if (config.domain) return deriveSenderAddress(userEmail, config.domain);
116
- const email = userEmail?.trim();
117
- if (!email) {
118
- throw ConfigurationError.resourceNotFound(
119
- "Email sender address",
120
- "Set `from` / EMAIL_FROM, set `domain` / EMAIL_DOMAIN, or run on behalf of a user.",
121
- );
122
- }
172
+ if (config.domain) return deriveSenderAddress(email, config.domain);
123
173
  return email;
124
174
  }
125
175
 
package/src/transport.ts CHANGED
@@ -28,7 +28,7 @@ import {
28
28
  ValidationError,
29
29
  type ExecutionResult,
30
30
  } from "@databricks/appkit";
31
- import { execution, log, object } from "@dbx-tools/shared-core";
31
+ import { execution, log } from "@dbx-tools/shared-core";
32
32
  import type { EmailAttachment, EmailMessage, EmailResult } from "@dbx-tools/shared-email";
33
33
  import nodemailer, { type SendMailOptions, type Transporter } from "nodemailer";
34
34
  import { resolveEmailConfig, type EmailPluginConfig, type ResolvedEmailConfig } from "./config.ts";
@@ -322,7 +322,7 @@ async function dispatch(
322
322
  signal?.throwIfAborted();
323
323
 
324
324
  if (config.mode === "file") {
325
- const path = await writeOutboxEmail(message, from, config.outDir, config.brand, options);
325
+ const path = await writeOutboxEmail(message, from, config.outDir, config.brand);
326
326
  return { sent: true, recipient, from, messageId: path };
327
327
  }
328
328
 
@@ -337,14 +337,17 @@ async function dispatch(
337
337
  subject: message.subject,
338
338
  body: message.body,
339
339
  brand: config.brand,
340
- ...object.optional("trailer", options?.trailer),
341
340
  });
342
341
  const info = await abortable(
343
342
  transporter.sendMail({
344
343
  from,
345
344
  to: message.to,
346
345
  subject: message.subject,
347
- text: rendered.text,
346
+ // A caller-supplied plain-text part WINS over the generated one. Both parts
347
+ // still come from the same content; this only lets a caller control the
348
+ // text alternative's exact line layout, which some clients parse (see
349
+ // `SendEmailOptions.text`).
350
+ text: options?.text ?? rendered.text,
348
351
  html: rendered.html,
349
352
  ...(message.cc && message.cc.length > 0 ? { cc: message.cc } : {}),
350
353
  ...(message.bcc && message.bcc.length > 0 ? { bcc: message.bcc } : {}),
@@ -364,18 +367,28 @@ async function dispatch(
364
367
  * Delivery-time options that are NOT part of the message a model composes.
365
368
  *
366
369
  * Deliberately separate from {@link EmailMessage}: that schema is the agent
367
- * tool's input, so anything added to it becomes a field a model can set. A
368
- * trailer is a property of how the message is DELIVERED (it must be the final
369
- * line, and its content is derived from the deployment's own domain), so it is
370
- * the caller's to supply, never the model's.
370
+ * tool's input, so anything added to it becomes a field a model can set. These
371
+ * describe how a message is DELIVERED, so they are the caller's to supply.
371
372
  */
372
373
  export interface SendEmailOptions {
373
374
  /**
374
- * A machine-read final line, after the branded footer - Apple's domain-bound
375
- * one-time-code AutoFill trailer. Build it with
376
- * `sharedEmailTemplate.autofillTrailer(domain, code)`.
375
+ * An explicit `text/plain` alternative, replacing the one generated from the
376
+ * React Email tree. The HTML part is untouched, so the recipient still gets the
377
+ * full branded template.
378
+ *
379
+ * This exists because the generated text part is a RENDERING of the HTML: it
380
+ * carries the brand header and footer, and it turns CSS margin into blank
381
+ * lines. That is fine for prose and wrong for content a machine parses. A
382
+ * one-time-code email is the case in point - clients look for the code on the
383
+ * line immediately after the prompt, and a styled `<h2>` code lands two blank
384
+ * lines below it, so autofill stops being offered even though the HTML looks
385
+ * perfect. Supplying the text part directly keeps the nice template AND the
386
+ * layout those clients expect.
387
+ *
388
+ * Keep the same information in both parts; a text alternative that disagrees
389
+ * with the HTML reads as phishing to spam filters.
377
390
  */
378
- trailer?: string;
391
+ text?: string;
379
392
  }
380
393
 
381
394
  /**