@exulu/backend 0.1.6 → 0.1.7
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/index.cjs +27 -18
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +27 -18
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -56,18 +56,26 @@ var redisServer = {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
// src/redis/client.ts
|
|
59
|
-
var
|
|
60
|
-
|
|
61
|
-
if (!
|
|
59
|
+
var client = {};
|
|
60
|
+
async function redisClient() {
|
|
61
|
+
if (!redisServer.host || !redisServer.port) {
|
|
62
|
+
return {
|
|
63
|
+
client: null
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (!client["exulu"]) {
|
|
62
67
|
const url = `redis://${redisServer.host}:${redisServer.port}`;
|
|
63
68
|
console.log(`[EXULU] connecting to redis.`);
|
|
64
|
-
|
|
69
|
+
client["exulu"] = (0, import_redis.createClient)({
|
|
65
70
|
// todo add password
|
|
66
71
|
url
|
|
67
72
|
});
|
|
68
|
-
await
|
|
73
|
+
await client["exulu"].connect();
|
|
69
74
|
}
|
|
70
|
-
|
|
75
|
+
return {
|
|
76
|
+
client: client["exulu"]
|
|
77
|
+
};
|
|
78
|
+
}
|
|
71
79
|
|
|
72
80
|
// src/bullmq/validators.ts
|
|
73
81
|
var validateJob = (job) => {
|
|
@@ -1382,7 +1390,8 @@ var import_express3 = require("express");
|
|
|
1382
1390
|
|
|
1383
1391
|
// src/registry/rate-limiter.ts
|
|
1384
1392
|
var rateLimiter = async (key, windowSeconds, limit, points) => {
|
|
1385
|
-
|
|
1393
|
+
const { client: client2 } = await redisClient();
|
|
1394
|
+
if (!client2) {
|
|
1386
1395
|
return {
|
|
1387
1396
|
status: false,
|
|
1388
1397
|
retryAfter: 10
|
|
@@ -1390,12 +1399,12 @@ var rateLimiter = async (key, windowSeconds, limit, points) => {
|
|
|
1390
1399
|
};
|
|
1391
1400
|
}
|
|
1392
1401
|
const redisKey = `exulu/${key}`;
|
|
1393
|
-
const current = await
|
|
1402
|
+
const current = await client2.incrBy(redisKey, points);
|
|
1394
1403
|
if (current === points) {
|
|
1395
|
-
await
|
|
1404
|
+
await client2.expire(redisKey, windowSeconds);
|
|
1396
1405
|
}
|
|
1397
1406
|
if (current > limit) {
|
|
1398
|
-
const ttl = await
|
|
1407
|
+
const ttl = await client2.ttl(redisKey);
|
|
1399
1408
|
return {
|
|
1400
1409
|
status: false,
|
|
1401
1410
|
retryAfter: ttl
|
|
@@ -2310,7 +2319,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2310
2319
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
2311
2320
|
return;
|
|
2312
2321
|
}
|
|
2313
|
-
const
|
|
2322
|
+
const client2 = getS3Client();
|
|
2314
2323
|
const { type, metadata, filename } = req.body;
|
|
2315
2324
|
if (typeof filename !== "string") {
|
|
2316
2325
|
return res.status(400).json({ error: "s3: content filename must be a string" });
|
|
@@ -2332,7 +2341,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2332
2341
|
Metadata: metadata
|
|
2333
2342
|
};
|
|
2334
2343
|
const command = new CreateMultipartUploadCommand(params);
|
|
2335
|
-
return
|
|
2344
|
+
return client2.send(command, (err, data) => {
|
|
2336
2345
|
if (err) {
|
|
2337
2346
|
next(err);
|
|
2338
2347
|
return;
|
|
@@ -2369,7 +2378,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2369
2378
|
}, next);
|
|
2370
2379
|
});
|
|
2371
2380
|
app.get("/s3/multipart/:uploadId", (req, res, next) => {
|
|
2372
|
-
const
|
|
2381
|
+
const client2 = getS3Client();
|
|
2373
2382
|
const { uploadId } = req.params;
|
|
2374
2383
|
const { key } = req.query;
|
|
2375
2384
|
if (typeof key !== "string") {
|
|
@@ -2378,7 +2387,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2378
2387
|
}
|
|
2379
2388
|
const parts = [];
|
|
2380
2389
|
function listPartsPage(startAt) {
|
|
2381
|
-
|
|
2390
|
+
client2.send(new ListPartsCommand({
|
|
2382
2391
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2383
2392
|
Key: key,
|
|
2384
2393
|
UploadId: uploadId,
|
|
@@ -2402,7 +2411,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2402
2411
|
return part && typeof part === "object" && Number(part.PartNumber) && typeof part.ETag === "string";
|
|
2403
2412
|
}
|
|
2404
2413
|
app.post("/s3/multipart/:uploadId/complete", (req, res, next) => {
|
|
2405
|
-
const
|
|
2414
|
+
const client2 = getS3Client();
|
|
2406
2415
|
const { uploadId } = req.params;
|
|
2407
2416
|
const { key } = req.query;
|
|
2408
2417
|
const { parts } = req.body;
|
|
@@ -2412,7 +2421,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2412
2421
|
if (!Array.isArray(parts) || !parts.every(isValidPart)) {
|
|
2413
2422
|
return res.status(400).json({ error: "s3: `parts` must be an array of {ETag, PartNumber} objects." });
|
|
2414
2423
|
}
|
|
2415
|
-
return
|
|
2424
|
+
return client2.send(new CompleteMultipartUploadCommand({
|
|
2416
2425
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2417
2426
|
Key: key,
|
|
2418
2427
|
UploadId: uploadId,
|
|
@@ -2431,13 +2440,13 @@ var createUppyRoutes = async (app) => {
|
|
|
2431
2440
|
});
|
|
2432
2441
|
});
|
|
2433
2442
|
app.delete("/s3/multipart/:uploadId", (req, res, next) => {
|
|
2434
|
-
const
|
|
2443
|
+
const client2 = getS3Client();
|
|
2435
2444
|
const { uploadId } = req.params;
|
|
2436
2445
|
const { key } = req.query;
|
|
2437
2446
|
if (typeof key !== "string") {
|
|
2438
2447
|
return res.status(400).json({ error: 's3: the object key must be passed as a query parameter. For example: "?key=abc.jpg"' });
|
|
2439
2448
|
}
|
|
2440
|
-
return
|
|
2449
|
+
return client2.send(new AbortMultipartUploadCommand({
|
|
2441
2450
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2442
2451
|
Key: key,
|
|
2443
2452
|
UploadId: uploadId
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as bullmq from 'bullmq';
|
|
2
2
|
import { Queue } from 'bullmq';
|
|
3
|
-
import
|
|
3
|
+
import { RedisClientType } from 'redis';
|
|
4
4
|
import * as _mastra_core from '@mastra/core';
|
|
5
5
|
import { ToolAction, Workflow, Agent } from '@mastra/core';
|
|
6
6
|
import { ZodSchema, z } from 'zod';
|
|
@@ -8,6 +8,10 @@ import { LanguageModelV1 } from 'ai';
|
|
|
8
8
|
import { Express } from 'express';
|
|
9
9
|
import { Knex } from 'knex';
|
|
10
10
|
|
|
11
|
+
declare function redisClient(): Promise<{
|
|
12
|
+
client: RedisClientType | null;
|
|
13
|
+
}>;
|
|
14
|
+
|
|
11
15
|
type STATISTICS_TYPE = "context.retrieve" | "source.update" | "embedder.upsert" | "embedder.delete" | "workflow.run" | "context.upsert" | "tool.call" | "agent.run";
|
|
12
16
|
declare const STATISTICS_TYPE_ENUM: {
|
|
13
17
|
CONTEXT_RETRIEVE: string;
|
|
@@ -437,7 +441,7 @@ declare class ExuluQueues {
|
|
|
437
441
|
declare const queues: ExuluQueues;
|
|
438
442
|
|
|
439
443
|
declare const ExuluJobs: {
|
|
440
|
-
redis:
|
|
444
|
+
redis: typeof redisClient;
|
|
441
445
|
jobs: {
|
|
442
446
|
validate: (job: bullmq.Job) => bullmq.Job<any, any, string>;
|
|
443
447
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as bullmq from 'bullmq';
|
|
2
2
|
import { Queue } from 'bullmq';
|
|
3
|
-
import
|
|
3
|
+
import { RedisClientType } from 'redis';
|
|
4
4
|
import * as _mastra_core from '@mastra/core';
|
|
5
5
|
import { ToolAction, Workflow, Agent } from '@mastra/core';
|
|
6
6
|
import { ZodSchema, z } from 'zod';
|
|
@@ -8,6 +8,10 @@ import { LanguageModelV1 } from 'ai';
|
|
|
8
8
|
import { Express } from 'express';
|
|
9
9
|
import { Knex } from 'knex';
|
|
10
10
|
|
|
11
|
+
declare function redisClient(): Promise<{
|
|
12
|
+
client: RedisClientType | null;
|
|
13
|
+
}>;
|
|
14
|
+
|
|
11
15
|
type STATISTICS_TYPE = "context.retrieve" | "source.update" | "embedder.upsert" | "embedder.delete" | "workflow.run" | "context.upsert" | "tool.call" | "agent.run";
|
|
12
16
|
declare const STATISTICS_TYPE_ENUM: {
|
|
13
17
|
CONTEXT_RETRIEVE: string;
|
|
@@ -437,7 +441,7 @@ declare class ExuluQueues {
|
|
|
437
441
|
declare const queues: ExuluQueues;
|
|
438
442
|
|
|
439
443
|
declare const ExuluJobs: {
|
|
440
|
-
redis:
|
|
444
|
+
redis: typeof redisClient;
|
|
441
445
|
jobs: {
|
|
442
446
|
validate: (job: bullmq.Job) => bullmq.Job<any, any, string>;
|
|
443
447
|
};
|
package/dist/index.js
CHANGED
|
@@ -15,18 +15,26 @@ var redisServer = {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
// src/redis/client.ts
|
|
18
|
-
var
|
|
19
|
-
|
|
20
|
-
if (!
|
|
18
|
+
var client = {};
|
|
19
|
+
async function redisClient() {
|
|
20
|
+
if (!redisServer.host || !redisServer.port) {
|
|
21
|
+
return {
|
|
22
|
+
client: null
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (!client["exulu"]) {
|
|
21
26
|
const url = `redis://${redisServer.host}:${redisServer.port}`;
|
|
22
27
|
console.log(`[EXULU] connecting to redis.`);
|
|
23
|
-
|
|
28
|
+
client["exulu"] = createClient({
|
|
24
29
|
// todo add password
|
|
25
30
|
url
|
|
26
31
|
});
|
|
27
|
-
await
|
|
32
|
+
await client["exulu"].connect();
|
|
28
33
|
}
|
|
29
|
-
|
|
34
|
+
return {
|
|
35
|
+
client: client["exulu"]
|
|
36
|
+
};
|
|
37
|
+
}
|
|
30
38
|
|
|
31
39
|
// src/bullmq/validators.ts
|
|
32
40
|
var validateJob = (job) => {
|
|
@@ -1341,7 +1349,8 @@ import "express";
|
|
|
1341
1349
|
|
|
1342
1350
|
// src/registry/rate-limiter.ts
|
|
1343
1351
|
var rateLimiter = async (key, windowSeconds, limit, points) => {
|
|
1344
|
-
|
|
1352
|
+
const { client: client2 } = await redisClient();
|
|
1353
|
+
if (!client2) {
|
|
1345
1354
|
return {
|
|
1346
1355
|
status: false,
|
|
1347
1356
|
retryAfter: 10
|
|
@@ -1349,12 +1358,12 @@ var rateLimiter = async (key, windowSeconds, limit, points) => {
|
|
|
1349
1358
|
};
|
|
1350
1359
|
}
|
|
1351
1360
|
const redisKey = `exulu/${key}`;
|
|
1352
|
-
const current = await
|
|
1361
|
+
const current = await client2.incrBy(redisKey, points);
|
|
1353
1362
|
if (current === points) {
|
|
1354
|
-
await
|
|
1363
|
+
await client2.expire(redisKey, windowSeconds);
|
|
1355
1364
|
}
|
|
1356
1365
|
if (current > limit) {
|
|
1357
|
-
const ttl = await
|
|
1366
|
+
const ttl = await client2.ttl(redisKey);
|
|
1358
1367
|
return {
|
|
1359
1368
|
status: false,
|
|
1360
1369
|
retryAfter: ttl
|
|
@@ -2269,7 +2278,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2269
2278
|
res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
|
|
2270
2279
|
return;
|
|
2271
2280
|
}
|
|
2272
|
-
const
|
|
2281
|
+
const client2 = getS3Client();
|
|
2273
2282
|
const { type, metadata, filename } = req.body;
|
|
2274
2283
|
if (typeof filename !== "string") {
|
|
2275
2284
|
return res.status(400).json({ error: "s3: content filename must be a string" });
|
|
@@ -2291,7 +2300,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2291
2300
|
Metadata: metadata
|
|
2292
2301
|
};
|
|
2293
2302
|
const command = new CreateMultipartUploadCommand(params);
|
|
2294
|
-
return
|
|
2303
|
+
return client2.send(command, (err, data) => {
|
|
2295
2304
|
if (err) {
|
|
2296
2305
|
next(err);
|
|
2297
2306
|
return;
|
|
@@ -2328,7 +2337,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2328
2337
|
}, next);
|
|
2329
2338
|
});
|
|
2330
2339
|
app.get("/s3/multipart/:uploadId", (req, res, next) => {
|
|
2331
|
-
const
|
|
2340
|
+
const client2 = getS3Client();
|
|
2332
2341
|
const { uploadId } = req.params;
|
|
2333
2342
|
const { key } = req.query;
|
|
2334
2343
|
if (typeof key !== "string") {
|
|
@@ -2337,7 +2346,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2337
2346
|
}
|
|
2338
2347
|
const parts = [];
|
|
2339
2348
|
function listPartsPage(startAt) {
|
|
2340
|
-
|
|
2349
|
+
client2.send(new ListPartsCommand({
|
|
2341
2350
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2342
2351
|
Key: key,
|
|
2343
2352
|
UploadId: uploadId,
|
|
@@ -2361,7 +2370,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2361
2370
|
return part && typeof part === "object" && Number(part.PartNumber) && typeof part.ETag === "string";
|
|
2362
2371
|
}
|
|
2363
2372
|
app.post("/s3/multipart/:uploadId/complete", (req, res, next) => {
|
|
2364
|
-
const
|
|
2373
|
+
const client2 = getS3Client();
|
|
2365
2374
|
const { uploadId } = req.params;
|
|
2366
2375
|
const { key } = req.query;
|
|
2367
2376
|
const { parts } = req.body;
|
|
@@ -2371,7 +2380,7 @@ var createUppyRoutes = async (app) => {
|
|
|
2371
2380
|
if (!Array.isArray(parts) || !parts.every(isValidPart)) {
|
|
2372
2381
|
return res.status(400).json({ error: "s3: `parts` must be an array of {ETag, PartNumber} objects." });
|
|
2373
2382
|
}
|
|
2374
|
-
return
|
|
2383
|
+
return client2.send(new CompleteMultipartUploadCommand({
|
|
2375
2384
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2376
2385
|
Key: key,
|
|
2377
2386
|
UploadId: uploadId,
|
|
@@ -2390,13 +2399,13 @@ var createUppyRoutes = async (app) => {
|
|
|
2390
2399
|
});
|
|
2391
2400
|
});
|
|
2392
2401
|
app.delete("/s3/multipart/:uploadId", (req, res, next) => {
|
|
2393
|
-
const
|
|
2402
|
+
const client2 = getS3Client();
|
|
2394
2403
|
const { uploadId } = req.params;
|
|
2395
2404
|
const { key } = req.query;
|
|
2396
2405
|
if (typeof key !== "string") {
|
|
2397
2406
|
return res.status(400).json({ error: 's3: the object key must be passed as a query parameter. For example: "?key=abc.jpg"' });
|
|
2398
2407
|
}
|
|
2399
|
-
return
|
|
2408
|
+
return client2.send(new AbortMultipartUploadCommand({
|
|
2400
2409
|
Bucket: process.env.COMPANION_S3_BUCKET,
|
|
2401
2410
|
Key: key,
|
|
2402
2411
|
UploadId: uploadId
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exulu/backend",
|
|
3
3
|
"author": "Qventu Bv.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.7",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"private": false,
|
|
7
7
|
"publishConfig": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
18
|
-
"url": "https://github.com/Qventu/exulu-
|
|
18
|
+
"url": "https://github.com/Qventu/exulu-backend"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "tsup",
|