@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.
@@ -0,0 +1,3 @@
1
+ import type { AdminColumnType } from "./types.ts";
2
+ declare function formatAdminValue(value: unknown, type?: AdminColumnType): string;
3
+ export { formatAdminValue };
@@ -0,0 +1,3 @@
1
+ export { formatAdminValue } from "./formatValue.ts";
2
+ export { AdminResourceRegistry } from "./registry.ts";
3
+ export type { AdminColumn, AdminColumnType, AdminResource, AdminResourceDefinition, AdminResourceHandlers, } from "./types.ts";
@@ -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
- abstract via(notifiable: TNotifiable): NotificationChannelName[];
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 = [`From: ${from}`, `To: ${message.to}`, `Subject: ${message.subject}`, "MIME-Version: 1.0"];
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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getstrata/core",
3
- "version": "0.5.12",
3
+ "version": "0.5.13",
4
4
  "description": "Strata — Laravel-inspired Bun framework public API",
5
5
  "type": "module",
6
6
  "license": "MIT",