@getstrata/core 0.5.45 → 0.5.47
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.
|
@@ -1,78 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// ../../src/core/errors/http.ts
|
|
3
|
-
class HttpError extends Error {
|
|
4
|
-
status;
|
|
5
|
-
details;
|
|
6
|
-
constructor(status, message, details) {
|
|
7
|
-
super(message);
|
|
8
|
-
this.name = new.target.name;
|
|
9
|
-
this.status = status;
|
|
10
|
-
this.details = details;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
class BadRequestError extends HttpError {
|
|
15
|
-
constructor(message = "Bad Request", details) {
|
|
16
|
-
super(400, message, details);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
class NotFoundError extends HttpError {
|
|
21
|
-
constructor(message = "Not Found", details) {
|
|
22
|
-
super(404, message, details);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
class ConflictError extends HttpError {
|
|
27
|
-
constructor(message = "Conflict", details) {
|
|
28
|
-
super(409, message, details);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
class UnprocessableEntityError extends HttpError {
|
|
33
|
-
constructor(message = "Unprocessable Entity", details) {
|
|
34
|
-
super(422, message, details);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
class ValidationError extends HttpError {
|
|
39
|
-
constructor(message = "Validation failed", details) {
|
|
40
|
-
super(422, message, details);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
class ForbiddenError extends HttpError {
|
|
45
|
-
constructor(message = "Forbidden", details) {
|
|
46
|
-
super(403, message, details);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
class UnauthorizedError extends HttpError {
|
|
51
|
-
constructor(message = "Unauthorized", details) {
|
|
52
|
-
super(401, message, details);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
class PayloadTooLargeError extends HttpError {
|
|
57
|
-
constructor(message = "Payload Too Large", details) {
|
|
58
|
-
super(413, message, details);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
class PreconditionFailedError extends HttpError {
|
|
63
|
-
constructor(message = "Precondition Failed", details) {
|
|
64
|
-
super(412, message, details);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
export {
|
|
68
|
-
ValidationError,
|
|
69
|
-
UnprocessableEntityError,
|
|
70
|
-
UnauthorizedError,
|
|
71
|
-
PreconditionFailedError,
|
|
72
|
-
PayloadTooLargeError,
|
|
73
|
-
NotFoundError,
|
|
74
|
-
HttpError,
|
|
75
|
-
ForbiddenError,
|
|
76
|
-
ConflictError,
|
|
77
|
-
BadRequestError
|
|
78
|
-
};
|
|
1
|
+
export * from "../../index.js";
|
|
@@ -1,152 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// ../../src/core/mail/markdownMail.ts
|
|
3
|
-
function escapeHtml(value) {
|
|
4
|
-
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
5
|
-
}
|
|
6
|
-
function stripMarkdown(markdown) {
|
|
7
|
-
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, `
|
|
8
|
-
|
|
9
|
-
`).trim();
|
|
10
|
-
}
|
|
11
|
-
function markdownToHtml(markdown) {
|
|
12
|
-
const escaped = markdown.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
13
|
-
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) => {
|
|
14
|
-
if (block.startsWith("<")) {
|
|
15
|
-
return block;
|
|
16
|
-
}
|
|
17
|
-
return `<p>${block.replace(/\n/g, " ")}</p>`;
|
|
18
|
-
}).join(`
|
|
19
|
-
`);
|
|
20
|
-
}
|
|
21
|
-
function wrapMarkdownMailLayout(bodyHtml, options = {}) {
|
|
22
|
-
const title = escapeHtml(options.title ?? "GetStrata");
|
|
23
|
-
const preview = escapeHtml(options.preview ?? "");
|
|
24
|
-
const footer = escapeHtml(options.footer ?? "Sent by GetStrata");
|
|
25
|
-
return `<!DOCTYPE html>
|
|
26
|
-
<html lang="en">
|
|
27
|
-
<head>
|
|
28
|
-
<meta charset="utf-8">
|
|
29
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
30
|
-
<title>${title}</title>
|
|
31
|
-
<style>
|
|
32
|
-
body { font-family: system-ui, sans-serif; line-height: 1.5; color: #111827; background: #f9fafb; margin: 0; padding: 24px; }
|
|
33
|
-
.container { max-width: 640px; margin: 0 auto; background: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden; }
|
|
34
|
-
.header { padding: 20px 24px; border-bottom: 1px solid #e5e7eb; font-weight: 600; }
|
|
35
|
-
.content { padding: 24px; }
|
|
36
|
-
.footer { padding: 16px 24px; border-top: 1px solid #e5e7eb; color: #6b7280; font-size: 14px; }
|
|
37
|
-
a { color: #2563eb; }
|
|
38
|
-
code { background: #f3f4f6; padding: 2px 4px; border-radius: 4px; }
|
|
39
|
-
pre { background: #111827; color: #f9fafb; padding: 12px; border-radius: 6px; overflow-x: auto; }
|
|
40
|
-
</style>
|
|
41
|
-
</head>
|
|
42
|
-
<body>
|
|
43
|
-
${preview ? `<span style="display:none;max-height:0;overflow:hidden;">${preview}</span>` : ""}
|
|
44
|
-
<div class="container">
|
|
45
|
-
<div class="header">${title}</div>
|
|
46
|
-
<div class="content">${bodyHtml}</div>
|
|
47
|
-
<div class="footer">${footer}</div>
|
|
48
|
-
</div>
|
|
49
|
-
</body>
|
|
50
|
-
</html>`;
|
|
51
|
-
}
|
|
52
|
-
function renderMarkdownMail(markdown, options = {}) {
|
|
53
|
-
const bodyHtml = markdownToHtml(markdown.trim());
|
|
54
|
-
const html = wrapMarkdownMailLayout(bodyHtml, options);
|
|
55
|
-
const text = stripMarkdown(markdown);
|
|
56
|
-
return { html, text };
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// ../../src/core/mail/markdownMailable.ts
|
|
60
|
-
function buildMarkdownMailMessage(input) {
|
|
61
|
-
const rendered = renderMarkdownMail(input.markdown, {
|
|
62
|
-
title: input.layout?.title ?? input.subject,
|
|
63
|
-
...input.layout
|
|
64
|
-
});
|
|
65
|
-
return {
|
|
66
|
-
to: input.to,
|
|
67
|
-
subject: input.subject,
|
|
68
|
-
body: rendered.text,
|
|
69
|
-
html: rendered.html
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
async function sendMarkdownMail(mailer, input) {
|
|
73
|
-
await mailer.send(buildMarkdownMailMessage(input));
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// ../../src/core/notifications/dispatcher.ts
|
|
77
|
-
class NotificationDispatcher {
|
|
78
|
-
mailer;
|
|
79
|
-
databaseStore;
|
|
80
|
-
constructor(mailer, databaseStore = null) {
|
|
81
|
-
this.mailer = mailer;
|
|
82
|
-
this.databaseStore = databaseStore;
|
|
83
|
-
}
|
|
84
|
-
async send(notifiable, notification) {
|
|
85
|
-
for (const channel of notification.via(notifiable)) {
|
|
86
|
-
if (channel === "mail") {
|
|
87
|
-
await this.sendMail(notifiable, notification);
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
if (channel === "database") {
|
|
91
|
-
await this.sendDatabase(notifiable, notification);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
async sendMail(notifiable, notification) {
|
|
96
|
-
const routed = notifiable.routeNotificationFor("mail");
|
|
97
|
-
if (routed === null) {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
const message = notification.toMail(notifiable);
|
|
101
|
-
if (!message) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
if (message.markdown) {
|
|
105
|
-
await this.mailer.send(buildMarkdownMailMessage({
|
|
106
|
-
to: String(routed),
|
|
107
|
-
subject: message.subject,
|
|
108
|
-
markdown: message.markdown
|
|
109
|
-
}));
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
await this.mailer.send({
|
|
113
|
-
to: String(routed),
|
|
114
|
-
subject: message.subject,
|
|
115
|
-
body: message.body ?? "",
|
|
116
|
-
...message.html ? { html: message.html } : {}
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
async sendDatabase(notifiable, notification) {
|
|
120
|
-
if (!this.databaseStore) {
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
const payload = notification.toDatabase(notifiable);
|
|
124
|
-
if (!payload) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
await this.databaseStore.create({
|
|
128
|
-
userId: Number(notifiable.getNotificationKey()),
|
|
129
|
-
...payload
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
function createNotificationDispatcher(mailer, databaseStore) {
|
|
134
|
-
return new NotificationDispatcher(mailer, databaseStore ?? null);
|
|
135
|
-
}
|
|
136
|
-
// ../../src/core/notifications/notification.ts
|
|
137
|
-
class Notification {
|
|
138
|
-
via(_notifiable) {
|
|
139
|
-
throw new Error("Notification subclasses must implement via().");
|
|
140
|
-
}
|
|
141
|
-
toMail(_notifiable) {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
toDatabase(_notifiable) {
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
export {
|
|
149
|
-
createNotificationDispatcher,
|
|
150
|
-
NotificationDispatcher,
|
|
151
|
-
Notification
|
|
152
|
-
};
|
|
1
|
+
export * from "../index.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getstrata/core",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.47",
|
|
4
4
|
"description": "Strata — Laravel-inspired Bun framework public API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -722,7 +722,7 @@
|
|
|
722
722
|
"build:bundle": "bun build index.ts --outdir dist --target bun --external bun --external eta",
|
|
723
723
|
"build:types": "tsc -p tsconfig.types.json",
|
|
724
724
|
"prepublishOnly": "bun run build && bun ../../scripts/prepare-core-package-publish.ts",
|
|
725
|
-
"build:subpaths": "bun build entries/auth/abilityChecker.ts entries/auth/membershipMiddleware.ts entries/auth/oauth/oidcProvider.ts entries/auth/oauth/providers.ts entries/auth/oauth/samlProvider.ts entries/auth/oauth/types.ts entries/auth/password.ts entries/auth/scimAuthMiddleware.ts entries/auth/sessionCookie.ts entries/auth/sessionGuard.ts entries/auth/tokenHash.ts entries/audit/exportAuditLogs.ts entries/audit/siemFormatter.ts entries/admin/formatValue.ts entries/admin/registry.ts entries/admin/types.ts entries/cache/tags.ts entries/cache/createCacheStore.ts entries/cache/repository.ts entries/cache/simpleCache.ts entries/cache/simpleCacheStore.ts entries/config/envSchema.ts entries/contracts/serviceTokens.ts entries/contracts/container.ts entries/contracts/di.ts entries/crypto/fieldEncryption.ts entries/crypto/mfaSecret.ts entries/database/
|
|
725
|
+
"build:subpaths": "bun build entries/auth/abilityChecker.ts entries/auth/membershipMiddleware.ts entries/auth/oauth/oidcProvider.ts entries/auth/oauth/providers.ts entries/auth/oauth/samlProvider.ts entries/auth/oauth/types.ts entries/auth/password.ts entries/auth/scimAuthMiddleware.ts entries/auth/sessionCookie.ts entries/auth/sessionGuard.ts entries/auth/tokenHash.ts entries/audit/exportAuditLogs.ts entries/audit/siemFormatter.ts entries/admin/formatValue.ts entries/admin/registry.ts entries/admin/types.ts entries/cache/tags.ts entries/cache/createCacheStore.ts entries/cache/repository.ts entries/cache/simpleCache.ts entries/cache/simpleCacheStore.ts entries/config/envSchema.ts entries/contracts/serviceTokens.ts entries/contracts/container.ts entries/contracts/di.ts entries/crypto/fieldEncryption.ts entries/crypto/mfaSecret.ts entries/database/errors.ts entries/database/factory.ts entries/database/migrations.ts entries/database/migrations/types.ts entries/database/model.ts entries/database/query.ts entries/database/relationships.ts entries/database/seeders.ts entries/database/seeders/types.ts entries/database/schema.ts entries/database/table.ts entries/database/transaction.ts entries/database/types.ts entries/http/authMiddleware.ts entries/http/authorizeMiddleware.ts entries/http/bodySizeLimitMiddleware.ts entries/http/cookies.ts entries/http/contentNegotiation.ts entries/http/conditionalResponse.ts entries/http/corsMiddleware.ts entries/http/csrfMiddleware.ts entries/http/csrfProtection.ts entries/http/csrfToken.ts entries/http/etag.ts entries/http/flashSession.ts entries/http/flashMiddleware.ts entries/http/formRequest.ts entries/http/metricsMiddleware.ts entries/http/loginThrottleMiddleware.ts entries/http/memoryThrottleMiddleware.ts entries/http/pagination.ts entries/http/parseFormBody.ts entries/http/parseMultipartUpload.ts entries/http/requireAbilityMiddleware.ts entries/http/requireAuthMiddleware.ts entries/http/requireGlobalAdminMiddleware.ts entries/http/requireWebAuthMiddleware.ts entries/http/resources.ts entries/http/route.ts entries/http/routeMiddleware.ts entries/http/routeModelBinding.ts entries/http/scimThrottleMiddleware.ts entries/http/securityHeadersMiddleware.ts entries/http/securedRouteModelBinding.ts entries/http/webErrorResponse.ts entries/http/webFormRequest.ts entries/http/throttleMiddleware.ts entries/jobs/dispatchWebhookJob.ts entries/jobs/invalidateCacheTagsJob.ts entries/lifecycle/gracefulShutdown.ts entries/logging/logger.ts entries/logging/requestLoggingMiddleware.ts entries/mail/mailer.ts entries/mail/markdownMail.ts entries/mail/markdownMailable.ts entries/metrics/prometheus.ts entries/openapi/generator.ts entries/openapi/registeredRoute.ts entries/openapi/validate.ts entries/pagination.ts entries/queue.ts entries/queue/createAppQueue.ts entries/queue/failedJobRepository.ts entries/queue/failedJobService.ts entries/queue/jobRunner.ts entries/queue/queueMetrics.ts entries/queue/publicQueue.ts entries/queue/redisQueue.ts entries/queue/types.ts entries/runtime/asyncContextStore.ts entries/scheduler/schedule.ts entries/security/oauthState.ts entries/security/publicReads.ts entries/security/safeFetch.ts entries/security/safeUrl.ts entries/security/scimTenantTokens.ts entries/security/stripeWebhook.ts entries/security/timingSafeCompare.ts entries/security/tokenExpiry.ts entries/security/totp.ts entries/storage/storage.ts entries/tenant/tenantDatabaseScope.ts entries/tenant/databaseTenantContext.ts entries/tracing/tracingMiddleware.ts entries/validation/rules.ts entries/view.ts --outdir dist --root . --target bun --external bun --external eta",
|
|
726
726
|
"build:shims": "bun ../../scripts/write-core-shared-shims.ts"
|
|
727
727
|
},
|
|
728
728
|
"publishConfig": {
|