expxagents 0.11.2 → 0.12.0
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/dashboard/assets/{BufferResource-CR4DczHL.js → BufferResource-BcVsF5HP.js} +1 -1
- package/dist/dashboard/assets/{CanvasRenderer-DdWLm2t4.js → CanvasRenderer-kA1Maw0x.js} +1 -1
- package/dist/dashboard/assets/{JarvisView-yQv964kf.js → JarvisView-DBrCWArD.js} +1 -1
- package/dist/dashboard/assets/{RenderTargetSystem-DdTH8Un8.js → RenderTargetSystem-Bp9B4iP8.js} +1 -1
- package/dist/dashboard/assets/{WebGLRenderer-C6BYo_WV.js → WebGLRenderer-CNJyeb_W.js} +1 -1
- package/dist/dashboard/assets/{WebGPURenderer-C1UxCrJq.js → WebGPURenderer-DCbozzdc.js} +1 -1
- package/dist/dashboard/assets/{browserAll-BC0ycs7y.js → browserAll-Bu4cXbCn.js} +1 -1
- package/dist/dashboard/assets/index-zfHiMrG2.js +344 -0
- package/dist/dashboard/assets/{webworkerAll-D7SccyuO.js → webworkerAll-BFb9bpT-.js} +1 -1
- package/dist/dashboard/index.html +1 -1
- package/dist/data/opensquad.db +0 -0
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +30 -0
- package/dist/server/app.js.map +1 -1
- package/dist/server/config.d.ts +6 -0
- package/dist/server/config.d.ts.map +1 -1
- package/dist/server/config.js +14 -1
- package/dist/server/config.js.map +1 -1
- package/dist/server/db/__tests__/email-schema.test.d.ts +2 -0
- package/dist/server/db/__tests__/email-schema.test.d.ts.map +1 -0
- package/dist/server/db/__tests__/email-schema.test.js +53 -0
- package/dist/server/db/__tests__/email-schema.test.js.map +1 -0
- package/dist/server/db/schema.d.ts +1 -1
- package/dist/server/db/schema.d.ts.map +1 -1
- package/dist/server/db/schema.js +70 -0
- package/dist/server/db/schema.js.map +1 -1
- package/dist/server/email/__tests__/campaign-routes.test.d.ts +2 -0
- package/dist/server/email/__tests__/campaign-routes.test.d.ts.map +1 -0
- package/dist/server/email/__tests__/campaign-routes.test.js +216 -0
- package/dist/server/email/__tests__/campaign-routes.test.js.map +1 -0
- package/dist/server/email/__tests__/campaign-service.test.d.ts +2 -0
- package/dist/server/email/__tests__/campaign-service.test.d.ts.map +1 -0
- package/dist/server/email/__tests__/campaign-service.test.js +79 -0
- package/dist/server/email/__tests__/campaign-service.test.js.map +1 -0
- package/dist/server/email/__tests__/email-queue-worker.test.d.ts +2 -0
- package/dist/server/email/__tests__/email-queue-worker.test.d.ts.map +1 -0
- package/dist/server/email/__tests__/email-queue-worker.test.js +93 -0
- package/dist/server/email/__tests__/email-queue-worker.test.js.map +1 -0
- package/dist/server/email/__tests__/email-utils.test.d.ts +2 -0
- package/dist/server/email/__tests__/email-utils.test.d.ts.map +1 -0
- package/dist/server/email/__tests__/email-utils.test.js +36 -0
- package/dist/server/email/__tests__/email-utils.test.js.map +1 -0
- package/dist/server/email/__tests__/lead-routes.test.d.ts +2 -0
- package/dist/server/email/__tests__/lead-routes.test.d.ts.map +1 -0
- package/dist/server/email/__tests__/lead-routes.test.js +180 -0
- package/dist/server/email/__tests__/lead-routes.test.js.map +1 -0
- package/dist/server/email/__tests__/lead-service.test.d.ts +2 -0
- package/dist/server/email/__tests__/lead-service.test.d.ts.map +1 -0
- package/dist/server/email/__tests__/lead-service.test.js +113 -0
- package/dist/server/email/__tests__/lead-service.test.js.map +1 -0
- package/dist/server/email/__tests__/ses-client.test.d.ts +2 -0
- package/dist/server/email/__tests__/ses-client.test.d.ts.map +1 -0
- package/dist/server/email/__tests__/ses-client.test.js +48 -0
- package/dist/server/email/__tests__/ses-client.test.js.map +1 -0
- package/dist/server/email/__tests__/sns-webhook.test.d.ts +2 -0
- package/dist/server/email/__tests__/sns-webhook.test.d.ts.map +1 -0
- package/dist/server/email/__tests__/sns-webhook.test.js +40 -0
- package/dist/server/email/__tests__/sns-webhook.test.js.map +1 -0
- package/dist/server/email/campaign-routes.d.ts +8 -0
- package/dist/server/email/campaign-routes.d.ts.map +1 -0
- package/dist/server/email/campaign-routes.js +65 -0
- package/dist/server/email/campaign-routes.js.map +1 -0
- package/dist/server/email/campaign-service.d.ts +55 -0
- package/dist/server/email/campaign-service.d.ts.map +1 -0
- package/dist/server/email/campaign-service.js +89 -0
- package/dist/server/email/campaign-service.js.map +1 -0
- package/dist/server/email/email-queue-worker.d.ts +27 -0
- package/dist/server/email/email-queue-worker.d.ts.map +1 -0
- package/dist/server/email/email-queue-worker.js +119 -0
- package/dist/server/email/email-queue-worker.js.map +1 -0
- package/dist/server/email/email-utils.d.ts +5 -0
- package/dist/server/email/email-utils.d.ts.map +1 -0
- package/dist/server/email/email-utils.js +24 -0
- package/dist/server/email/email-utils.js.map +1 -0
- package/dist/server/email/lead-routes.d.ts +8 -0
- package/dist/server/email/lead-routes.d.ts.map +1 -0
- package/dist/server/email/lead-routes.js +56 -0
- package/dist/server/email/lead-routes.js.map +1 -0
- package/dist/server/email/lead-service.d.ts +66 -0
- package/dist/server/email/lead-service.d.ts.map +1 -0
- package/dist/server/email/lead-service.js +138 -0
- package/dist/server/email/lead-service.js.map +1 -0
- package/dist/server/email/ses-client.d.ts +27 -0
- package/dist/server/email/ses-client.d.ts.map +1 -0
- package/dist/server/email/ses-client.js +44 -0
- package/dist/server/email/ses-client.js.map +1 -0
- package/dist/server/email/sns-webhook.d.ts +10 -0
- package/dist/server/email/sns-webhook.d.ts.map +1 -0
- package/dist/server/email/sns-webhook.js +73 -0
- package/dist/server/email/sns-webhook.js.map +1 -0
- package/package.json +6 -2
- package/dist/dashboard/assets/index-3Noclaww.js +0 -344
- package/dist/data/opensquad.db-shm +0 -0
- package/dist/data/opensquad.db-wal +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a0 as G,a2 as I,a3 as B,k as _,M as k,V as O,L as A,a8 as m,T as v,ar as C,R as E,w as z,a7 as U,t as w}from"./index-
|
|
1
|
+
import{a0 as G,a2 as I,a3 as B,k as _,M as k,V as O,L as A,a8 as m,T as v,ar as C,R as E,w as z,a7 as U,t as w}from"./index-zfHiMrG2.js";var M=`in vec2 aPosition;
|
|
2
2
|
out vec2 vTextureCoord;
|
|
3
3
|
|
|
4
4
|
uniform vec4 uInputSize;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>ExpxAgents — Mission Control</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-zfHiMrG2.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-B-8_BLE5.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
package/dist/data/opensquad.db
CHANGED
|
Binary file
|
package/dist/server/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAQ/C,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAQ/C,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAyBtD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1B;AAED,wBAAsB,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAwJ/E"}
|
package/dist/server/app.js
CHANGED
|
@@ -22,6 +22,11 @@ import { ChatHandler } from './bridge/chat-handler.js';
|
|
|
22
22
|
import { JobRunner } from './scheduler/job-runner.js';
|
|
23
23
|
import { SchedulerService } from './scheduler/scheduler-service.js';
|
|
24
24
|
import { schedulerRoutes } from './scheduler/scheduler-routes.js';
|
|
25
|
+
import { leadRoutes } from './email/lead-routes.js';
|
|
26
|
+
import { campaignRoutes } from './email/campaign-routes.js';
|
|
27
|
+
import { snsWebhookRoutes } from './email/sns-webhook.js';
|
|
28
|
+
import { createSesClient } from './email/ses-client.js';
|
|
29
|
+
import { EmailQueueWorker } from './email/email-queue-worker.js';
|
|
25
30
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
26
31
|
export async function buildApp(opts) {
|
|
27
32
|
const config = { ...loadConfig(), ...opts?.config };
|
|
@@ -87,6 +92,29 @@ export async function buildApp(opts) {
|
|
|
87
92
|
});
|
|
88
93
|
schedulerService.start();
|
|
89
94
|
await app.register(schedulerRoutes, { db, schedulerService });
|
|
95
|
+
// Email Engine
|
|
96
|
+
const sesClient = createSesClient({
|
|
97
|
+
region: config.awsRegion,
|
|
98
|
+
accessKeyId: config.awsAccessKeyId,
|
|
99
|
+
secretAccessKey: config.awsSecretAccessKey,
|
|
100
|
+
});
|
|
101
|
+
let emailWorker = null;
|
|
102
|
+
if (sesClient.isConfigured()) {
|
|
103
|
+
emailWorker = new EmailQueueWorker({
|
|
104
|
+
db,
|
|
105
|
+
ses: sesClient,
|
|
106
|
+
rateLimit: config.sesRateLimit,
|
|
107
|
+
jwtSecret: config.jwtSecret,
|
|
108
|
+
serverUrl: config.serverUrl,
|
|
109
|
+
broadcast: (message) => {
|
|
110
|
+
wsContext.broadcastToAll(message);
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
emailWorker.start();
|
|
114
|
+
}
|
|
115
|
+
await app.register(leadRoutes, { db });
|
|
116
|
+
await app.register(campaignRoutes, { db });
|
|
117
|
+
await app.register(snsWebhookRoutes, { db, jwtSecret: config.jwtSecret });
|
|
90
118
|
// File Watcher
|
|
91
119
|
const watcher = createFileWatcher(config.squadsDir, (event) => {
|
|
92
120
|
if (event.type === 'squad:state') {
|
|
@@ -117,6 +145,8 @@ export async function buildApp(opts) {
|
|
|
117
145
|
await watcher.ready;
|
|
118
146
|
// Cleanup on close
|
|
119
147
|
app.addHook('onClose', async () => {
|
|
148
|
+
if (emailWorker)
|
|
149
|
+
emailWorker.stop();
|
|
120
150
|
schedulerService.stop();
|
|
121
151
|
watcher.stop();
|
|
122
152
|
});
|
package/dist/server/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,IAAI,MAAM,eAAe,CAAC;AACjC,OAAO,MAAM,MAAM,iBAAiB,CAAC;AACrC,OAAO,SAAS,MAAM,qBAAqB,CAAC;AAC5C,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAe,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
package/dist/server/config.d.ts
CHANGED
|
@@ -5,6 +5,12 @@ export interface Config {
|
|
|
5
5
|
jwtSecret: string;
|
|
6
6
|
dataDir: string;
|
|
7
7
|
squadsDir: string;
|
|
8
|
+
awsAccessKeyId?: string;
|
|
9
|
+
awsSecretAccessKey?: string;
|
|
10
|
+
awsRegion: string;
|
|
11
|
+
sesFromEmail: string;
|
|
12
|
+
sesRateLimit: number;
|
|
13
|
+
serverUrl: string;
|
|
8
14
|
}
|
|
9
15
|
export declare function loadConfig(): Config;
|
|
10
16
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,UAAU,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,UAAU,IAAI,MAAM,CAkCnC"}
|
package/dist/server/config.js
CHANGED
|
@@ -17,6 +17,19 @@ export function loadConfig() {
|
|
|
17
17
|
const nodeEnv = process.env.NODE_ENV || 'development';
|
|
18
18
|
const dataDir = process.env.DATA_DIR ?? path.join(__dirname, '..', 'data');
|
|
19
19
|
const squadsDir = process.env.SQUADS_DIR ?? path.resolve(projectRoot, 'squads');
|
|
20
|
-
return {
|
|
20
|
+
return {
|
|
21
|
+
port,
|
|
22
|
+
corsOrigin,
|
|
23
|
+
nodeEnv,
|
|
24
|
+
jwtSecret,
|
|
25
|
+
dataDir,
|
|
26
|
+
squadsDir,
|
|
27
|
+
awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID || undefined,
|
|
28
|
+
awsSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || undefined,
|
|
29
|
+
awsRegion: process.env.AWS_REGION || 'us-east-1',
|
|
30
|
+
sesFromEmail: process.env.SES_FROM_EMAIL || '',
|
|
31
|
+
sesRateLimit: parseInt(process.env.SES_RATE_LIMIT || '14', 10),
|
|
32
|
+
serverUrl: process.env.SERVER_URL || `http://localhost:${port}`,
|
|
33
|
+
};
|
|
21
34
|
}
|
|
22
35
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAiB/D,MAAM,UAAU,UAAU;IACxB,wEAAwE;IACxE,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC7E,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAEpC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;IACzC,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CACb,kFAAkF;YAClF,4CAA4C,CAC7C,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,oBAAoB,IAAI,EAAE,CAAC;IACzE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC;IACtD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3E,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAEhF,OAAO;QACL,IAAI;QACJ,UAAU;QACV,OAAO;QACP,SAAS;QACT,OAAO;QACP,SAAS;QACT,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,SAAS;QAC1D,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,SAAS;QAClE,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,WAAW;QAChD,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE;QAC9C,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,EAAE,EAAE,CAAC;QAC9D,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,oBAAoB,IAAI,EAAE;KAChE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-schema.test.d.ts","sourceRoot":"","sources":["../../../src/db/__tests__/email-schema.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import Database from 'better-sqlite3';
|
|
3
|
+
import { runMigrations } from '../migrations.js';
|
|
4
|
+
describe('email schema', () => {
|
|
5
|
+
let db;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
db = new Database(':memory:');
|
|
8
|
+
runMigrations(db);
|
|
9
|
+
});
|
|
10
|
+
afterEach(() => { db.close(); });
|
|
11
|
+
it('should create leads table', () => {
|
|
12
|
+
const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='leads'").get();
|
|
13
|
+
expect(row).toBeTruthy();
|
|
14
|
+
});
|
|
15
|
+
it('should create lead_tags table', () => {
|
|
16
|
+
const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='lead_tags'").get();
|
|
17
|
+
expect(row).toBeTruthy();
|
|
18
|
+
});
|
|
19
|
+
it('should create lead_lists table', () => {
|
|
20
|
+
const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='lead_lists'").get();
|
|
21
|
+
expect(row).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
it('should create email_campaigns table', () => {
|
|
24
|
+
const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='email_campaigns'").get();
|
|
25
|
+
expect(row).toBeTruthy();
|
|
26
|
+
});
|
|
27
|
+
it('should create email_queue table', () => {
|
|
28
|
+
const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='email_queue'").get();
|
|
29
|
+
expect(row).toBeTruthy();
|
|
30
|
+
});
|
|
31
|
+
it('should enforce unique email on leads', () => {
|
|
32
|
+
db.prepare("INSERT INTO leads (id, email) VALUES ('a', 'test@example.com')").run();
|
|
33
|
+
expect(() => {
|
|
34
|
+
db.prepare("INSERT INTO leads (id, email) VALUES ('b', 'test@example.com')").run();
|
|
35
|
+
}).toThrow();
|
|
36
|
+
});
|
|
37
|
+
it('should cascade delete lead_tags when lead is deleted', () => {
|
|
38
|
+
db.prepare("INSERT INTO leads (id, email) VALUES ('a', 'test@example.com')").run();
|
|
39
|
+
db.prepare("INSERT INTO lead_tags (lead_id, tag) VALUES ('a', 'saas')").run();
|
|
40
|
+
db.prepare("DELETE FROM leads WHERE id = 'a'").run();
|
|
41
|
+
const tags = db.prepare("SELECT * FROM lead_tags WHERE lead_id = 'a'").all();
|
|
42
|
+
expect(tags).toHaveLength(0);
|
|
43
|
+
});
|
|
44
|
+
it('should set null on email_queue.lead_id when lead is deleted', () => {
|
|
45
|
+
db.prepare("INSERT INTO leads (id, email) VALUES ('a', 'test@example.com')").run();
|
|
46
|
+
db.prepare("INSERT INTO email_campaigns (id, name, subject, body_html, from_email) VALUES ('c1', 'Test', 'Hi', '<p>Hi</p>', 'a@b.com')").run();
|
|
47
|
+
db.prepare("INSERT INTO email_queue (id, campaign_id, lead_id, to_email) VALUES ('q1', 'c1', 'a', 'test@example.com')").run();
|
|
48
|
+
db.prepare("DELETE FROM leads WHERE id = 'a'").run();
|
|
49
|
+
const row = db.prepare("SELECT lead_id FROM email_queue WHERE id = 'q1'").get();
|
|
50
|
+
expect(row.lead_id).toBeNull();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=email-schema.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-schema.test.js","sourceRoot":"","sources":["../../../src/db/__tests__/email-schema.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const SCHEMA_SQL = "\nCREATE TABLE IF NOT EXISTS users (\n id TEXT PRIMARY KEY,\n username TEXT UNIQUE NOT NULL,\n email TEXT,\n password_hash TEXT NOT NULL,\n role TEXT NOT NULL DEFAULT 'operator',\n created_at TEXT NOT NULL,\n last_login TEXT\n);\n\nCREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,\n token_hash TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS audit_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n user_id TEXT NOT NULL REFERENCES users(id),\n action TEXT NOT NULL,\n details TEXT,\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS conversations (\n id TEXT PRIMARY KEY,\n squad_name TEXT NOT NULL,\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS chat_messages (\n id TEXT PRIMARY KEY,\n conversation_id TEXT NOT NULL REFERENCES conversations(id),\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n agent_id TEXT,\n agent_name TEXT,\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS squad_activities (\n id TEXT PRIMARY KEY,\n squad_code TEXT NOT NULL,\n conversation_id TEXT,\n started_at TEXT NOT NULL,\n finished_at TEXT,\n duration_ms INTEGER,\n status TEXT NOT NULL DEFAULT 'running',\n user_message TEXT,\n result_summary TEXT,\n triggered_by TEXT DEFAULT 'dashboard',\n created_at TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS idx_squad_activities_squad_date\n ON squad_activities(squad_code, started_at);\n\nCREATE INDEX IF NOT EXISTS idx_squad_activities_date\n ON squad_activities(started_at);\n\nCREATE TABLE IF NOT EXISTS scheduled_jobs (\n squad_name TEXT PRIMARY KEY,\n cron_expression TEXT NOT NULL,\n prompt TEXT NOT NULL,\n mode TEXT DEFAULT 'autonomous',\n timeout_minutes INTEGER DEFAULT 30,\n retry_on_failure INTEGER DEFAULT 0,\n timezone TEXT,\n status TEXT DEFAULT 'active',\n last_run_at TEXT,\n last_result TEXT,\n next_run_at TEXT,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_squad_activities_triggered_by\n ON squad_activities(triggered_by, squad_code);\n";
|
|
1
|
+
export declare const SCHEMA_SQL = "\nCREATE TABLE IF NOT EXISTS users (\n id TEXT PRIMARY KEY,\n username TEXT UNIQUE NOT NULL,\n email TEXT,\n password_hash TEXT NOT NULL,\n role TEXT NOT NULL DEFAULT 'operator',\n created_at TEXT NOT NULL,\n last_login TEXT\n);\n\nCREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,\n token_hash TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS audit_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n user_id TEXT NOT NULL REFERENCES users(id),\n action TEXT NOT NULL,\n details TEXT,\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS conversations (\n id TEXT PRIMARY KEY,\n squad_name TEXT NOT NULL,\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS chat_messages (\n id TEXT PRIMARY KEY,\n conversation_id TEXT NOT NULL REFERENCES conversations(id),\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n agent_id TEXT,\n agent_name TEXT,\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS squad_activities (\n id TEXT PRIMARY KEY,\n squad_code TEXT NOT NULL,\n conversation_id TEXT,\n started_at TEXT NOT NULL,\n finished_at TEXT,\n duration_ms INTEGER,\n status TEXT NOT NULL DEFAULT 'running',\n user_message TEXT,\n result_summary TEXT,\n triggered_by TEXT DEFAULT 'dashboard',\n created_at TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS idx_squad_activities_squad_date\n ON squad_activities(squad_code, started_at);\n\nCREATE INDEX IF NOT EXISTS idx_squad_activities_date\n ON squad_activities(started_at);\n\nCREATE TABLE IF NOT EXISTS scheduled_jobs (\n squad_name TEXT PRIMARY KEY,\n cron_expression TEXT NOT NULL,\n prompt TEXT NOT NULL,\n mode TEXT DEFAULT 'autonomous',\n timeout_minutes INTEGER DEFAULT 30,\n retry_on_failure INTEGER DEFAULT 0,\n timezone TEXT,\n status TEXT DEFAULT 'active',\n last_run_at TEXT,\n last_result TEXT,\n next_run_at TEXT,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_squad_activities_triggered_by\n ON squad_activities(triggered_by, squad_code);\n\nCREATE TABLE IF NOT EXISTS leads (\n id TEXT PRIMARY KEY,\n email TEXT UNIQUE NOT NULL,\n name TEXT,\n company TEXT,\n metadata TEXT,\n status TEXT DEFAULT 'active',\n source TEXT,\n source_detail TEXT,\n created_at TEXT DEFAULT (datetime('now')),\n updated_at TEXT DEFAULT (datetime('now'))\n);\n\nCREATE TABLE IF NOT EXISTS lead_tags (\n lead_id TEXT NOT NULL REFERENCES leads(id) ON DELETE CASCADE,\n tag TEXT NOT NULL,\n PRIMARY KEY (lead_id, tag)\n);\n\nCREATE TABLE IF NOT EXISTS lead_lists (\n lead_id TEXT NOT NULL REFERENCES leads(id) ON DELETE CASCADE,\n list_name TEXT NOT NULL,\n PRIMARY KEY (lead_id, list_name)\n);\n\nCREATE TABLE IF NOT EXISTS email_campaigns (\n id TEXT PRIMARY KEY,\n name TEXT,\n squad_name TEXT,\n subject TEXT,\n body_html TEXT,\n body_text TEXT,\n from_email TEXT,\n from_name TEXT,\n status TEXT DEFAULT 'draft',\n total_recipients INTEGER DEFAULT 0,\n sent_count INTEGER DEFAULT 0,\n failed_count INTEGER DEFAULT 0,\n bounce_count INTEGER DEFAULT 0,\n complaint_count INTEGER DEFAULT 0,\n created_at TEXT DEFAULT (datetime('now')),\n started_at TEXT,\n completed_at TEXT\n);\n\nCREATE TABLE IF NOT EXISTS email_queue (\n id TEXT PRIMARY KEY,\n campaign_id TEXT REFERENCES email_campaigns(id) ON DELETE CASCADE,\n lead_id TEXT REFERENCES leads(id) ON DELETE SET NULL,\n to_email TEXT NOT NULL,\n status TEXT DEFAULT 'pending',\n ses_message_id TEXT,\n error TEXT,\n attempts INTEGER DEFAULT 0,\n scheduled_at TEXT,\n sent_at TEXT,\n created_at TEXT DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_email_queue_status_scheduled\n ON email_queue(status, scheduled_at);\nCREATE INDEX IF NOT EXISTS idx_email_queue_ses_message_id\n ON email_queue(ses_message_id);\nCREATE INDEX IF NOT EXISTS idx_email_queue_campaign_status\n ON email_queue(campaign_id, status);\nCREATE INDEX IF NOT EXISTS idx_lead_tags_tag\n ON lead_tags(tag);\nCREATE INDEX IF NOT EXISTS idx_lead_lists_list_name\n ON lead_lists(list_name);\n";
|
|
2
2
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,0mIAuJtB,CAAC"}
|
package/dist/server/db/schema.js
CHANGED
|
@@ -79,5 +79,75 @@ CREATE TABLE IF NOT EXISTS scheduled_jobs (
|
|
|
79
79
|
|
|
80
80
|
CREATE INDEX IF NOT EXISTS idx_squad_activities_triggered_by
|
|
81
81
|
ON squad_activities(triggered_by, squad_code);
|
|
82
|
+
|
|
83
|
+
CREATE TABLE IF NOT EXISTS leads (
|
|
84
|
+
id TEXT PRIMARY KEY,
|
|
85
|
+
email TEXT UNIQUE NOT NULL,
|
|
86
|
+
name TEXT,
|
|
87
|
+
company TEXT,
|
|
88
|
+
metadata TEXT,
|
|
89
|
+
status TEXT DEFAULT 'active',
|
|
90
|
+
source TEXT,
|
|
91
|
+
source_detail TEXT,
|
|
92
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
93
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
CREATE TABLE IF NOT EXISTS lead_tags (
|
|
97
|
+
lead_id TEXT NOT NULL REFERENCES leads(id) ON DELETE CASCADE,
|
|
98
|
+
tag TEXT NOT NULL,
|
|
99
|
+
PRIMARY KEY (lead_id, tag)
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
CREATE TABLE IF NOT EXISTS lead_lists (
|
|
103
|
+
lead_id TEXT NOT NULL REFERENCES leads(id) ON DELETE CASCADE,
|
|
104
|
+
list_name TEXT NOT NULL,
|
|
105
|
+
PRIMARY KEY (lead_id, list_name)
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
CREATE TABLE IF NOT EXISTS email_campaigns (
|
|
109
|
+
id TEXT PRIMARY KEY,
|
|
110
|
+
name TEXT,
|
|
111
|
+
squad_name TEXT,
|
|
112
|
+
subject TEXT,
|
|
113
|
+
body_html TEXT,
|
|
114
|
+
body_text TEXT,
|
|
115
|
+
from_email TEXT,
|
|
116
|
+
from_name TEXT,
|
|
117
|
+
status TEXT DEFAULT 'draft',
|
|
118
|
+
total_recipients INTEGER DEFAULT 0,
|
|
119
|
+
sent_count INTEGER DEFAULT 0,
|
|
120
|
+
failed_count INTEGER DEFAULT 0,
|
|
121
|
+
bounce_count INTEGER DEFAULT 0,
|
|
122
|
+
complaint_count INTEGER DEFAULT 0,
|
|
123
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
124
|
+
started_at TEXT,
|
|
125
|
+
completed_at TEXT
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
CREATE TABLE IF NOT EXISTS email_queue (
|
|
129
|
+
id TEXT PRIMARY KEY,
|
|
130
|
+
campaign_id TEXT REFERENCES email_campaigns(id) ON DELETE CASCADE,
|
|
131
|
+
lead_id TEXT REFERENCES leads(id) ON DELETE SET NULL,
|
|
132
|
+
to_email TEXT NOT NULL,
|
|
133
|
+
status TEXT DEFAULT 'pending',
|
|
134
|
+
ses_message_id TEXT,
|
|
135
|
+
error TEXT,
|
|
136
|
+
attempts INTEGER DEFAULT 0,
|
|
137
|
+
scheduled_at TEXT,
|
|
138
|
+
sent_at TEXT,
|
|
139
|
+
created_at TEXT DEFAULT (datetime('now'))
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
CREATE INDEX IF NOT EXISTS idx_email_queue_status_scheduled
|
|
143
|
+
ON email_queue(status, scheduled_at);
|
|
144
|
+
CREATE INDEX IF NOT EXISTS idx_email_queue_ses_message_id
|
|
145
|
+
ON email_queue(ses_message_id);
|
|
146
|
+
CREATE INDEX IF NOT EXISTS idx_email_queue_campaign_status
|
|
147
|
+
ON email_queue(campaign_id, status);
|
|
148
|
+
CREATE INDEX IF NOT EXISTS idx_lead_tags_tag
|
|
149
|
+
ON lead_tags(tag);
|
|
150
|
+
CREATE INDEX IF NOT EXISTS idx_lead_lists_list_name
|
|
151
|
+
ON lead_lists(list_name);
|
|
82
152
|
`;
|
|
83
153
|
//# sourceMappingURL=schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuJzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"campaign-routes.test.d.ts","sourceRoot":"","sources":["../../../src/email/__tests__/campaign-routes.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import Fastify from 'fastify';
|
|
3
|
+
import cookie from '@fastify/cookie';
|
|
4
|
+
import Database from 'better-sqlite3';
|
|
5
|
+
import { campaignRoutes } from '../campaign-routes.js';
|
|
6
|
+
import { leadRoutes } from '../lead-routes.js';
|
|
7
|
+
import { registerAuthMiddleware } from '../../auth/auth-middleware.js';
|
|
8
|
+
import { authRoutes } from '../../auth/auth-routes.js';
|
|
9
|
+
import { hashPassword } from '../../auth/password.js';
|
|
10
|
+
import { runMigrations } from '../../db/migrations.js';
|
|
11
|
+
const SECRET = 'test-secret-that-is-at-least-32-chars-long!!';
|
|
12
|
+
async function buildApp(db) {
|
|
13
|
+
const app = Fastify();
|
|
14
|
+
await app.register(cookie);
|
|
15
|
+
registerAuthMiddleware(app, SECRET);
|
|
16
|
+
await app.register(authRoutes, { db, jwtSecret: SECRET });
|
|
17
|
+
await app.register(leadRoutes, { db });
|
|
18
|
+
await app.register(campaignRoutes, { db });
|
|
19
|
+
await app.ready();
|
|
20
|
+
return app;
|
|
21
|
+
}
|
|
22
|
+
async function getAuthCookie(app) {
|
|
23
|
+
const res = await app.inject({
|
|
24
|
+
method: 'POST',
|
|
25
|
+
url: '/api/auth/login',
|
|
26
|
+
payload: { username: 'admin', password: 'admin123' },
|
|
27
|
+
});
|
|
28
|
+
const cookies = res.cookies;
|
|
29
|
+
const accessToken = cookies.find(c => c.name === 'access_token');
|
|
30
|
+
return `access_token=${accessToken.value}`;
|
|
31
|
+
}
|
|
32
|
+
describe('campaign routes', () => {
|
|
33
|
+
let db;
|
|
34
|
+
let app;
|
|
35
|
+
let authCookie;
|
|
36
|
+
beforeEach(async () => {
|
|
37
|
+
db = new Database(':memory:');
|
|
38
|
+
runMigrations(db);
|
|
39
|
+
const hash = await hashPassword('admin123');
|
|
40
|
+
db.prepare("INSERT INTO users (id, username, password_hash, role, created_at) VALUES (?, ?, ?, ?, ?)").run('admin-id', 'admin', hash, 'admin', new Date().toISOString());
|
|
41
|
+
app = await buildApp(db);
|
|
42
|
+
authCookie = await getAuthCookie(app);
|
|
43
|
+
});
|
|
44
|
+
afterEach(async () => {
|
|
45
|
+
await app?.close();
|
|
46
|
+
db?.close();
|
|
47
|
+
});
|
|
48
|
+
it('POST /api/email/campaigns — creates a campaign', async () => {
|
|
49
|
+
const res = await app.inject({
|
|
50
|
+
method: 'POST',
|
|
51
|
+
url: '/api/email/campaigns',
|
|
52
|
+
headers: { cookie: authCookie },
|
|
53
|
+
payload: {
|
|
54
|
+
name: 'Test Campaign',
|
|
55
|
+
subject: 'Hello',
|
|
56
|
+
body_html: '<p>Hi</p>',
|
|
57
|
+
from_email: 'noreply@test.com',
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
expect(res.statusCode).toBe(200);
|
|
61
|
+
const body = JSON.parse(res.payload);
|
|
62
|
+
expect(body.campaign.name).toBe('Test Campaign');
|
|
63
|
+
expect(body.campaign.status).toBe('draft');
|
|
64
|
+
});
|
|
65
|
+
it('GET /api/email/campaigns — lists campaigns', async () => {
|
|
66
|
+
await app.inject({
|
|
67
|
+
method: 'POST',
|
|
68
|
+
url: '/api/email/campaigns',
|
|
69
|
+
headers: { cookie: authCookie },
|
|
70
|
+
payload: { name: 'C1', subject: 'S', body_html: '<p>H</p>', from_email: 'a@b.com' },
|
|
71
|
+
});
|
|
72
|
+
const res = await app.inject({
|
|
73
|
+
method: 'GET',
|
|
74
|
+
url: '/api/email/campaigns',
|
|
75
|
+
headers: { cookie: authCookie },
|
|
76
|
+
});
|
|
77
|
+
expect(res.statusCode).toBe(200);
|
|
78
|
+
const body = JSON.parse(res.payload);
|
|
79
|
+
expect(body.data.length).toBe(1);
|
|
80
|
+
});
|
|
81
|
+
it('GET /api/email/campaigns/:id — returns a campaign', async () => {
|
|
82
|
+
const createRes = await app.inject({
|
|
83
|
+
method: 'POST',
|
|
84
|
+
url: '/api/email/campaigns',
|
|
85
|
+
headers: { cookie: authCookie },
|
|
86
|
+
payload: { name: 'C1', subject: 'S', body_html: '<p>H</p>', from_email: 'a@b.com' },
|
|
87
|
+
});
|
|
88
|
+
const id = JSON.parse(createRes.payload).campaign.id;
|
|
89
|
+
const res = await app.inject({
|
|
90
|
+
method: 'GET',
|
|
91
|
+
url: `/api/email/campaigns/${id}`,
|
|
92
|
+
headers: { cookie: authCookie },
|
|
93
|
+
});
|
|
94
|
+
expect(res.statusCode).toBe(200);
|
|
95
|
+
expect(JSON.parse(res.payload).campaign.id).toBe(id);
|
|
96
|
+
});
|
|
97
|
+
it('POST /:id/enqueue — enqueues recipients', async () => {
|
|
98
|
+
await app.inject({
|
|
99
|
+
method: 'POST',
|
|
100
|
+
url: '/api/email/leads',
|
|
101
|
+
headers: { cookie: authCookie },
|
|
102
|
+
payload: { email: 'recipient@test.com', name: 'Bob' },
|
|
103
|
+
});
|
|
104
|
+
const createRes = await app.inject({
|
|
105
|
+
method: 'POST',
|
|
106
|
+
url: '/api/email/campaigns',
|
|
107
|
+
headers: { cookie: authCookie },
|
|
108
|
+
payload: { name: 'C1', subject: 'S', body_html: '<p>H</p>', from_email: 'a@b.com' },
|
|
109
|
+
});
|
|
110
|
+
const id = JSON.parse(createRes.payload).campaign.id;
|
|
111
|
+
const res = await app.inject({
|
|
112
|
+
method: 'POST',
|
|
113
|
+
url: `/api/email/campaigns/${id}/enqueue`,
|
|
114
|
+
headers: { cookie: authCookie },
|
|
115
|
+
payload: { filters: {} },
|
|
116
|
+
});
|
|
117
|
+
expect(res.statusCode).toBe(200);
|
|
118
|
+
const body = JSON.parse(res.payload);
|
|
119
|
+
expect(body.campaign.status).toBe('queued');
|
|
120
|
+
expect(body.campaign.total_recipients).toBe(1);
|
|
121
|
+
});
|
|
122
|
+
it('POST /:id/start — starts a queued campaign', async () => {
|
|
123
|
+
await app.inject({
|
|
124
|
+
method: 'POST',
|
|
125
|
+
url: '/api/email/leads',
|
|
126
|
+
headers: { cookie: authCookie },
|
|
127
|
+
payload: { email: 'r@t.com' },
|
|
128
|
+
});
|
|
129
|
+
const createRes = await app.inject({
|
|
130
|
+
method: 'POST',
|
|
131
|
+
url: '/api/email/campaigns',
|
|
132
|
+
headers: { cookie: authCookie },
|
|
133
|
+
payload: { name: 'C1', subject: 'S', body_html: '<p>H</p>', from_email: 'a@b.com' },
|
|
134
|
+
});
|
|
135
|
+
const id = JSON.parse(createRes.payload).campaign.id;
|
|
136
|
+
await app.inject({
|
|
137
|
+
method: 'POST',
|
|
138
|
+
url: `/api/email/campaigns/${id}/enqueue`,
|
|
139
|
+
headers: { cookie: authCookie },
|
|
140
|
+
payload: { filters: {} },
|
|
141
|
+
});
|
|
142
|
+
const res = await app.inject({
|
|
143
|
+
method: 'POST',
|
|
144
|
+
url: `/api/email/campaigns/${id}/start`,
|
|
145
|
+
headers: { cookie: authCookie },
|
|
146
|
+
});
|
|
147
|
+
expect(res.statusCode).toBe(200);
|
|
148
|
+
expect(JSON.parse(res.payload).campaign.status).toBe('sending');
|
|
149
|
+
});
|
|
150
|
+
it('POST /:id/cancel — cancels a campaign', async () => {
|
|
151
|
+
await app.inject({
|
|
152
|
+
method: 'POST',
|
|
153
|
+
url: '/api/email/leads',
|
|
154
|
+
headers: { cookie: authCookie },
|
|
155
|
+
payload: { email: 'r@t.com' },
|
|
156
|
+
});
|
|
157
|
+
const createRes = await app.inject({
|
|
158
|
+
method: 'POST',
|
|
159
|
+
url: '/api/email/campaigns',
|
|
160
|
+
headers: { cookie: authCookie },
|
|
161
|
+
payload: { name: 'C1', subject: 'S', body_html: '<p>H</p>', from_email: 'a@b.com' },
|
|
162
|
+
});
|
|
163
|
+
const id = JSON.parse(createRes.payload).campaign.id;
|
|
164
|
+
await app.inject({
|
|
165
|
+
method: 'POST',
|
|
166
|
+
url: `/api/email/campaigns/${id}/enqueue`,
|
|
167
|
+
headers: { cookie: authCookie },
|
|
168
|
+
payload: { filters: {} },
|
|
169
|
+
});
|
|
170
|
+
const res = await app.inject({
|
|
171
|
+
method: 'POST',
|
|
172
|
+
url: `/api/email/campaigns/${id}/cancel`,
|
|
173
|
+
headers: { cookie: authCookie },
|
|
174
|
+
});
|
|
175
|
+
expect(res.statusCode).toBe(200);
|
|
176
|
+
expect(JSON.parse(res.payload).campaign.status).toBe('cancelled');
|
|
177
|
+
});
|
|
178
|
+
it('GET /:id/queue — returns queue items', async () => {
|
|
179
|
+
await app.inject({
|
|
180
|
+
method: 'POST',
|
|
181
|
+
url: '/api/email/leads',
|
|
182
|
+
headers: { cookie: authCookie },
|
|
183
|
+
payload: { email: 'r@t.com' },
|
|
184
|
+
});
|
|
185
|
+
const createRes = await app.inject({
|
|
186
|
+
method: 'POST',
|
|
187
|
+
url: '/api/email/campaigns',
|
|
188
|
+
headers: { cookie: authCookie },
|
|
189
|
+
payload: { name: 'C1', subject: 'S', body_html: '<p>H</p>', from_email: 'a@b.com' },
|
|
190
|
+
});
|
|
191
|
+
const id = JSON.parse(createRes.payload).campaign.id;
|
|
192
|
+
await app.inject({
|
|
193
|
+
method: 'POST',
|
|
194
|
+
url: `/api/email/campaigns/${id}/enqueue`,
|
|
195
|
+
headers: { cookie: authCookie },
|
|
196
|
+
payload: { filters: {} },
|
|
197
|
+
});
|
|
198
|
+
const res = await app.inject({
|
|
199
|
+
method: 'GET',
|
|
200
|
+
url: `/api/email/campaigns/${id}/queue`,
|
|
201
|
+
headers: { cookie: authCookie },
|
|
202
|
+
});
|
|
203
|
+
expect(res.statusCode).toBe(200);
|
|
204
|
+
const body = JSON.parse(res.payload);
|
|
205
|
+
expect(body.data.length).toBe(1);
|
|
206
|
+
expect(body.total).toBe(1);
|
|
207
|
+
});
|
|
208
|
+
it('rejects unauthenticated requests', async () => {
|
|
209
|
+
const res = await app.inject({
|
|
210
|
+
method: 'GET',
|
|
211
|
+
url: '/api/email/campaigns',
|
|
212
|
+
});
|
|
213
|
+
expect(res.statusCode).toBe(401);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
//# sourceMappingURL=campaign-routes.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"campaign-routes.test.js","sourceRoot":"","sources":["../../../src/email/__tests__/campaign-routes.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"campaign-service.test.d.ts","sourceRoot":"","sources":["../../../src/email/__tests__/campaign-service.test.ts"],"names":[],"mappings":""}
|