@getstrata/core 0.5.9 → 0.5.12
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/dist/core/database/baseRepository.d.ts +4 -1
- package/dist/core/database/index.d.ts +2 -2
- package/dist/core/database/relationships.d.ts +46 -2
- package/dist/core/database/repositoryQuery.d.ts +4 -1
- package/dist/core/mail/mailer.d.ts +3 -1
- package/dist/core/mail/markdownMail.d.ts +15 -0
- package/dist/core/mail/markdownMailable.d.ts +13 -0
- package/dist/core/notifications/dispatcher.d.ts +13 -0
- package/dist/core/notifications/index.d.ts +3 -0
- package/dist/core/notifications/notification.d.ts +7 -0
- package/dist/core/notifications/types.d.ts +25 -0
- package/dist/entries/auth/guard.js +176 -1
- package/dist/entries/database.js +182 -1
- package/dist/entries/http/webErrorResponse.js +176 -1
- package/dist/entries/http.js +176 -1
- package/dist/entries/queue/createAppQueue.js +176 -1
- package/dist/entries/queue/publicQueue.js +176 -1
- package/dist/entries/queue/queueMetrics.js +176 -1
- package/dist/entries/view.js +176 -1
- package/dist/framework/public-api.d.ts +9 -3
- package/dist/index.js +360 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -942,6 +942,66 @@ function indexBelongsToManyRelation(parents, pivotRows, relatedRows, relation) {
|
|
|
942
942
|
}
|
|
943
943
|
return groups;
|
|
944
944
|
}
|
|
945
|
+
function morphMany(definition) {
|
|
946
|
+
return {
|
|
947
|
+
type: "morphMany",
|
|
948
|
+
...definition
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
function morphOne(definition) {
|
|
952
|
+
return {
|
|
953
|
+
type: "morphOne",
|
|
954
|
+
...definition
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
function morphTo(definition) {
|
|
958
|
+
return {
|
|
959
|
+
type: "morphTo",
|
|
960
|
+
...definition
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
function indexMorphManyRelation(parents, children, relation) {
|
|
964
|
+
const groups = new Map;
|
|
965
|
+
for (const parent of parents) {
|
|
966
|
+
groups.set(parent[relation.localKey], []);
|
|
967
|
+
}
|
|
968
|
+
for (const child of children) {
|
|
969
|
+
if (child[relation.morphTypeKey] !== relation.morphType) {
|
|
970
|
+
continue;
|
|
971
|
+
}
|
|
972
|
+
const key = child[relation.morphIdKey];
|
|
973
|
+
const group = groups.get(key);
|
|
974
|
+
if (!group) {
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
977
|
+
group.push(child);
|
|
978
|
+
}
|
|
979
|
+
return groups;
|
|
980
|
+
}
|
|
981
|
+
function indexMorphOneRelation(parents, children, relation) {
|
|
982
|
+
const grouped = indexMorphManyRelation(parents, children, relation);
|
|
983
|
+
const result = new Map;
|
|
984
|
+
for (const parent of parents) {
|
|
985
|
+
const matches = grouped.get(parent[relation.localKey]) ?? [];
|
|
986
|
+
result.set(parent[relation.localKey], matches[0]);
|
|
987
|
+
}
|
|
988
|
+
return result;
|
|
989
|
+
}
|
|
990
|
+
function indexMorphToRelation(children, parentsByType, relation) {
|
|
991
|
+
const result = new Map;
|
|
992
|
+
for (const child of children) {
|
|
993
|
+
const morphType = String(child[relation.morphTypeKey]);
|
|
994
|
+
const parents = parentsByType.get(morphType);
|
|
995
|
+
if (!parents) {
|
|
996
|
+
continue;
|
|
997
|
+
}
|
|
998
|
+
const parent = parents.get(child[relation.morphIdKey]);
|
|
999
|
+
if (parent) {
|
|
1000
|
+
result.set(child[relation.morphIdKey], parent);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
return result;
|
|
1004
|
+
}
|
|
945
1005
|
|
|
946
1006
|
// ../../src/config/database.ts
|
|
947
1007
|
function readInteger(name, fallback) {
|
|
@@ -1145,6 +1205,37 @@ class RepositoryQuery {
|
|
|
1145
1205
|
});
|
|
1146
1206
|
return this;
|
|
1147
1207
|
}
|
|
1208
|
+
withMorphMany(as, relation, childRepository, options = {}) {
|
|
1209
|
+
this.eagerLoads.push({
|
|
1210
|
+
kind: "morphMany",
|
|
1211
|
+
as,
|
|
1212
|
+
relation,
|
|
1213
|
+
repository: childRepository,
|
|
1214
|
+
options
|
|
1215
|
+
});
|
|
1216
|
+
return this;
|
|
1217
|
+
}
|
|
1218
|
+
withMorphOne(as, relation, childRepository, options = {}) {
|
|
1219
|
+
this.eagerLoads.push({
|
|
1220
|
+
kind: "morphOne",
|
|
1221
|
+
as,
|
|
1222
|
+
relation,
|
|
1223
|
+
repository: childRepository,
|
|
1224
|
+
options
|
|
1225
|
+
});
|
|
1226
|
+
return this;
|
|
1227
|
+
}
|
|
1228
|
+
withMorphTo(as, relation, repositoriesByType, options = {}) {
|
|
1229
|
+
this.eagerLoads.push({
|
|
1230
|
+
kind: "morphTo",
|
|
1231
|
+
as,
|
|
1232
|
+
relation,
|
|
1233
|
+
repository: this.repository,
|
|
1234
|
+
morphRepositories: repositoriesByType,
|
|
1235
|
+
options
|
|
1236
|
+
});
|
|
1237
|
+
return this;
|
|
1238
|
+
}
|
|
1148
1239
|
async get() {
|
|
1149
1240
|
const rows = await this.repository.findAll(this.buildOptions());
|
|
1150
1241
|
return await this.attach(rows);
|
|
@@ -1205,6 +1296,33 @@ class RepositoryQuery {
|
|
|
1205
1296
|
}));
|
|
1206
1297
|
continue;
|
|
1207
1298
|
}
|
|
1299
|
+
if (load.kind === "morphMany") {
|
|
1300
|
+
const relation2 = load.relation;
|
|
1301
|
+
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphManyForParents(rows, relation2, load.options);
|
|
1302
|
+
result = result.map((row) => ({
|
|
1303
|
+
...row,
|
|
1304
|
+
[load.as]: grouped2.get(row[relation2.localKey]) ?? []
|
|
1305
|
+
}));
|
|
1306
|
+
continue;
|
|
1307
|
+
}
|
|
1308
|
+
if (load.kind === "morphOne") {
|
|
1309
|
+
const relation2 = load.relation;
|
|
1310
|
+
const grouped2 = await load.repository.withConnection(this.repository.getConnection()).loadMorphOneForParents(rows, relation2, load.options);
|
|
1311
|
+
result = result.map((row) => ({
|
|
1312
|
+
...row,
|
|
1313
|
+
[load.as]: grouped2.get(row[relation2.localKey])
|
|
1314
|
+
}));
|
|
1315
|
+
continue;
|
|
1316
|
+
}
|
|
1317
|
+
if (load.kind === "morphTo") {
|
|
1318
|
+
const relation2 = load.relation;
|
|
1319
|
+
const grouped2 = await this.repository.loadMorphToForChildren(rows, relation2, load.morphRepositories ?? new Map, load.options);
|
|
1320
|
+
result = result.map((row) => ({
|
|
1321
|
+
...row,
|
|
1322
|
+
[load.as]: grouped2.get(row[relation2.morphIdKey])
|
|
1323
|
+
}));
|
|
1324
|
+
continue;
|
|
1325
|
+
}
|
|
1208
1326
|
const relation = load.relation;
|
|
1209
1327
|
const grouped = await this.repository.loadBelongsToForParents(rows, relation, load.repository, load.options);
|
|
1210
1328
|
result = result.map((row) => ({
|
|
@@ -1481,6 +1599,56 @@ class BaseRepository {
|
|
|
1481
1599
|
}, options);
|
|
1482
1600
|
return indexBelongsToRelation(children, parents, relation);
|
|
1483
1601
|
}
|
|
1602
|
+
async loadMorphManyForParents(parents, relation, options = {}) {
|
|
1603
|
+
if (parents.length === 0) {
|
|
1604
|
+
return indexMorphManyRelation(parents, [], relation);
|
|
1605
|
+
}
|
|
1606
|
+
const parentIds = [...new Set(parents.map((parent) => parent[relation.localKey]))];
|
|
1607
|
+
const children = await this.findWhere({
|
|
1608
|
+
[relation.morphTypeKey]: relation.morphType,
|
|
1609
|
+
[relation.morphIdKey]: parentIds
|
|
1610
|
+
}, options);
|
|
1611
|
+
return indexMorphManyRelation(parents, children, relation);
|
|
1612
|
+
}
|
|
1613
|
+
async loadMorphOneForParents(parents, relation, options = {}) {
|
|
1614
|
+
const grouped = await this.loadMorphManyForParents(parents, relation, options);
|
|
1615
|
+
const result = new Map;
|
|
1616
|
+
for (const parent of parents) {
|
|
1617
|
+
const matches = grouped.get(parent[relation.localKey]) ?? [];
|
|
1618
|
+
result.set(parent[relation.localKey], matches[0]);
|
|
1619
|
+
}
|
|
1620
|
+
return result;
|
|
1621
|
+
}
|
|
1622
|
+
async loadMorphToForChildren(children, relation, repositoriesByType, options = {}) {
|
|
1623
|
+
if (children.length === 0) {
|
|
1624
|
+
return new Map;
|
|
1625
|
+
}
|
|
1626
|
+
const idsByType = new Map;
|
|
1627
|
+
for (const child of children) {
|
|
1628
|
+
const morphType = String(child[relation.morphTypeKey]);
|
|
1629
|
+
const morphId = child[relation.morphIdKey];
|
|
1630
|
+
const ids = idsByType.get(morphType) ?? new Set;
|
|
1631
|
+
ids.add(morphId);
|
|
1632
|
+
idsByType.set(morphType, ids);
|
|
1633
|
+
}
|
|
1634
|
+
const parentsByType = new Map;
|
|
1635
|
+
for (const [morphType, ids] of idsByType) {
|
|
1636
|
+
const repository = repositoriesByType.get(morphType);
|
|
1637
|
+
if (!repository) {
|
|
1638
|
+
continue;
|
|
1639
|
+
}
|
|
1640
|
+
const ownerKey = repository.getTable().primaryKey;
|
|
1641
|
+
const parents = await repository.withConnection(this.connection).findWhere({
|
|
1642
|
+
[ownerKey]: [...ids]
|
|
1643
|
+
}, options);
|
|
1644
|
+
const indexed = new Map;
|
|
1645
|
+
for (const parent of parents) {
|
|
1646
|
+
indexed.set(parent[ownerKey], parent);
|
|
1647
|
+
}
|
|
1648
|
+
parentsByType.set(morphType, indexed);
|
|
1649
|
+
}
|
|
1650
|
+
return indexMorphToRelation(children, parentsByType, relation);
|
|
1651
|
+
}
|
|
1484
1652
|
}
|
|
1485
1653
|
var baseRepository_default = BaseRepository;
|
|
1486
1654
|
// ../../src/core/database/bindConnection.ts
|
|
@@ -2573,8 +2741,15 @@ function defineTable(definition) {
|
|
|
2573
2741
|
return definition;
|
|
2574
2742
|
}
|
|
2575
2743
|
// ../../src/core/database/transaction.ts
|
|
2744
|
+
function supportsTransactions(connection) {
|
|
2745
|
+
return typeof connection.begin === "function";
|
|
2746
|
+
}
|
|
2576
2747
|
async function runInTransaction(operation) {
|
|
2577
|
-
|
|
2748
|
+
const pool = resolveRepositoryConnection();
|
|
2749
|
+
if (!supportsTransactions(pool)) {
|
|
2750
|
+
throw new Error("Active database connection does not support transactions. Bind a client with begin() via bindDatabaseConnection.");
|
|
2751
|
+
}
|
|
2752
|
+
return await pool.begin(async (transaction) => {
|
|
2578
2753
|
return await operation(createDatabaseConnection2(transaction));
|
|
2579
2754
|
});
|
|
2580
2755
|
}
|
|
@@ -2691,18 +2866,7 @@ async function defaultSmtpTransport(config, message) {
|
|
|
2691
2866
|
await socket.write(`DATA\r
|
|
2692
2867
|
`);
|
|
2693
2868
|
await waitForSmtpResponse(readResponse, ["354"]);
|
|
2694
|
-
const payload =
|
|
2695
|
-
`From: ${config.from}`,
|
|
2696
|
-
`To: ${message.to}`,
|
|
2697
|
-
`Subject: ${message.subject}`,
|
|
2698
|
-
"MIME-Version: 1.0",
|
|
2699
|
-
"Content-Type: text/plain; charset=utf-8",
|
|
2700
|
-
"",
|
|
2701
|
-
message.body,
|
|
2702
|
-
".",
|
|
2703
|
-
""
|
|
2704
|
-
].join(`\r
|
|
2705
|
-
`);
|
|
2869
|
+
const payload = buildSmtpPayload(config.from, message);
|
|
2706
2870
|
await socket.write(payload);
|
|
2707
2871
|
await waitForSmtpResponse(readResponse, ["250"]);
|
|
2708
2872
|
await socket.write(`QUIT\r
|
|
@@ -2712,6 +2876,30 @@ async function defaultSmtpTransport(config, message) {
|
|
|
2712
2876
|
socket.end();
|
|
2713
2877
|
}
|
|
2714
2878
|
}
|
|
2879
|
+
function buildSmtpPayload(from, message) {
|
|
2880
|
+
const headers = [`From: ${from}`, `To: ${message.to}`, `Subject: ${message.subject}`, "MIME-Version: 1.0"];
|
|
2881
|
+
if (message.html) {
|
|
2882
|
+
const boundary = `strata-${Date.now().toString(36)}`;
|
|
2883
|
+
headers.push(`Content-Type: multipart/alternative; boundary="${boundary}"`);
|
|
2884
|
+
const parts = [
|
|
2885
|
+
`--${boundary}`,
|
|
2886
|
+
"Content-Type: text/plain; charset=utf-8",
|
|
2887
|
+
"",
|
|
2888
|
+
message.body,
|
|
2889
|
+
`--${boundary}`,
|
|
2890
|
+
"Content-Type: text/html; charset=utf-8",
|
|
2891
|
+
"",
|
|
2892
|
+
message.html,
|
|
2893
|
+
`--${boundary}--`,
|
|
2894
|
+
""
|
|
2895
|
+
];
|
|
2896
|
+
return [...headers, "", ...parts, ".", ""].join(`\r
|
|
2897
|
+
`);
|
|
2898
|
+
}
|
|
2899
|
+
headers.push("Content-Type: text/plain; charset=utf-8");
|
|
2900
|
+
return [...headers, "", message.body, ".", ""].join(`\r
|
|
2901
|
+
`);
|
|
2902
|
+
}
|
|
2715
2903
|
|
|
2716
2904
|
class LogMailDriver {
|
|
2717
2905
|
async send(message) {
|
|
@@ -2720,7 +2908,8 @@ class LogMailDriver {
|
|
|
2720
2908
|
channel: "mail",
|
|
2721
2909
|
to: message.to,
|
|
2722
2910
|
subject: message.subject,
|
|
2723
|
-
body: message.body
|
|
2911
|
+
body: message.body,
|
|
2912
|
+
...message.html ? { html: message.html } : {}
|
|
2724
2913
|
}));
|
|
2725
2914
|
}
|
|
2726
2915
|
}
|
|
@@ -4860,6 +5049,147 @@ function resetGracefulShutdownForTests() {
|
|
|
4860
5049
|
shutdownInstalled = false;
|
|
4861
5050
|
shuttingDown = false;
|
|
4862
5051
|
}
|
|
5052
|
+
// ../../src/core/mail/markdownMail.ts
|
|
5053
|
+
function escapeHtml(value) {
|
|
5054
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
5055
|
+
}
|
|
5056
|
+
function stripMarkdown(markdown) {
|
|
5057
|
+
return markdown.replace(/^#{1,6}\s+/gm, "").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1 ($2)").replace(/^[-*]\s+/gm, "\u2022 ").replace(/```[\s\S]*?```/g, "").replace(/\n{3,}/g, `
|
|
5058
|
+
|
|
5059
|
+
`).trim();
|
|
5060
|
+
}
|
|
5061
|
+
function markdownToHtml(markdown) {
|
|
5062
|
+
const escaped = markdown.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
5063
|
+
return escaped.replace(/^### (.+)$/gm, "<h3>$1</h3>").replace(/^## (.+)$/gm, "<h2>$1</h2>").replace(/^# (.+)$/gm, "<h1>$1</h1>").replace(/`([^`]+)`/g, "<code>$1</code>").replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>").replace(/\*([^*]+)\*/g, "<em>$1</em>").replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>').replace(/^[-*]\s+(.+)$/gm, "<li>$1</li>").replace(/(<li>[\s\S]*?<\/li>\n?)+/g, (block) => `<ul>${block}</ul>`).replace(/```(\w+)?\n([\s\S]*?)```/g, "<pre><code>$2</code></pre>").split(/\n\n+/).map((block) => {
|
|
5064
|
+
if (block.startsWith("<")) {
|
|
5065
|
+
return block;
|
|
5066
|
+
}
|
|
5067
|
+
return `<p>${block.replace(/\n/g, " ")}</p>`;
|
|
5068
|
+
}).join(`
|
|
5069
|
+
`);
|
|
5070
|
+
}
|
|
5071
|
+
function wrapMarkdownMailLayout(bodyHtml, options = {}) {
|
|
5072
|
+
const title = escapeHtml(options.title ?? "GetStrata");
|
|
5073
|
+
const preview = escapeHtml(options.preview ?? "");
|
|
5074
|
+
const footer = escapeHtml(options.footer ?? "Sent by GetStrata");
|
|
5075
|
+
return `<!DOCTYPE html>
|
|
5076
|
+
<html lang="en">
|
|
5077
|
+
<head>
|
|
5078
|
+
<meta charset="utf-8">
|
|
5079
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
5080
|
+
<title>${title}</title>
|
|
5081
|
+
<style>
|
|
5082
|
+
body { font-family: system-ui, sans-serif; line-height: 1.5; color: #111827; background: #f9fafb; margin: 0; padding: 24px; }
|
|
5083
|
+
.container { max-width: 640px; margin: 0 auto; background: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden; }
|
|
5084
|
+
.header { padding: 20px 24px; border-bottom: 1px solid #e5e7eb; font-weight: 600; }
|
|
5085
|
+
.content { padding: 24px; }
|
|
5086
|
+
.footer { padding: 16px 24px; border-top: 1px solid #e5e7eb; color: #6b7280; font-size: 14px; }
|
|
5087
|
+
a { color: #2563eb; }
|
|
5088
|
+
code { background: #f3f4f6; padding: 2px 4px; border-radius: 4px; }
|
|
5089
|
+
pre { background: #111827; color: #f9fafb; padding: 12px; border-radius: 6px; overflow-x: auto; }
|
|
5090
|
+
</style>
|
|
5091
|
+
</head>
|
|
5092
|
+
<body>
|
|
5093
|
+
${preview ? `<span style="display:none;max-height:0;overflow:hidden;">${preview}</span>` : ""}
|
|
5094
|
+
<div class="container">
|
|
5095
|
+
<div class="header">${title}</div>
|
|
5096
|
+
<div class="content">${bodyHtml}</div>
|
|
5097
|
+
<div class="footer">${footer}</div>
|
|
5098
|
+
</div>
|
|
5099
|
+
</body>
|
|
5100
|
+
</html>`;
|
|
5101
|
+
}
|
|
5102
|
+
function renderMarkdownMail(markdown, options = {}) {
|
|
5103
|
+
const bodyHtml = markdownToHtml(markdown.trim());
|
|
5104
|
+
const html = wrapMarkdownMailLayout(bodyHtml, options);
|
|
5105
|
+
const text = stripMarkdown(markdown);
|
|
5106
|
+
return { html, text };
|
|
5107
|
+
}
|
|
5108
|
+
// ../../src/core/mail/markdownMailable.ts
|
|
5109
|
+
function buildMarkdownMailMessage(input) {
|
|
5110
|
+
const rendered = renderMarkdownMail(input.markdown, {
|
|
5111
|
+
title: input.layout?.title ?? input.subject,
|
|
5112
|
+
...input.layout
|
|
5113
|
+
});
|
|
5114
|
+
return {
|
|
5115
|
+
to: input.to,
|
|
5116
|
+
subject: input.subject,
|
|
5117
|
+
body: rendered.text,
|
|
5118
|
+
html: rendered.html
|
|
5119
|
+
};
|
|
5120
|
+
}
|
|
5121
|
+
async function sendMarkdownMail(mailer2, input) {
|
|
5122
|
+
await mailer2.send(buildMarkdownMailMessage(input));
|
|
5123
|
+
}
|
|
5124
|
+
// ../../src/core/notifications/dispatcher.ts
|
|
5125
|
+
class NotificationDispatcher {
|
|
5126
|
+
mailer;
|
|
5127
|
+
databaseStore;
|
|
5128
|
+
constructor(mailer2, databaseStore = null) {
|
|
5129
|
+
this.mailer = mailer2;
|
|
5130
|
+
this.databaseStore = databaseStore;
|
|
5131
|
+
}
|
|
5132
|
+
async send(notifiable, notification) {
|
|
5133
|
+
for (const channel of notification.via(notifiable)) {
|
|
5134
|
+
if (channel === "mail") {
|
|
5135
|
+
await this.sendMail(notifiable, notification);
|
|
5136
|
+
continue;
|
|
5137
|
+
}
|
|
5138
|
+
if (channel === "database") {
|
|
5139
|
+
await this.sendDatabase(notifiable, notification);
|
|
5140
|
+
}
|
|
5141
|
+
}
|
|
5142
|
+
}
|
|
5143
|
+
async sendMail(notifiable, notification) {
|
|
5144
|
+
const routed = notifiable.routeNotificationFor("mail");
|
|
5145
|
+
if (routed === null) {
|
|
5146
|
+
return;
|
|
5147
|
+
}
|
|
5148
|
+
const message = notification.toMail(notifiable);
|
|
5149
|
+
if (!message) {
|
|
5150
|
+
return;
|
|
5151
|
+
}
|
|
5152
|
+
if (message.markdown) {
|
|
5153
|
+
await this.mailer.send(buildMarkdownMailMessage({
|
|
5154
|
+
to: String(routed),
|
|
5155
|
+
subject: message.subject,
|
|
5156
|
+
markdown: message.markdown
|
|
5157
|
+
}));
|
|
5158
|
+
return;
|
|
5159
|
+
}
|
|
5160
|
+
await this.mailer.send({
|
|
5161
|
+
to: String(routed),
|
|
5162
|
+
subject: message.subject,
|
|
5163
|
+
body: message.body ?? "",
|
|
5164
|
+
...message.html ? { html: message.html } : {}
|
|
5165
|
+
});
|
|
5166
|
+
}
|
|
5167
|
+
async sendDatabase(notifiable, notification) {
|
|
5168
|
+
if (!this.databaseStore) {
|
|
5169
|
+
return;
|
|
5170
|
+
}
|
|
5171
|
+
const payload = notification.toDatabase(notifiable);
|
|
5172
|
+
if (!payload) {
|
|
5173
|
+
return;
|
|
5174
|
+
}
|
|
5175
|
+
await this.databaseStore.create({
|
|
5176
|
+
userId: Number(notifiable.getNotificationKey()),
|
|
5177
|
+
...payload
|
|
5178
|
+
});
|
|
5179
|
+
}
|
|
5180
|
+
}
|
|
5181
|
+
function createNotificationDispatcher(mailer2, databaseStore) {
|
|
5182
|
+
return new NotificationDispatcher(mailer2, databaseStore ?? null);
|
|
5183
|
+
}
|
|
5184
|
+
// ../../src/core/notifications/notification.ts
|
|
5185
|
+
class Notification {
|
|
5186
|
+
toMail(_notifiable) {
|
|
5187
|
+
return null;
|
|
5188
|
+
}
|
|
5189
|
+
toDatabase(_notifiable) {
|
|
5190
|
+
return null;
|
|
5191
|
+
}
|
|
5192
|
+
}
|
|
4863
5193
|
// ../../src/core/queue/index.ts
|
|
4864
5194
|
class Job {
|
|
4865
5195
|
maxAttempts;
|
|
@@ -5363,6 +5693,7 @@ function validateObject(payload, schema) {
|
|
|
5363
5693
|
return output;
|
|
5364
5694
|
}
|
|
5365
5695
|
export {
|
|
5696
|
+
wrapMarkdownMailLayout,
|
|
5366
5697
|
withMigrationLock,
|
|
5367
5698
|
withMiddleware,
|
|
5368
5699
|
withErrorHandling,
|
|
@@ -5370,10 +5701,12 @@ export {
|
|
|
5370
5701
|
validateObject,
|
|
5371
5702
|
toResourceCollection,
|
|
5372
5703
|
toPaginatedResourceCollection,
|
|
5704
|
+
stripMarkdown,
|
|
5373
5705
|
stringRule,
|
|
5374
5706
|
storageFacade as storage,
|
|
5375
5707
|
setActiveApplicationContext,
|
|
5376
5708
|
serializeDate,
|
|
5709
|
+
sendMarkdownMail,
|
|
5377
5710
|
securedBindRouteModelByKey,
|
|
5378
5711
|
securedBindRouteModel,
|
|
5379
5712
|
runWithDatabaseConnection,
|
|
@@ -5396,6 +5729,7 @@ export {
|
|
|
5396
5729
|
resolveApplicationCache,
|
|
5397
5730
|
resolveApplicationAuth,
|
|
5398
5731
|
required,
|
|
5732
|
+
renderMarkdownMail,
|
|
5399
5733
|
registerShutdownHandler,
|
|
5400
5734
|
registerModelRepository,
|
|
5401
5735
|
readSubmittedCsrfTokenFromBody,
|
|
@@ -5409,9 +5743,13 @@ export {
|
|
|
5409
5743
|
paginatedResponse,
|
|
5410
5744
|
normalizeMetricPath,
|
|
5411
5745
|
noContentResponse,
|
|
5746
|
+
morphTo,
|
|
5747
|
+
morphOne,
|
|
5748
|
+
morphMany,
|
|
5412
5749
|
minLength,
|
|
5413
5750
|
migrateDatabase,
|
|
5414
5751
|
maxLength,
|
|
5752
|
+
markdownToHtml,
|
|
5415
5753
|
mailer,
|
|
5416
5754
|
mail,
|
|
5417
5755
|
log,
|
|
@@ -5423,6 +5761,9 @@ export {
|
|
|
5423
5761
|
isEtagEnabled,
|
|
5424
5762
|
installGracefulShutdownSignals,
|
|
5425
5763
|
inferReferencedTable,
|
|
5764
|
+
indexMorphToRelation,
|
|
5765
|
+
indexMorphOneRelation,
|
|
5766
|
+
indexMorphManyRelation,
|
|
5426
5767
|
indexHasOneRelation,
|
|
5427
5768
|
indexHasManyRelation,
|
|
5428
5769
|
indexBelongsToRelation,
|
|
@@ -5452,6 +5793,7 @@ export {
|
|
|
5452
5793
|
createQueueWorker,
|
|
5453
5794
|
createQueue,
|
|
5454
5795
|
createProductionQueue,
|
|
5796
|
+
createNotificationDispatcher,
|
|
5455
5797
|
createMetricsMiddleware,
|
|
5456
5798
|
createMemoryThrottleMiddleware,
|
|
5457
5799
|
createLoginThrottleMiddleware,
|
|
@@ -5467,6 +5809,8 @@ export {
|
|
|
5467
5809
|
composeMiddleware,
|
|
5468
5810
|
compileBlueprint,
|
|
5469
5811
|
cache,
|
|
5812
|
+
buildSmtpPayload,
|
|
5813
|
+
buildMarkdownMailMessage,
|
|
5470
5814
|
bindDatabaseConnection2 as bindDatabaseConnection,
|
|
5471
5815
|
belongsToMany,
|
|
5472
5816
|
belongsTo,
|
|
@@ -5496,6 +5840,8 @@ export {
|
|
|
5496
5840
|
PostgresGrammar,
|
|
5497
5841
|
PolicyGate,
|
|
5498
5842
|
Policy,
|
|
5843
|
+
NotificationDispatcher,
|
|
5844
|
+
Notification,
|
|
5499
5845
|
NotFoundError,
|
|
5500
5846
|
MySqlGrammar,
|
|
5501
5847
|
Model,
|