@getstrata/core 0.5.12 → 0.5.13
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/admin/formatValue.d.ts +3 -0
- package/dist/core/admin/index.d.ts +3 -0
- package/dist/core/admin/registry.d.ts +10 -0
- package/dist/core/admin/types.d.ts +24 -0
- package/dist/core/mail/markdownMailable.d.ts +1 -2
- package/dist/core/notifications/notification.d.ts +1 -1
- package/dist/core/queue/failedJobService.d.ts +1 -0
- package/dist/core/queue/publicQueue.d.ts +2 -1
- package/dist/entries/queue/createAppQueue.js +7 -3
- package/dist/entries/queue/failedJobService.js +6 -0
- package/dist/entries/queue/publicQueue.js +8 -3
- package/dist/entries/queue/queueMetrics.js +7 -3
- package/dist/framework/public-api.d.ts +5 -3
- package/dist/index.js +70 -5
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AdminResource, AdminResourceDefinition } from "./types.ts";
|
|
2
|
+
declare class AdminResourceRegistry {
|
|
3
|
+
private readonly resources;
|
|
4
|
+
register<TEntity extends object>(resource: AdminResource<TEntity>): void;
|
|
5
|
+
get(name: string): AdminResource<object> | undefined;
|
|
6
|
+
list(): AdminResourceDefinition[];
|
|
7
|
+
all(): AdminResource<object>[];
|
|
8
|
+
clear(): void;
|
|
9
|
+
}
|
|
10
|
+
export { AdminResourceRegistry };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PaginatedResult } from "../pagination/index.ts";
|
|
2
|
+
type AdminColumnType = "text" | "number" | "boolean" | "datetime" | "code";
|
|
3
|
+
interface AdminColumn {
|
|
4
|
+
key: string;
|
|
5
|
+
label: string;
|
|
6
|
+
type?: AdminColumnType;
|
|
7
|
+
}
|
|
8
|
+
interface AdminResourceHandlers<TEntity extends object> {
|
|
9
|
+
paginate(options: {
|
|
10
|
+
page: number;
|
|
11
|
+
perPage: number;
|
|
12
|
+
}): Promise<PaginatedResult<TEntity>>;
|
|
13
|
+
findById?(id: number): Promise<TEntity | null>;
|
|
14
|
+
}
|
|
15
|
+
interface AdminResourceDefinition {
|
|
16
|
+
name: string;
|
|
17
|
+
label: string;
|
|
18
|
+
labelPlural: string;
|
|
19
|
+
columns: AdminColumn[];
|
|
20
|
+
}
|
|
21
|
+
interface AdminResource<TEntity extends object> extends AdminResourceDefinition {
|
|
22
|
+
handlers: AdminResourceHandlers<TEntity>;
|
|
23
|
+
}
|
|
24
|
+
export type { AdminColumn, AdminColumnType, AdminResource, AdminResourceDefinition, AdminResourceHandlers, };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { MailMessage } from "./mailer.ts";
|
|
2
|
-
import type { Mailer } from "./mailer.ts";
|
|
1
|
+
import type { Mailer, MailMessage } from "./mailer.ts";
|
|
3
2
|
import { type MarkdownMailLayoutOptions } from "./markdownMail.ts";
|
|
4
3
|
interface MarkdownMailableInput {
|
|
5
4
|
to: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DatabaseNotificationPayload, MailNotificationMessage, NotificationChannelName } from "./types.ts";
|
|
2
2
|
declare abstract class Notification<TNotifiable = unknown> {
|
|
3
|
-
|
|
3
|
+
via(_notifiable: TNotifiable): NotificationChannelName[];
|
|
4
4
|
toMail(_notifiable: TNotifiable): MailNotificationMessage | null;
|
|
5
5
|
toDatabase(_notifiable: TNotifiable): DatabaseNotificationPayload | null;
|
|
6
6
|
}
|
|
@@ -10,6 +10,7 @@ declare class FailedJobService {
|
|
|
10
10
|
}): Promise<FailedJobRecord>;
|
|
11
11
|
listRecent(limit?: number): Promise<FailedJobRecord[]>;
|
|
12
12
|
retry(id: number): Promise<FailedJobRecord>;
|
|
13
|
+
delete(id: number): Promise<void>;
|
|
13
14
|
flush(): Promise<number>;
|
|
14
15
|
}
|
|
15
16
|
export default FailedJobService;
|
|
@@ -2,6 +2,7 @@ import FailedJobRepository from "./failedJobRepository.ts";
|
|
|
2
2
|
import FailedJobService from "./failedJobService.ts";
|
|
3
3
|
import type { Job, Queue } from "./index.ts";
|
|
4
4
|
import { jobRegistry } from "./jobRegistry.ts";
|
|
5
|
+
import { runQueueJob } from "./jobRunner.ts";
|
|
5
6
|
import { QueueWorker, RedisQueue } from "./redisQueue.ts";
|
|
6
7
|
import { ResilientQueue } from "./resilientQueue.ts";
|
|
7
8
|
declare function createFailedJobService(): FailedJobService;
|
|
@@ -12,4 +13,4 @@ declare function createProductionQueue(driver: "sync" | "async" | "redis", optio
|
|
|
12
13
|
registerJobs?: () => void;
|
|
13
14
|
}): Queue;
|
|
14
15
|
declare function createQueueWorker(redisUrl: string, failedJobs?: FailedJobService): QueueWorker;
|
|
15
|
-
export { createFailedJobService, createProductionQueue, createQueueWorker, createTrackedJob, FailedJobRepository, FailedJobService, jobRegistry, QueueWorker, RedisQueue, ResilientQueue, };
|
|
16
|
+
export { createFailedJobService, createProductionQueue, createQueueWorker, createTrackedJob, FailedJobRepository, FailedJobService, jobRegistry, QueueWorker, RedisQueue, ResilientQueue, runQueueJob, };
|
|
@@ -2773,6 +2773,12 @@ class FailedJobService {
|
|
|
2773
2773
|
await this.repository.deleteById(id);
|
|
2774
2774
|
return failedJob;
|
|
2775
2775
|
}
|
|
2776
|
+
async delete(id) {
|
|
2777
|
+
const deleted = await this.repository.deleteById(id);
|
|
2778
|
+
if (!deleted) {
|
|
2779
|
+
throw new Error(`Failed job ${id} not found.`);
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2776
2782
|
async flush() {
|
|
2777
2783
|
const jobs = await this.repository.findAll();
|
|
2778
2784
|
let deleted = 0;
|
|
@@ -2786,9 +2792,6 @@ class FailedJobService {
|
|
|
2786
2792
|
}
|
|
2787
2793
|
var failedJobService_default = FailedJobService;
|
|
2788
2794
|
|
|
2789
|
-
// ../../src/core/queue/redisQueue.ts
|
|
2790
|
-
var {RedisClient } = globalThis.Bun;
|
|
2791
|
-
|
|
2792
2795
|
// ../../src/config/queue.ts
|
|
2793
2796
|
var queueConfig = {
|
|
2794
2797
|
driver: process.env.QUEUE_DRIVER === "redis" || process.env.QUEUE_DRIVER === "async" || process.env.QUEUE_DRIVER === "sync" ? process.env.QUEUE_DRIVER : DEFAULT_QUEUE_DRIVER,
|
|
@@ -2827,6 +2830,7 @@ async function runQueueJob(envelope, failedJobs) {
|
|
|
2827
2830
|
}
|
|
2828
2831
|
|
|
2829
2832
|
// ../../src/core/queue/redisQueue.ts
|
|
2833
|
+
var {RedisClient } = globalThis.Bun;
|
|
2830
2834
|
var QUEUE_LIST_KEY = "workhub:queue:default";
|
|
2831
2835
|
var QUEUE_HIGH_KEY = "workhub:queue:high";
|
|
2832
2836
|
var QUEUE_LOW_KEY = "workhub:queue:low";
|
|
@@ -24,6 +24,12 @@ class FailedJobService {
|
|
|
24
24
|
await this.repository.deleteById(id);
|
|
25
25
|
return failedJob;
|
|
26
26
|
}
|
|
27
|
+
async delete(id) {
|
|
28
|
+
const deleted = await this.repository.deleteById(id);
|
|
29
|
+
if (!deleted) {
|
|
30
|
+
throw new Error(`Failed job ${id} not found.`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
27
33
|
async flush() {
|
|
28
34
|
const jobs = await this.repository.findAll();
|
|
29
35
|
let deleted = 0;
|
|
@@ -2375,6 +2375,12 @@ class FailedJobService {
|
|
|
2375
2375
|
await this.repository.deleteById(id);
|
|
2376
2376
|
return failedJob;
|
|
2377
2377
|
}
|
|
2378
|
+
async delete(id) {
|
|
2379
|
+
const deleted = await this.repository.deleteById(id);
|
|
2380
|
+
if (!deleted) {
|
|
2381
|
+
throw new Error(`Failed job ${id} not found.`);
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2378
2384
|
async flush() {
|
|
2379
2385
|
const jobs = await this.repository.findAll();
|
|
2380
2386
|
let deleted = 0;
|
|
@@ -2416,9 +2422,6 @@ class JobRegistry {
|
|
|
2416
2422
|
}
|
|
2417
2423
|
var jobRegistry = new JobRegistry;
|
|
2418
2424
|
|
|
2419
|
-
// ../../src/core/queue/redisQueue.ts
|
|
2420
|
-
var {RedisClient } = globalThis.Bun;
|
|
2421
|
-
|
|
2422
2425
|
// ../../src/bootstrap/config.ts
|
|
2423
2426
|
var CORE_QUEUE_TOKEN = "core.queue";
|
|
2424
2427
|
var CORE_POLICY_GATE_TOKEN = "core.policyGate";
|
|
@@ -2464,6 +2467,7 @@ async function runQueueJob(envelope, failedJobs) {
|
|
|
2464
2467
|
}
|
|
2465
2468
|
|
|
2466
2469
|
// ../../src/core/queue/redisQueue.ts
|
|
2470
|
+
var {RedisClient } = globalThis.Bun;
|
|
2467
2471
|
var QUEUE_LIST_KEY = "workhub:queue:default";
|
|
2468
2472
|
var QUEUE_HIGH_KEY = "workhub:queue:high";
|
|
2469
2473
|
var QUEUE_LOW_KEY = "workhub:queue:low";
|
|
@@ -2637,6 +2641,7 @@ function createQueueWorker(redisUrl, failedJobs = createFailedJobService()) {
|
|
|
2637
2641
|
return new QueueWorker(redisUrl, failedJobs);
|
|
2638
2642
|
}
|
|
2639
2643
|
export {
|
|
2644
|
+
runQueueJob,
|
|
2640
2645
|
jobRegistry,
|
|
2641
2646
|
createTrackedJob,
|
|
2642
2647
|
createQueueWorker,
|
|
@@ -2783,6 +2783,12 @@ class FailedJobService {
|
|
|
2783
2783
|
await this.repository.deleteById(id);
|
|
2784
2784
|
return failedJob;
|
|
2785
2785
|
}
|
|
2786
|
+
async delete(id) {
|
|
2787
|
+
const deleted = await this.repository.deleteById(id);
|
|
2788
|
+
if (!deleted) {
|
|
2789
|
+
throw new Error(`Failed job ${id} not found.`);
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2786
2792
|
async flush() {
|
|
2787
2793
|
const jobs = await this.repository.findAll();
|
|
2788
2794
|
let deleted = 0;
|
|
@@ -2796,9 +2802,6 @@ class FailedJobService {
|
|
|
2796
2802
|
}
|
|
2797
2803
|
var failedJobService_default = FailedJobService;
|
|
2798
2804
|
|
|
2799
|
-
// ../../src/core/queue/redisQueue.ts
|
|
2800
|
-
var {RedisClient } = globalThis.Bun;
|
|
2801
|
-
|
|
2802
2805
|
// ../../src/core/queue/jobRunner.ts
|
|
2803
2806
|
async function runQueueJob(envelope, failedJobs) {
|
|
2804
2807
|
const job = jobRegistry.create(envelope.name);
|
|
@@ -2830,6 +2833,7 @@ async function runQueueJob(envelope, failedJobs) {
|
|
|
2830
2833
|
}
|
|
2831
2834
|
|
|
2832
2835
|
// ../../src/core/queue/redisQueue.ts
|
|
2836
|
+
var {RedisClient } = globalThis.Bun;
|
|
2833
2837
|
var QUEUE_LIST_KEY = "workhub:queue:default";
|
|
2834
2838
|
var QUEUE_HIGH_KEY = "workhub:queue:high";
|
|
2835
2839
|
var QUEUE_LOW_KEY = "workhub:queue:low";
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
export { resolveApplicationAuth, resolveApplicationCache, resolveApplicationConfig, resolveApplicationDependencies, resolveApplicationLogger, resolveApplicationPolicyGate, resolveApplicationQueue, setActiveApplicationContext, } from "../bootstrap/applicationRegistry.ts";
|
|
6
6
|
export type { ServiceProvider } from "../bootstrap/contracts.ts";
|
|
7
7
|
export { ConfigStore, resolveService, ServiceContainer, } from "../bootstrap/contracts.ts";
|
|
8
|
+
export type { AdminColumn, AdminColumnType, AdminResource, AdminResourceDefinition, AdminResourceHandlers, } from "../core/admin/index.ts";
|
|
9
|
+
export { AdminResourceRegistry, formatAdminValue, } from "../core/admin/index.ts";
|
|
8
10
|
export type { AbilityChecker } from "../core/auth/abilityChecker.ts";
|
|
9
11
|
export type { AuthUser } from "../core/auth/authContext.ts";
|
|
10
12
|
export { currentAuthUser, runWithAuthUser } from "../core/auth/authContext.ts";
|
|
@@ -61,14 +63,14 @@ export type { MarkdownMailLayoutOptions, RenderedMarkdownMail } from "../core/ma
|
|
|
61
63
|
export { markdownToHtml, renderMarkdownMail, stripMarkdown, wrapMarkdownMailLayout, } from "../core/mail/markdownMail.ts";
|
|
62
64
|
export type { MarkdownMailableInput } from "../core/mail/markdownMailable.ts";
|
|
63
65
|
export { buildMarkdownMailMessage, sendMarkdownMail } from "../core/mail/markdownMailable.ts";
|
|
64
|
-
export type { DatabaseNotificationPayload, DatabaseNotificationStore, MailNotificationMessage, Notifiable, NotificationChannelName, } from "../core/notifications/index.ts";
|
|
65
|
-
export { createNotificationDispatcher, Notification, NotificationDispatcher, } from "../core/notifications/index.ts";
|
|
66
66
|
export type { MetricLabels } from "../core/metrics/prometheus.ts";
|
|
67
67
|
export { PrometheusRegistry, prometheusRegistry } from "../core/metrics/prometheus.ts";
|
|
68
|
+
export type { DatabaseNotificationPayload, DatabaseNotificationStore, MailNotificationMessage, Notifiable, NotificationChannelName, } from "../core/notifications/index.ts";
|
|
69
|
+
export { createNotificationDispatcher, Notification, NotificationDispatcher, } from "../core/notifications/index.ts";
|
|
68
70
|
export type { CursorPaginatedResult, PaginatedResult, PaginationMeta, } from "../core/pagination/index.ts";
|
|
69
71
|
export type { Queue, QueuePriority } from "../core/queue/index.ts";
|
|
70
72
|
export { AsyncQueue, createQueue, Job, SyncQueue } from "../core/queue/index.ts";
|
|
71
|
-
export { createFailedJobService, createProductionQueue, createQueueWorker, createTrackedJob, FailedJobRepository, FailedJobService, jobRegistry, QueueWorker, RedisQueue, ResilientQueue, } from "../core/queue/publicQueue.ts";
|
|
73
|
+
export { createFailedJobService, createProductionQueue, createQueueWorker, createTrackedJob, FailedJobRepository, FailedJobService, jobRegistry, QueueWorker, RedisQueue, ResilientQueue, runQueueJob, } from "../core/queue/publicQueue.ts";
|
|
72
74
|
export type { ScheduledTask } from "../core/scheduler/schedule.ts";
|
|
73
75
|
export { appSchedule, runDueScheduledTasks, Schedule } from "../core/scheduler/schedule.ts";
|
|
74
76
|
export type { StorageDriver } from "../core/storage/storage.ts";
|
package/dist/index.js
CHANGED
|
@@ -149,6 +149,56 @@ function resolveApplicationLogger() {
|
|
|
149
149
|
function resolveApplicationDependencies() {
|
|
150
150
|
return requireActiveApplicationContext().dependencies;
|
|
151
151
|
}
|
|
152
|
+
// ../../src/core/admin/formatValue.ts
|
|
153
|
+
function formatAdminValue(value, type = "text") {
|
|
154
|
+
if (value === null || value === undefined) {
|
|
155
|
+
return "";
|
|
156
|
+
}
|
|
157
|
+
if (type === "boolean") {
|
|
158
|
+
return value ? "yes" : "no";
|
|
159
|
+
}
|
|
160
|
+
if (type === "number") {
|
|
161
|
+
return String(value);
|
|
162
|
+
}
|
|
163
|
+
if (type === "datetime") {
|
|
164
|
+
if (value instanceof Date) {
|
|
165
|
+
return value.toISOString();
|
|
166
|
+
}
|
|
167
|
+
return String(value);
|
|
168
|
+
}
|
|
169
|
+
if (type === "code") {
|
|
170
|
+
if (typeof value === "string") {
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
return JSON.stringify(value, null, 2);
|
|
174
|
+
}
|
|
175
|
+
if (typeof value === "object") {
|
|
176
|
+
return JSON.stringify(value);
|
|
177
|
+
}
|
|
178
|
+
return String(value);
|
|
179
|
+
}
|
|
180
|
+
// ../../src/core/admin/registry.ts
|
|
181
|
+
class AdminResourceRegistry {
|
|
182
|
+
resources = new Map;
|
|
183
|
+
register(resource) {
|
|
184
|
+
if (this.resources.has(resource.name)) {
|
|
185
|
+
throw new Error(`Admin resource "${resource.name}" is already registered.`);
|
|
186
|
+
}
|
|
187
|
+
this.resources.set(resource.name, resource);
|
|
188
|
+
}
|
|
189
|
+
get(name) {
|
|
190
|
+
return this.resources.get(name);
|
|
191
|
+
}
|
|
192
|
+
list() {
|
|
193
|
+
return [...this.resources.values()].map(({ handlers: _handlers, ...definition }) => definition);
|
|
194
|
+
}
|
|
195
|
+
all() {
|
|
196
|
+
return [...this.resources.values()];
|
|
197
|
+
}
|
|
198
|
+
clear() {
|
|
199
|
+
this.resources.clear();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
152
202
|
// ../../src/core/auth/authContext.ts
|
|
153
203
|
import { AsyncLocalStorage } from "async_hooks";
|
|
154
204
|
var authContext = new AsyncLocalStorage;
|
|
@@ -2877,7 +2927,12 @@ async function defaultSmtpTransport(config, message) {
|
|
|
2877
2927
|
}
|
|
2878
2928
|
}
|
|
2879
2929
|
function buildSmtpPayload(from, message) {
|
|
2880
|
-
const headers = [
|
|
2930
|
+
const headers = [
|
|
2931
|
+
`From: ${from}`,
|
|
2932
|
+
`To: ${message.to}`,
|
|
2933
|
+
`Subject: ${message.subject}`,
|
|
2934
|
+
"MIME-Version: 1.0"
|
|
2935
|
+
];
|
|
2881
2936
|
if (message.html) {
|
|
2882
2937
|
const boundary = `strata-${Date.now().toString(36)}`;
|
|
2883
2938
|
headers.push(`Content-Type: multipart/alternative; boundary="${boundary}"`);
|
|
@@ -5183,6 +5238,9 @@ function createNotificationDispatcher(mailer2, databaseStore) {
|
|
|
5183
5238
|
}
|
|
5184
5239
|
// ../../src/core/notifications/notification.ts
|
|
5185
5240
|
class Notification {
|
|
5241
|
+
via(_notifiable) {
|
|
5242
|
+
throw new Error("Notification subclasses must implement via().");
|
|
5243
|
+
}
|
|
5186
5244
|
toMail(_notifiable) {
|
|
5187
5245
|
return null;
|
|
5188
5246
|
}
|
|
@@ -5256,6 +5314,12 @@ class FailedJobService {
|
|
|
5256
5314
|
await this.repository.deleteById(id);
|
|
5257
5315
|
return failedJob;
|
|
5258
5316
|
}
|
|
5317
|
+
async delete(id) {
|
|
5318
|
+
const deleted = await this.repository.deleteById(id);
|
|
5319
|
+
if (!deleted) {
|
|
5320
|
+
throw new Error(`Failed job ${id} not found.`);
|
|
5321
|
+
}
|
|
5322
|
+
}
|
|
5259
5323
|
async flush() {
|
|
5260
5324
|
const jobs = await this.repository.findAll();
|
|
5261
5325
|
let deleted = 0;
|
|
@@ -5297,9 +5361,6 @@ class JobRegistry {
|
|
|
5297
5361
|
}
|
|
5298
5362
|
var jobRegistry = new JobRegistry;
|
|
5299
5363
|
|
|
5300
|
-
// ../../src/core/queue/redisQueue.ts
|
|
5301
|
-
var {RedisClient: RedisClient3 } = globalThis.Bun;
|
|
5302
|
-
|
|
5303
5364
|
// ../../src/config/queue.ts
|
|
5304
5365
|
var queueConfig = {
|
|
5305
5366
|
driver: process.env.QUEUE_DRIVER === "redis" || process.env.QUEUE_DRIVER === "async" || process.env.QUEUE_DRIVER === "sync" ? process.env.QUEUE_DRIVER : DEFAULT_QUEUE_DRIVER,
|
|
@@ -5338,6 +5399,7 @@ async function runQueueJob(envelope, failedJobs) {
|
|
|
5338
5399
|
}
|
|
5339
5400
|
|
|
5340
5401
|
// ../../src/core/queue/redisQueue.ts
|
|
5402
|
+
var {RedisClient: RedisClient3 } = globalThis.Bun;
|
|
5341
5403
|
var QUEUE_LIST_KEY = "workhub:queue:default";
|
|
5342
5404
|
var QUEUE_HIGH_KEY = "workhub:queue:high";
|
|
5343
5405
|
var QUEUE_LOW_KEY = "workhub:queue:low";
|
|
@@ -5712,6 +5774,7 @@ export {
|
|
|
5712
5774
|
runWithDatabaseConnection,
|
|
5713
5775
|
runWithAuthUser,
|
|
5714
5776
|
runSeedersFromDirectory,
|
|
5777
|
+
runQueueJob,
|
|
5715
5778
|
runInTransaction,
|
|
5716
5779
|
runGracefulShutdown,
|
|
5717
5780
|
runDueScheduledTasks,
|
|
@@ -5776,6 +5839,7 @@ export {
|
|
|
5776
5839
|
getMigrationStatus,
|
|
5777
5840
|
getActiveDatabaseConnection,
|
|
5778
5841
|
freshDatabase,
|
|
5842
|
+
formatAdminValue,
|
|
5779
5843
|
filterMassAssignable,
|
|
5780
5844
|
events,
|
|
5781
5845
|
etagFromResource,
|
|
@@ -5865,5 +5929,6 @@ export {
|
|
|
5865
5929
|
Blueprint,
|
|
5866
5930
|
baseRepository_default as BaseRepository,
|
|
5867
5931
|
BadRequestError,
|
|
5868
|
-
AsyncQueue
|
|
5932
|
+
AsyncQueue,
|
|
5933
|
+
AdminResourceRegistry
|
|
5869
5934
|
};
|