notifkit 0.1.7 → 0.1.9
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/dashboard/README.md +29 -0
- package/dashboard/dist/assets/index-7mvXb4bS.js +310 -0
- package/dashboard/dist/assets/index-o7L-f3-c.css +1 -0
- package/dashboard/dist/favicon.svg +4 -0
- package/dashboard/dist/index.html +14 -0
- package/dist/index.d.mts +447 -9
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{main-CRPxM-O3.mjs → main-4Wyge9ms.mjs} +2 -2
- package/dist/{main-CRPxM-O3.mjs.map → main-4Wyge9ms.mjs.map} +1 -1
- package/dist/{main-Bgi2wWck.mjs → main-AO0JaY5z.mjs} +2 -2
- package/dist/{main-Bgi2wWck.mjs.map → main-AO0JaY5z.mjs.map} +1 -1
- package/dist/{main-DFMHcN_d.mjs → main-BMYSYcv2.mjs} +2 -2
- package/dist/{main-DFMHcN_d.mjs.map → main-BMYSYcv2.mjs.map} +1 -1
- package/dist/{main-Yorxzw0Z.mjs → main-BPbPnBIG.mjs} +2 -2
- package/dist/{main-Yorxzw0Z.mjs.map → main-BPbPnBIG.mjs.map} +1 -1
- package/dist/{main-pFAfCkVX.mjs → main-CyeQ_yDt.mjs} +2 -2
- package/dist/{main-pFAfCkVX.mjs.map → main-CyeQ_yDt.mjs.map} +1 -1
- package/dist/{main-CjbVdUqa.mjs → main-D19Wxs0x.mjs} +2 -2
- package/dist/{main-CjbVdUqa.mjs.map → main-D19Wxs0x.mjs.map} +1 -1
- package/dist/{main-D6SG3Isk.mjs → main-DSmh1e-V.mjs} +2 -2
- package/dist/{main-D6SG3Isk.mjs.map → main-DSmh1e-V.mjs.map} +1 -1
- package/dist/{main-CFSukWm8.mjs → main-JdOvJ70b.mjs} +495 -41
- package/dist/main-JdOvJ70b.mjs.map +1 -0
- package/dist/{src-CPMwsUCJ.mjs → src-CGmXRfsM.mjs} +86 -20
- package/dist/src-CGmXRfsM.mjs.map +1 -0
- package/drizzle/0005_admin_users.sql +11 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +8 -3
- package/scripts/create-admin.mjs +67 -0
- package/src/config/index.ts +12 -0
- package/src/db/schema.ts +13 -0
- package/src/repositories/index.ts +82 -1
- package/src/services/api/admin-static.ts +225 -0
- package/src/services/api/handlers.ts +224 -33
- package/src/services/api/main.ts +183 -29
- package/src/services/api/router.ts +7 -1
- package/src/services/auth/index.ts +111 -0
- package/dist/main-CFSukWm8.mjs.map +0 -1
- 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),
|
|
@@ -87,7 +90,16 @@ const baseConfigSchema = z.object({
|
|
|
87
90
|
* permanent: a dead link means the recipient reaches for the spam button
|
|
88
91
|
* instead, which costs far more than the key ever protected.
|
|
89
92
|
*/
|
|
90
|
-
UNSUBSCRIBE_SECRET: z.string().min(16).optional()
|
|
93
|
+
UNSUBSCRIBE_SECRET: z.string().min(16).optional(),
|
|
94
|
+
/**
|
|
95
|
+
* When true, trusts X-Forwarded-For headers from reverse proxies for client IP resolution.
|
|
96
|
+
* Defaults to false to prevent client-spoofed headers from bypassing rate limits.
|
|
97
|
+
*/
|
|
98
|
+
TRUST_PROXY: z.coerce.boolean().default(false),
|
|
99
|
+
/**
|
|
100
|
+
* Comma-separated list of allowed origins for CORS on session-authenticated admin routes.
|
|
101
|
+
*/
|
|
102
|
+
CORS_ORIGIN: z.string().optional()
|
|
91
103
|
});
|
|
92
104
|
let globalConfig = null;
|
|
93
105
|
function setGlobalConfig(config) {
|
|
@@ -673,10 +685,12 @@ registry.define("notification.ai_pending", NotificationAiPendingPayloadSchema);
|
|
|
673
685
|
//#endregion
|
|
674
686
|
//#region src/db/schema.ts
|
|
675
687
|
var schema_exports = /* @__PURE__ */ __exportAll({
|
|
688
|
+
adminUsers: () => adminUsers,
|
|
676
689
|
apiKeyRoleEnum: () => apiKeyRoleEnum,
|
|
677
690
|
channelEnum: () => channelEnum,
|
|
678
691
|
contactTopicPreferences: () => contactTopicPreferences,
|
|
679
692
|
deliveryOutbox: () => deliveryOutbox,
|
|
693
|
+
insertAdminUserSchema: () => insertAdminUserSchema,
|
|
680
694
|
insertDeliveryOutboxSchema: () => insertDeliveryOutboxSchema,
|
|
681
695
|
insertMessageLogSchema: () => insertMessageLogSchema,
|
|
682
696
|
insertProjectApiKeySchema: () => insertProjectApiKeySchema,
|
|
@@ -696,6 +710,7 @@ var schema_exports = /* @__PURE__ */ __exportAll({
|
|
|
696
710
|
projects: () => projects,
|
|
697
711
|
quietHours: () => quietHours,
|
|
698
712
|
scheduledPayloads: () => scheduledPayloads,
|
|
713
|
+
selectAdminUserSchema: () => selectAdminUserSchema,
|
|
699
714
|
selectDeliveryOutboxSchema: () => selectDeliveryOutboxSchema,
|
|
700
715
|
selectMessageLogSchema: () => selectMessageLogSchema,
|
|
701
716
|
selectProjectApiKeySchema: () => selectProjectApiKeySchema,
|
|
@@ -941,6 +956,17 @@ const scheduledPayloads = pgTable("scheduled_payloads", {
|
|
|
941
956
|
payload: jsonb("payload").notNull(),
|
|
942
957
|
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull()
|
|
943
958
|
});
|
|
959
|
+
const adminUsers = pgTable("admin_users", {
|
|
960
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
961
|
+
email: varchar("email").notNull().unique(),
|
|
962
|
+
username: varchar("username").unique(),
|
|
963
|
+
passwordHash: varchar("password_hash").notNull(),
|
|
964
|
+
role: varchar("role").notNull().default("admin"),
|
|
965
|
+
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
|
|
966
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull()
|
|
967
|
+
});
|
|
968
|
+
const insertAdminUserSchema = createInsertSchema(adminUsers);
|
|
969
|
+
const selectAdminUserSchema = createSelectSchema(adminUsers);
|
|
944
970
|
const insertProjectSchema = createInsertSchema(projects);
|
|
945
971
|
const selectProjectSchema = createSelectSchema(projects);
|
|
946
972
|
const insertProjectApiKeySchema = createInsertSchema(projectApiKeys);
|
|
@@ -2567,6 +2593,46 @@ var SegmentRepository = class {
|
|
|
2567
2593
|
`)).map((r) => r.segment);
|
|
2568
2594
|
}
|
|
2569
2595
|
};
|
|
2596
|
+
var AdminUserRepository = class {
|
|
2597
|
+
db;
|
|
2598
|
+
constructor(db) {
|
|
2599
|
+
this.db = db;
|
|
2600
|
+
}
|
|
2601
|
+
async findByEmailOrUsername(identifier) {
|
|
2602
|
+
const normalized = identifier.trim().toLowerCase();
|
|
2603
|
+
return (await this.db.select().from(adminUsers).where(or(eq(adminUsers.email, normalized), eq(adminUsers.username, identifier.trim()))).limit(1))[0] ?? null;
|
|
2604
|
+
}
|
|
2605
|
+
async findById(id) {
|
|
2606
|
+
return (await this.db.select().from(adminUsers).where(eq(adminUsers.id, id)).limit(1))[0] ?? null;
|
|
2607
|
+
}
|
|
2608
|
+
async create(data) {
|
|
2609
|
+
return (await this.db.insert(adminUsers).values({
|
|
2610
|
+
email: data.email.trim().toLowerCase(),
|
|
2611
|
+
username: data.username ? data.username.trim() : null,
|
|
2612
|
+
passwordHash: data.passwordHash,
|
|
2613
|
+
role: data.role || "admin"
|
|
2614
|
+
}).returning())[0];
|
|
2615
|
+
}
|
|
2616
|
+
async updatePassword(id, passwordHash) {
|
|
2617
|
+
return (await this.db.update(adminUsers).set({
|
|
2618
|
+
passwordHash,
|
|
2619
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
2620
|
+
}).where(eq(adminUsers.id, id)).returning()).length > 0;
|
|
2621
|
+
}
|
|
2622
|
+
async list() {
|
|
2623
|
+
return await this.db.select({
|
|
2624
|
+
id: adminUsers.id,
|
|
2625
|
+
email: adminUsers.email,
|
|
2626
|
+
username: adminUsers.username,
|
|
2627
|
+
role: adminUsers.role,
|
|
2628
|
+
createdAt: adminUsers.createdAt,
|
|
2629
|
+
updatedAt: adminUsers.updatedAt
|
|
2630
|
+
}).from(adminUsers).orderBy(adminUsers.createdAt);
|
|
2631
|
+
}
|
|
2632
|
+
async count() {
|
|
2633
|
+
return (await this.db.select({ count: sql`count(*)::int` }).from(adminUsers))[0]?.count ?? 0;
|
|
2634
|
+
}
|
|
2635
|
+
};
|
|
2570
2636
|
//#endregion
|
|
2571
2637
|
//#region src/templates/render.ts
|
|
2572
2638
|
function escapeHtml(unsafe) {
|
|
@@ -3402,35 +3468,35 @@ var NotifkitServer = class extends EventEmitter {
|
|
|
3402
3468
|
}
|
|
3403
3469
|
const startupPromises = [];
|
|
3404
3470
|
if (services.includes("api")) {
|
|
3405
|
-
const { startApiServer } = await import("./main-
|
|
3471
|
+
const { startApiServer } = await import("./main-JdOvJ70b.mjs");
|
|
3406
3472
|
startupPromises.push(startApiServer());
|
|
3407
3473
|
}
|
|
3408
3474
|
if (services.includes("delivery")) {
|
|
3409
|
-
const { startDeliveryWorker } = await import("./main-
|
|
3475
|
+
const { startDeliveryWorker } = await import("./main-CyeQ_yDt.mjs");
|
|
3410
3476
|
startupPromises.push(startDeliveryWorker());
|
|
3411
3477
|
}
|
|
3412
3478
|
if (services.includes("engine")) {
|
|
3413
|
-
const { startEngineWorker } = await import("./main-
|
|
3479
|
+
const { startEngineWorker } = await import("./main-BPbPnBIG.mjs");
|
|
3414
3480
|
startupPromises.push(startEngineWorker());
|
|
3415
3481
|
}
|
|
3416
3482
|
if (services.includes("enricher")) {
|
|
3417
|
-
const { startEnricherWorker } = await import("./main-
|
|
3483
|
+
const { startEnricherWorker } = await import("./main-AO0JaY5z.mjs");
|
|
3418
3484
|
startupPromises.push(startEnricherWorker());
|
|
3419
3485
|
}
|
|
3420
3486
|
if (services.includes("scheduler")) {
|
|
3421
|
-
const { startSchedulerWorker } = await import("./main-
|
|
3487
|
+
const { startSchedulerWorker } = await import("./main-BMYSYcv2.mjs");
|
|
3422
3488
|
startupPromises.push(startSchedulerWorker());
|
|
3423
3489
|
}
|
|
3424
3490
|
if (services.includes("ai")) {
|
|
3425
|
-
const { startAiWorker } = await import("./main-
|
|
3491
|
+
const { startAiWorker } = await import("./main-DSmh1e-V.mjs");
|
|
3426
3492
|
startupPromises.push(startAiWorker());
|
|
3427
3493
|
}
|
|
3428
3494
|
if (services.includes("workflow")) {
|
|
3429
|
-
const { startWorkflowWorker } = await import("./main-
|
|
3495
|
+
const { startWorkflowWorker } = await import("./main-D19Wxs0x.mjs");
|
|
3430
3496
|
startupPromises.push(startWorkflowWorker());
|
|
3431
3497
|
}
|
|
3432
3498
|
if (services.includes("events")) {
|
|
3433
|
-
const { startEventWorker } = await import("./main-
|
|
3499
|
+
const { startEventWorker } = await import("./main-4Wyge9ms.mjs");
|
|
3434
3500
|
startupPromises.push(startEventWorker());
|
|
3435
3501
|
}
|
|
3436
3502
|
const handleSignal = async (signal) => {
|
|
@@ -3470,35 +3536,35 @@ var NotifkitServer = class extends EventEmitter {
|
|
|
3470
3536
|
"events"
|
|
3471
3537
|
] : this.options.services;
|
|
3472
3538
|
if (services.includes("api")) {
|
|
3473
|
-
const { stopApiServer } = await import("./main-
|
|
3539
|
+
const { stopApiServer } = await import("./main-JdOvJ70b.mjs");
|
|
3474
3540
|
await stopApiServer();
|
|
3475
3541
|
}
|
|
3476
3542
|
if (services.includes("delivery")) {
|
|
3477
|
-
const { stopDeliveryWorker } = await import("./main-
|
|
3543
|
+
const { stopDeliveryWorker } = await import("./main-CyeQ_yDt.mjs");
|
|
3478
3544
|
await stopDeliveryWorker();
|
|
3479
3545
|
}
|
|
3480
3546
|
if (services.includes("engine")) {
|
|
3481
|
-
const { stopEngineWorker } = await import("./main-
|
|
3547
|
+
const { stopEngineWorker } = await import("./main-BPbPnBIG.mjs");
|
|
3482
3548
|
await stopEngineWorker();
|
|
3483
3549
|
}
|
|
3484
3550
|
if (services.includes("enricher")) {
|
|
3485
|
-
const { stopEnricherWorker } = await import("./main-
|
|
3551
|
+
const { stopEnricherWorker } = await import("./main-AO0JaY5z.mjs");
|
|
3486
3552
|
await stopEnricherWorker();
|
|
3487
3553
|
}
|
|
3488
3554
|
if (services.includes("scheduler")) {
|
|
3489
|
-
const { stopSchedulerWorker } = await import("./main-
|
|
3555
|
+
const { stopSchedulerWorker } = await import("./main-BMYSYcv2.mjs");
|
|
3490
3556
|
await stopSchedulerWorker();
|
|
3491
3557
|
}
|
|
3492
3558
|
if (services.includes("ai")) {
|
|
3493
|
-
const { stopAiWorker } = await import("./main-
|
|
3559
|
+
const { stopAiWorker } = await import("./main-DSmh1e-V.mjs");
|
|
3494
3560
|
await stopAiWorker();
|
|
3495
3561
|
}
|
|
3496
3562
|
if (services.includes("workflow")) {
|
|
3497
|
-
const { stopWorkflowWorker } = await import("./main-
|
|
3563
|
+
const { stopWorkflowWorker } = await import("./main-D19Wxs0x.mjs");
|
|
3498
3564
|
await stopWorkflowWorker();
|
|
3499
3565
|
}
|
|
3500
3566
|
if (services.includes("events")) {
|
|
3501
|
-
const { stopEventWorker } = await import("./main-
|
|
3567
|
+
const { stopEventWorker } = await import("./main-4Wyge9ms.mjs");
|
|
3502
3568
|
await stopEventWorker();
|
|
3503
3569
|
}
|
|
3504
3570
|
if (this.pgContainer) {
|
|
@@ -3512,6 +3578,6 @@ var NotifkitServer = class extends EventEmitter {
|
|
|
3512
3578
|
}
|
|
3513
3579
|
};
|
|
3514
3580
|
//#endregion
|
|
3515
|
-
export {
|
|
3581
|
+
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
3582
|
|
|
3517
|
-
//# sourceMappingURL=src-
|
|
3583
|
+
//# sourceMappingURL=src-CGmXRfsM.mjs.map
|