notifkit 0.1.7 → 0.1.8

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.
Files changed (39) hide show
  1. package/dashboard/README.md +29 -0
  2. package/dashboard/dist/assets/index-7mvXb4bS.js +310 -0
  3. package/dashboard/dist/assets/index-o7L-f3-c.css +1 -0
  4. package/dashboard/dist/favicon.svg +4 -0
  5. package/dashboard/dist/index.html +14 -0
  6. package/dist/index.d.mts +433 -8
  7. package/dist/index.d.mts.map +1 -1
  8. package/dist/index.mjs +2 -2
  9. package/dist/{main-D6SG3Isk.mjs → main-0FHNtN5g.mjs} +2 -2
  10. package/dist/{main-D6SG3Isk.mjs.map → main-0FHNtN5g.mjs.map} +1 -1
  11. package/dist/{main-pFAfCkVX.mjs → main-7KMlWnDx.mjs} +2 -2
  12. package/dist/{main-pFAfCkVX.mjs.map → main-7KMlWnDx.mjs.map} +1 -1
  13. package/dist/{main-Bgi2wWck.mjs → main-B0BcY_JJ.mjs} +2 -2
  14. package/dist/{main-Bgi2wWck.mjs.map → main-B0BcY_JJ.mjs.map} +1 -1
  15. package/dist/{main-CFSukWm8.mjs → main-BAO4kKce.mjs} +366 -26
  16. package/dist/main-BAO4kKce.mjs.map +1 -0
  17. package/dist/{main-CRPxM-O3.mjs → main-BjXgGJBd.mjs} +2 -2
  18. package/dist/{main-CRPxM-O3.mjs.map → main-BjXgGJBd.mjs.map} +1 -1
  19. package/dist/{main-CjbVdUqa.mjs → main-BtXITy0k.mjs} +2 -2
  20. package/dist/{main-CjbVdUqa.mjs.map → main-BtXITy0k.mjs.map} +1 -1
  21. package/dist/{main-Yorxzw0Z.mjs → main-BxqAXTr6.mjs} +2 -2
  22. package/dist/{main-Yorxzw0Z.mjs.map → main-BxqAXTr6.mjs.map} +1 -1
  23. package/dist/{main-DFMHcN_d.mjs → main-zCpvA9Rx.mjs} +2 -2
  24. package/dist/{main-DFMHcN_d.mjs.map → main-zCpvA9Rx.mjs.map} +1 -1
  25. package/dist/{src-CPMwsUCJ.mjs → src-DkvHYM3y.mjs} +76 -19
  26. package/dist/src-DkvHYM3y.mjs.map +1 -0
  27. package/drizzle/0005_admin_users.sql +11 -0
  28. package/drizzle/meta/_journal.json +7 -0
  29. package/package.json +8 -3
  30. package/scripts/create-admin.mjs +67 -0
  31. package/src/config/index.ts +3 -0
  32. package/src/db/schema.ts +13 -0
  33. package/src/repositories/index.ts +82 -1
  34. package/src/services/api/admin-static.ts +224 -0
  35. package/src/services/api/handlers.ts +129 -12
  36. package/src/services/api/main.ts +72 -19
  37. package/src/services/auth/index.ts +103 -0
  38. package/dist/main-CFSukWm8.mjs.map +0 -1
  39. package/dist/src-CPMwsUCJ.mjs.map +0 -1
@@ -7,7 +7,7 @@ import { createHmac, randomUUID, timingSafeEqual } from "node:crypto";
7
7
  import postgres from "postgres";
8
8
  import { drizzle } from "drizzle-orm/postgres-js";
9
9
  import { boolean, check, index, integer, jsonb, pgEnum, pgTable, primaryKey, text, time, timestamp, unique, uuid, varchar } from "drizzle-orm/pg-core";
10
- import { and, desc, eq, inArray, sql } from "drizzle-orm";
10
+ import { and, desc, eq, inArray, or, sql } from "drizzle-orm";
11
11
  import { createInsertSchema, createSelectSchema } from "drizzle-zod";
12
12
  import { migrate } from "drizzle-orm/postgres-js/migrator";
13
13
  import { fileURLToPath } from "url";
@@ -69,6 +69,9 @@ const baseConfigSchema = z.object({
69
69
  REDIS_URL: z.string().url().default("redis://localhost:6379"),
70
70
  DATABASE_URL: z.string().url().default("postgres://platform:platform@localhost:5432/notifkit"),
71
71
  ADMIN_API_KEY: z.string().trim().optional(),
72
+ ADMIN_EMAIL: z.string().trim().email().optional(),
73
+ ADMIN_PASSWORD: z.string().trim().min(6).optional(),
74
+ ADMIN_USERNAME: z.string().trim().optional(),
72
75
  WORKER_CONCURRENCY: z.coerce.number().int().min(1).default(10),
73
76
  QUEUE_MAX_LEN: z.coerce.number().int().min(1).default(1e7),
74
77
  DB_MAX_CONNECTIONS: z.coerce.number().int().min(1).default(2),
@@ -673,10 +676,12 @@ registry.define("notification.ai_pending", NotificationAiPendingPayloadSchema);
673
676
  //#endregion
674
677
  //#region src/db/schema.ts
675
678
  var schema_exports = /* @__PURE__ */ __exportAll({
679
+ adminUsers: () => adminUsers,
676
680
  apiKeyRoleEnum: () => apiKeyRoleEnum,
677
681
  channelEnum: () => channelEnum,
678
682
  contactTopicPreferences: () => contactTopicPreferences,
679
683
  deliveryOutbox: () => deliveryOutbox,
684
+ insertAdminUserSchema: () => insertAdminUserSchema,
680
685
  insertDeliveryOutboxSchema: () => insertDeliveryOutboxSchema,
681
686
  insertMessageLogSchema: () => insertMessageLogSchema,
682
687
  insertProjectApiKeySchema: () => insertProjectApiKeySchema,
@@ -696,6 +701,7 @@ var schema_exports = /* @__PURE__ */ __exportAll({
696
701
  projects: () => projects,
697
702
  quietHours: () => quietHours,
698
703
  scheduledPayloads: () => scheduledPayloads,
704
+ selectAdminUserSchema: () => selectAdminUserSchema,
699
705
  selectDeliveryOutboxSchema: () => selectDeliveryOutboxSchema,
700
706
  selectMessageLogSchema: () => selectMessageLogSchema,
701
707
  selectProjectApiKeySchema: () => selectProjectApiKeySchema,
@@ -941,6 +947,17 @@ const scheduledPayloads = pgTable("scheduled_payloads", {
941
947
  payload: jsonb("payload").notNull(),
942
948
  createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull()
943
949
  });
950
+ const adminUsers = pgTable("admin_users", {
951
+ id: uuid("id").primaryKey().defaultRandom(),
952
+ email: varchar("email").notNull().unique(),
953
+ username: varchar("username").unique(),
954
+ passwordHash: varchar("password_hash").notNull(),
955
+ role: varchar("role").notNull().default("admin"),
956
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
957
+ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull()
958
+ });
959
+ const insertAdminUserSchema = createInsertSchema(adminUsers);
960
+ const selectAdminUserSchema = createSelectSchema(adminUsers);
944
961
  const insertProjectSchema = createInsertSchema(projects);
945
962
  const selectProjectSchema = createSelectSchema(projects);
946
963
  const insertProjectApiKeySchema = createInsertSchema(projectApiKeys);
@@ -2567,6 +2584,46 @@ var SegmentRepository = class {
2567
2584
  `)).map((r) => r.segment);
2568
2585
  }
2569
2586
  };
2587
+ var AdminUserRepository = class {
2588
+ db;
2589
+ constructor(db) {
2590
+ this.db = db;
2591
+ }
2592
+ async findByEmailOrUsername(identifier) {
2593
+ const normalized = identifier.trim().toLowerCase();
2594
+ return (await this.db.select().from(adminUsers).where(or(eq(adminUsers.email, normalized), eq(adminUsers.username, identifier.trim()))).limit(1))[0] ?? null;
2595
+ }
2596
+ async findById(id) {
2597
+ return (await this.db.select().from(adminUsers).where(eq(adminUsers.id, id)).limit(1))[0] ?? null;
2598
+ }
2599
+ async create(data) {
2600
+ return (await this.db.insert(adminUsers).values({
2601
+ email: data.email.trim().toLowerCase(),
2602
+ username: data.username ? data.username.trim() : null,
2603
+ passwordHash: data.passwordHash,
2604
+ role: data.role || "admin"
2605
+ }).returning())[0];
2606
+ }
2607
+ async updatePassword(id, passwordHash) {
2608
+ return (await this.db.update(adminUsers).set({
2609
+ passwordHash,
2610
+ updatedAt: /* @__PURE__ */ new Date()
2611
+ }).where(eq(adminUsers.id, id)).returning()).length > 0;
2612
+ }
2613
+ async list() {
2614
+ return await this.db.select({
2615
+ id: adminUsers.id,
2616
+ email: adminUsers.email,
2617
+ username: adminUsers.username,
2618
+ role: adminUsers.role,
2619
+ createdAt: adminUsers.createdAt,
2620
+ updatedAt: adminUsers.updatedAt
2621
+ }).from(adminUsers).orderBy(adminUsers.createdAt);
2622
+ }
2623
+ async count() {
2624
+ return (await this.db.select({ count: sql`count(*)::int` }).from(adminUsers))[0]?.count ?? 0;
2625
+ }
2626
+ };
2570
2627
  //#endregion
2571
2628
  //#region src/templates/render.ts
2572
2629
  function escapeHtml(unsafe) {
@@ -3402,35 +3459,35 @@ var NotifkitServer = class extends EventEmitter {
3402
3459
  }
3403
3460
  const startupPromises = [];
3404
3461
  if (services.includes("api")) {
3405
- const { startApiServer } = await import("./main-CFSukWm8.mjs");
3462
+ const { startApiServer } = await import("./main-BAO4kKce.mjs");
3406
3463
  startupPromises.push(startApiServer());
3407
3464
  }
3408
3465
  if (services.includes("delivery")) {
3409
- const { startDeliveryWorker } = await import("./main-pFAfCkVX.mjs");
3466
+ const { startDeliveryWorker } = await import("./main-7KMlWnDx.mjs");
3410
3467
  startupPromises.push(startDeliveryWorker());
3411
3468
  }
3412
3469
  if (services.includes("engine")) {
3413
- const { startEngineWorker } = await import("./main-Yorxzw0Z.mjs");
3470
+ const { startEngineWorker } = await import("./main-BxqAXTr6.mjs");
3414
3471
  startupPromises.push(startEngineWorker());
3415
3472
  }
3416
3473
  if (services.includes("enricher")) {
3417
- const { startEnricherWorker } = await import("./main-Bgi2wWck.mjs");
3474
+ const { startEnricherWorker } = await import("./main-B0BcY_JJ.mjs");
3418
3475
  startupPromises.push(startEnricherWorker());
3419
3476
  }
3420
3477
  if (services.includes("scheduler")) {
3421
- const { startSchedulerWorker } = await import("./main-DFMHcN_d.mjs");
3478
+ const { startSchedulerWorker } = await import("./main-zCpvA9Rx.mjs");
3422
3479
  startupPromises.push(startSchedulerWorker());
3423
3480
  }
3424
3481
  if (services.includes("ai")) {
3425
- const { startAiWorker } = await import("./main-D6SG3Isk.mjs");
3482
+ const { startAiWorker } = await import("./main-0FHNtN5g.mjs");
3426
3483
  startupPromises.push(startAiWorker());
3427
3484
  }
3428
3485
  if (services.includes("workflow")) {
3429
- const { startWorkflowWorker } = await import("./main-CjbVdUqa.mjs");
3486
+ const { startWorkflowWorker } = await import("./main-BtXITy0k.mjs");
3430
3487
  startupPromises.push(startWorkflowWorker());
3431
3488
  }
3432
3489
  if (services.includes("events")) {
3433
- const { startEventWorker } = await import("./main-CRPxM-O3.mjs");
3490
+ const { startEventWorker } = await import("./main-BjXgGJBd.mjs");
3434
3491
  startupPromises.push(startEventWorker());
3435
3492
  }
3436
3493
  const handleSignal = async (signal) => {
@@ -3470,35 +3527,35 @@ var NotifkitServer = class extends EventEmitter {
3470
3527
  "events"
3471
3528
  ] : this.options.services;
3472
3529
  if (services.includes("api")) {
3473
- const { stopApiServer } = await import("./main-CFSukWm8.mjs");
3530
+ const { stopApiServer } = await import("./main-BAO4kKce.mjs");
3474
3531
  await stopApiServer();
3475
3532
  }
3476
3533
  if (services.includes("delivery")) {
3477
- const { stopDeliveryWorker } = await import("./main-pFAfCkVX.mjs");
3534
+ const { stopDeliveryWorker } = await import("./main-7KMlWnDx.mjs");
3478
3535
  await stopDeliveryWorker();
3479
3536
  }
3480
3537
  if (services.includes("engine")) {
3481
- const { stopEngineWorker } = await import("./main-Yorxzw0Z.mjs");
3538
+ const { stopEngineWorker } = await import("./main-BxqAXTr6.mjs");
3482
3539
  await stopEngineWorker();
3483
3540
  }
3484
3541
  if (services.includes("enricher")) {
3485
- const { stopEnricherWorker } = await import("./main-Bgi2wWck.mjs");
3542
+ const { stopEnricherWorker } = await import("./main-B0BcY_JJ.mjs");
3486
3543
  await stopEnricherWorker();
3487
3544
  }
3488
3545
  if (services.includes("scheduler")) {
3489
- const { stopSchedulerWorker } = await import("./main-DFMHcN_d.mjs");
3546
+ const { stopSchedulerWorker } = await import("./main-zCpvA9Rx.mjs");
3490
3547
  await stopSchedulerWorker();
3491
3548
  }
3492
3549
  if (services.includes("ai")) {
3493
- const { stopAiWorker } = await import("./main-D6SG3Isk.mjs");
3550
+ const { stopAiWorker } = await import("./main-0FHNtN5g.mjs");
3494
3551
  await stopAiWorker();
3495
3552
  }
3496
3553
  if (services.includes("workflow")) {
3497
- const { stopWorkflowWorker } = await import("./main-CjbVdUqa.mjs");
3554
+ const { stopWorkflowWorker } = await import("./main-BtXITy0k.mjs");
3498
3555
  await stopWorkflowWorker();
3499
3556
  }
3500
3557
  if (services.includes("events")) {
3501
- const { stopEventWorker } = await import("./main-CRPxM-O3.mjs");
3558
+ const { stopEventWorker } = await import("./main-BjXgGJBd.mjs");
3502
3559
  await stopEventWorker();
3503
3560
  }
3504
3561
  if (this.pgContainer) {
@@ -3512,6 +3569,6 @@ var NotifkitServer = class extends EventEmitter {
3512
3569
  }
3513
3570
  };
3514
3571
  //#endregion
3515
- export { childLogger as $, INBOUND_STREAMS as $t, ProjectSettingsCache as A, NotificationRequestedPayloadSchema as At, LUA_RELEASE_LOCK as B, PreferencesSchema as Bt, ProjectRepository as C, DeliveryOptionsSchema as Ct, WorkflowRepository as D, NotificationEnrichedPayloadSchema as Dt, UserRepository as E, NotificationScheduledPayloadSchema as Et, sleep as F, ContactChannelSchema as Ft, normaliseTarget as G, UpdateProjectSchema as Gt, LUA_SCHEDULER_CLAIM as H, SyncTemplatesSchema as Ht, DataLoader as I, CreateWorkflowSchema as It, PendingMessageScanner as J, WorkflowNotifyPayloadSchema as Jt, LRUCache as K, UpdateUserSchema as Kt, CircuitBreaker as L, IngestEventSchema as Lt, AppError as M, AddContactSchema as Mt, ValidationError as N, AddUserSchema as Nt, Redis as O, RecipientProfileSchema as Ot, generateId as P, BatchAddContactsSchema as Pt, metrics as Q, ENRICHED_STREAMS as Qt, BatchProcessor as R, InlineUserSchema as Rt, PreferenceRepository as S, NotificationDeliveredPayloadSchema as St, TemplateRepository as T, RenderedContentSchema as Tt, LUA_SCHEDULER_POLL as U, TemplateSchema as Ut, LUA_RENEW_LOCK as V, QuietHoursSchema as Vt, getPriorityBucket as W, TriggerWorkflowSchema as Wt, StreamProducer as X, buildStreamEvent as Xt, StreamConsumer as Y, WorkflowStepSchema as Yt, getMetricsRegistry as Z, CONSUMER_GROUPS as Zt, escapeHeader as _, readBaseConfig as _n, workflowWaiters as _t, SuspendExecutionError as a, StreamEventSchema as an, runMigrations as at, renderWithTemplate as b, NotificationSkippedPayloadSchema as bt, BaseWorker as c, EventMetadataSchema as cn, projectApiKeys as ct, buildUnsubscribeHeaders as d, NotificationStatusSchema as dn, suppressions as dt, OUTBOUND_STREAMS as en, createLogger as et, signUnsubscribeToken as f, AI_DEFAULTS as fn, userTopicPreferences as ft, TemplateCache as g, parseConfig as gn, workflowSteps as gt, templateRegistry as h, loadEnv as hn, workflowInstances as ht, workflowRegistry as i, StreamEventMetadataSchema as in, createDatabase as it, UserThrottle as j, NotificationTargetSchema as jt, RedisClient as k, NotificationCreatedPayloadSchema as kt, NonRetryableError as l, NotificationChannelSchema as ln, projects as lt, renderTemplate as m, getAiConfig as mn, workflowDefinitions as mt, NotifkitClient as n, STREAMS as nn, withRequestId as nt, buildStepNotifyPayload as o, EventRegistry as on, deliveryOutbox as ot, verifyUnsubscribeToken as p, baseConfigSchema as pn, users as pt, globalEmitter as q, UserContactInputSchema as qt, workflow as r, EventEnvelopeSchema as rn, IdempotencyGuard as rt, resolveStepTarget as s, registry as sn, messageLogs as st, NotifkitServer as t, PUBSUB_CHANNELS as tn, withContext as tt, startHealthReporter as u, NotificationPrioritySchema as un, scheduledPayloads as ut, escapeHtml as v, setAiConfig as vn, NotificationAiPendingPayloadSchema as vt, SegmentRepository as w, NotificationDispatchedPayloadSchema as wt, ContactRepository as x, NotificationFailedPayloadSchema as xt, interpolate as y, setGlobalConfig as yn, NotificationCanceledPayloadSchema as yt, AsyncSemaphore as z, NotifyRequestSchema as zt };
3572
+ export { metrics as $, ENRICHED_STREAMS as $t, RedisClient as A, NotificationCreatedPayloadSchema as At, AsyncSemaphore as B, NotifyRequestSchema as Bt, PreferenceRepository as C, NotificationDeliveredPayloadSchema as Ct, UserRepository as D, NotificationScheduledPayloadSchema as Dt, TemplateRepository as E, RenderedContentSchema as Et, generateId as F, BatchAddContactsSchema as Ft, getPriorityBucket as G, TriggerWorkflowSchema as Gt, LUA_RENEW_LOCK as H, QuietHoursSchema as Ht, sleep as I, ContactChannelSchema as It, globalEmitter as J, UserContactInputSchema as Jt, normaliseTarget as K, UpdateProjectSchema as Kt, DataLoader as L, CreateWorkflowSchema as Lt, UserThrottle as M, NotificationTargetSchema as Mt, AppError as N, AddContactSchema as Nt, WorkflowRepository as O, NotificationEnrichedPayloadSchema as Ot, ValidationError as P, AddUserSchema as Pt, getMetricsRegistry as Q, CONSUMER_GROUPS as Qt, CircuitBreaker as R, IngestEventSchema as Rt, ContactRepository as S, NotificationFailedPayloadSchema as St, SegmentRepository as T, NotificationDispatchedPayloadSchema as Tt, LUA_SCHEDULER_CLAIM as U, SyncTemplatesSchema as Ut, LUA_RELEASE_LOCK as V, PreferencesSchema as Vt, LUA_SCHEDULER_POLL as W, TemplateSchema as Wt, StreamConsumer as X, WorkflowStepSchema as Xt, PendingMessageScanner as Y, WorkflowNotifyPayloadSchema as Yt, StreamProducer as Z, buildStreamEvent as Zt, escapeHeader as _, parseConfig as _n, workflowSteps as _t, SuspendExecutionError as a, StreamEventMetadataSchema as an, createDatabase as at, renderWithTemplate as b, setGlobalConfig as bn, NotificationCanceledPayloadSchema as bt, BaseWorker as c, registry as cn, messageLogs as ct, buildUnsubscribeHeaders as d, NotificationPrioritySchema as dn, scheduledPayloads as dt, INBOUND_STREAMS as en, childLogger as et, signUnsubscribeToken as f, NotificationStatusSchema as fn, suppressions as ft, TemplateCache as g, loadEnv as gn, workflowInstances as gt, templateRegistry as h, getAiConfig as hn, workflowDefinitions as ht, workflowRegistry as i, EventEnvelopeSchema as in, IdempotencyGuard as it, ProjectSettingsCache as j, NotificationRequestedPayloadSchema as jt, Redis as k, RecipientProfileSchema as kt, NonRetryableError as l, EventMetadataSchema as ln, projectApiKeys as lt, renderTemplate as m, baseConfigSchema as mn, users as mt, NotifkitClient as n, PUBSUB_CHANNELS as nn, withContext as nt, buildStepNotifyPayload as o, StreamEventSchema as on, runMigrations as ot, verifyUnsubscribeToken as p, AI_DEFAULTS as pn, userTopicPreferences as pt, LRUCache as q, UpdateUserSchema as qt, workflow as r, STREAMS as rn, withRequestId as rt, resolveStepTarget as s, EventRegistry as sn, deliveryOutbox as st, NotifkitServer as t, OUTBOUND_STREAMS as tn, createLogger as tt, startHealthReporter as u, NotificationChannelSchema as un, projects as ut, escapeHtml as v, readBaseConfig as vn, workflowWaiters as vt, ProjectRepository as w, DeliveryOptionsSchema as wt, AdminUserRepository as x, NotificationSkippedPayloadSchema as xt, interpolate as y, setAiConfig as yn, NotificationAiPendingPayloadSchema as yt, BatchProcessor as z, InlineUserSchema as zt };
3516
3573
 
3517
- //# sourceMappingURL=src-CPMwsUCJ.mjs.map
3574
+ //# sourceMappingURL=src-DkvHYM3y.mjs.map