@exulu/backend 0.2.1 → 0.2.3

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 CHANGED
@@ -194,6 +194,10 @@ var usersSchema = {
194
194
  name: "apikey",
195
195
  type: "text"
196
196
  },
197
+ {
198
+ name: "last_used",
199
+ type: "date"
200
+ },
197
201
  {
198
202
  name: "role",
199
203
  type: "reference",
@@ -202,10 +206,6 @@ var usersSchema = {
202
206
  field: "id",
203
207
  onDelete: "CASCADE"
204
208
  }
205
- },
206
- {
207
- name: "last_used",
208
- type: "date"
209
209
  }
210
210
  ]
211
211
  };
@@ -404,7 +404,61 @@ var sanitizeName = (name) => {
404
404
  };
405
405
 
406
406
  // src/postgres/init-db.ts
407
+ var import_bcryptjs2 = __toESM(require("bcryptjs"), 1);
408
+
409
+ // src/auth/generate-key.ts
407
410
  var import_bcryptjs = __toESM(require("bcryptjs"), 1);
411
+ var SALT_ROUNDS = 12;
412
+ async function encryptApiKey(apikey) {
413
+ const hash = await import_bcryptjs.default.hash(apikey, SALT_ROUNDS);
414
+ return hash;
415
+ }
416
+ var generateApiKey = async (name, email) => {
417
+ const { db: db2 } = await postgresClient();
418
+ console.log("[EXULU] Inserting default user and admin role.");
419
+ const existingRole = await db2.from("roles").where({ name: "admin" }).first();
420
+ let roleId;
421
+ if (!existingRole) {
422
+ console.log("[EXULU] Creating default admin role.");
423
+ const role = await db2.from("roles").insert({
424
+ name: "admin",
425
+ is_admin: true,
426
+ agents: []
427
+ }).returning("id");
428
+ roleId = role[0].id;
429
+ } else {
430
+ roleId = existingRole.id;
431
+ }
432
+ const newKeyName = name;
433
+ const plainKey = `sk_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
434
+ const postFix = `/${newKeyName.toLowerCase().trim().replaceAll(" ", "_")}`;
435
+ const encryptedKey = await encryptApiKey(plainKey);
436
+ const existingApiUser = await db2.from("users").where({ email }).first();
437
+ if (!existingApiUser) {
438
+ console.log("[EXULU] Creating default api user.");
439
+ await db2.from("users").insert({
440
+ name,
441
+ email,
442
+ super_admin: true,
443
+ createdAt: /* @__PURE__ */ new Date(),
444
+ updatedAt: /* @__PURE__ */ new Date(),
445
+ type: "api",
446
+ apikey: `${encryptedKey}${postFix}`,
447
+ // password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
448
+ role: roleId
449
+ });
450
+ console.log("[EXULU] Default api user created. Key: ", `${plainKey}${postFix}`);
451
+ } else {
452
+ console.log("[EXULU] API user with that name already exists.");
453
+ }
454
+ console.log("[EXULU] Key generated, copy and use the plain key from here, you will not be able to access it again.");
455
+ console.log("[EXULU] Key: ", `${plainKey}${postFix}`);
456
+ return {
457
+ key: `${plainKey}${postFix}`
458
+ };
459
+ };
460
+
461
+ // src/postgres/init-db.ts
408
462
  var up = async function(knex) {
409
463
  if (!await knex.schema.hasTable("roles")) {
410
464
  await knex.schema.createTable("roles", (table) => {
@@ -509,6 +563,7 @@ var up = async function(knex) {
509
563
  table.timestamp("emailVerified", { useTz: true });
510
564
  table.text("image");
511
565
  for (const field of usersSchema.fields) {
566
+ console.log("[EXULU] field", field);
512
567
  const { type, name, references, default: defaultValue } = field;
513
568
  if (name === "id" || name === "name" || name === "email" || name === "emailVerified" || name === "image") {
514
569
  continue;
@@ -552,9 +607,9 @@ var up = async function(knex) {
552
607
  });
553
608
  }
554
609
  };
555
- var SALT_ROUNDS = 12;
556
- async function encryptApiKey(apikey) {
557
- const hash = await import_bcryptjs.default.hash(apikey, SALT_ROUNDS);
610
+ var SALT_ROUNDS2 = 12;
611
+ async function encryptApiKey2(apikey) {
612
+ const hash = await import_bcryptjs2.default.hash(apikey, SALT_ROUNDS2);
558
613
  return hash;
559
614
  }
560
615
  var execute = async () => {
@@ -578,7 +633,7 @@ var execute = async () => {
578
633
  const newKeyName = "exulu_default_key";
579
634
  const plainKey = `sk_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
580
635
  const postFix = `/${newKeyName.toLowerCase().trim().replaceAll(" ", "_")}`;
581
- const encryptedKey = await encryptApiKey(plainKey);
636
+ const encryptedKey = await encryptApiKey2(plainKey);
582
637
  const existingUser = await db2.from("users").where({ email: "admin@exulu.com" }).first();
583
638
  if (!existingUser) {
584
639
  console.log("[EXULU] Creating default admin user.");
@@ -593,23 +648,9 @@ var execute = async () => {
593
648
  role: roleId
594
649
  });
595
650
  }
596
- const existingApiUser = await db2.from("users").where({ email: "api@exulu.com" }).first();
597
- if (!existingApiUser) {
598
- console.log("[EXULU] Creating default api user.");
599
- await db2.from("users").insert({
600
- name: "exulu",
601
- email: "admin@exulu.com",
602
- super_admin: true,
603
- createdAt: /* @__PURE__ */ new Date(),
604
- updatedAt: /* @__PURE__ */ new Date(),
605
- type: "api",
606
- apikey: `${encryptedKey}${postFix}`,
607
- // password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
608
- role: roleId
609
- });
610
- }
651
+ const { key } = await generateApiKey("exulu", "api@exulu.com");
611
652
  console.log("[EXULU] Database initialized.");
612
- console.log("[EXULU] Default api key: ", `${encryptedKey}${postFix}`);
653
+ console.log("[EXULU] Default api key: ", `${key}`);
613
654
  return;
614
655
  };
615
656
 
@@ -1469,13 +1510,14 @@ var import_express = require("express");
1469
1510
  var import_jwt = require("next-auth/jwt");
1470
1511
 
1471
1512
  // src/auth/auth.ts
1472
- var import_bcryptjs2 = __toESM(require("bcryptjs"), 1);
1513
+ var import_bcryptjs3 = __toESM(require("bcryptjs"), 1);
1473
1514
  var authentication = async ({
1474
1515
  apikey,
1475
1516
  authtoken,
1476
1517
  internalkey,
1477
1518
  db: db2
1478
1519
  }) => {
1520
+ console.log("[EXULU] apikey", apikey);
1479
1521
  if (internalkey) {
1480
1522
  if (!process.env.INTERNAL_SECRET) {
1481
1523
  return {
@@ -1543,31 +1585,38 @@ var authentication = async ({
1543
1585
  code: 401
1544
1586
  };
1545
1587
  }
1546
- const keyParts = apikey.split("/");
1547
- const keyName = keyParts.pop();
1548
- const keyValue = keyParts[0];
1549
- if (!keyName) {
1588
+ const request_key_parts = apikey.split("/");
1589
+ const request_key_name = request_key_parts.pop();
1590
+ const request_key_last_slash_index = apikey.lastIndexOf("/");
1591
+ const request_key_compare_value = apikey.substring(0, request_key_last_slash_index);
1592
+ if (!request_key_name) {
1550
1593
  return {
1551
1594
  error: true,
1552
1595
  message: "Provided api key does not include postfix with key name ({key}/{name}).",
1553
1596
  code: 401
1554
1597
  };
1555
1598
  }
1556
- if (!keyValue) {
1599
+ if (!request_key_compare_value) {
1557
1600
  return {
1558
1601
  error: true,
1559
1602
  message: "Provided api key is not in the correct format.",
1560
1603
  code: 401
1561
1604
  };
1562
1605
  }
1563
- const filtered = users.filter(({ apikey: apikey2, id }) => apikey2.includes(keyName));
1606
+ console.log("[EXULU] users", users);
1607
+ console.log("[EXULU] request_key_name", request_key_name);
1608
+ console.log("[EXULU] request_key_compare_value", request_key_compare_value);
1609
+ const filtered = users.filter(({ apikey: apikey2, id }) => apikey2.includes(request_key_name));
1610
+ console.log("[EXULU] filtered", filtered);
1564
1611
  for (const user of filtered) {
1565
- const lastSlashIndex = user.apikey.lastIndexOf("/");
1566
- const compareValue = lastSlashIndex !== -1 ? user.apikey.substring(0, lastSlashIndex) : user.apikey;
1567
- const isMatch = await import_bcryptjs2.default.compare(keyValue, compareValue);
1612
+ const user_key_last_slash_index = user.apikey.lastIndexOf("/");
1613
+ const user_key_compare_value = user.apikey.substring(0, user_key_last_slash_index);
1614
+ console.log("[EXULU] user_key_compare_value", user_key_compare_value);
1615
+ const isMatch = await import_bcryptjs3.default.compare(request_key_compare_value, user_key_compare_value);
1616
+ console.log("[EXULU] isMatch", isMatch);
1568
1617
  if (isMatch) {
1569
1618
  await db2.from("users").where({ id: user.id }).update({
1570
- lastUsed: /* @__PURE__ */ new Date()
1619
+ last_used: /* @__PURE__ */ new Date()
1571
1620
  }).returning("id");
1572
1621
  return {
1573
1622
  error: false,
@@ -1576,6 +1625,12 @@ var authentication = async ({
1576
1625
  };
1577
1626
  }
1578
1627
  }
1628
+ console.log("[EXULU] No matching api key found.");
1629
+ return {
1630
+ error: true,
1631
+ message: "No matching api key found.",
1632
+ code: 401
1633
+ };
1579
1634
  }
1580
1635
  return {
1581
1636
  error: true,
@@ -2723,13 +2778,22 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
2723
2778
  if (!exists) {
2724
2779
  throw new Error("Table with name " + context.getTableName() + " does not exist.");
2725
2780
  }
2726
- const mutation = db2.from(context.getTableName()).delete().returning("id");
2781
+ const query = db2.from(context.getTableName()).select("id");
2727
2782
  if (id) {
2728
- mutation.where({ id });
2783
+ query.where({ id });
2729
2784
  }
2730
2785
  if (external_id) {
2731
- mutation.where({ external_id });
2786
+ query.where({ external_id });
2787
+ }
2788
+ const item = await query.first();
2789
+ if (!item) {
2790
+ throw new Error("Item not found.");
2732
2791
  }
2792
+ const chunks = await db2.from(context.getChunksTableName()).where({ source: item.id }).select("id");
2793
+ if (chunks.length > 0) {
2794
+ await db2.from(context.getChunksTableName()).where({ source: item.id }).delete();
2795
+ }
2796
+ const mutation = db2.from(context.getTableName()).where({ id: item.id }).delete().returning("id");
2733
2797
  const result = await mutation;
2734
2798
  return result;
2735
2799
  };
@@ -2840,12 +2904,25 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
2840
2904
  });
2841
2905
  app.post("/items/:context", async (req, res) => {
2842
2906
  try {
2907
+ console.log("[EXULU] post items");
2843
2908
  if (!req.params.context) {
2844
2909
  res.status(400).json({
2845
2910
  message: "Missing context in request."
2846
2911
  });
2847
2912
  return;
2848
2913
  }
2914
+ if (!req.body) {
2915
+ res.status(400).json({
2916
+ message: "Missing body in request."
2917
+ });
2918
+ return;
2919
+ }
2920
+ if (!req.body.name) {
2921
+ res.status(400).json({
2922
+ message: "Missing in body of request."
2923
+ });
2924
+ return;
2925
+ }
2849
2926
  const authenticationResult = await requestValidators.authenticate(req);
2850
2927
  if (!authenticationResult.user?.id) {
2851
2928
  res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
@@ -3783,6 +3860,9 @@ var ExuluJobs = {
3783
3860
  var ExuluDatabase = {
3784
3861
  init: async () => {
3785
3862
  await execute();
3863
+ },
3864
+ generateApiKey: async (name, email) => {
3865
+ return await generateApiKey(name, email);
3786
3866
  }
3787
3867
  };
3788
3868
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.d.cts CHANGED
@@ -449,6 +449,9 @@ declare const ExuluJobs: {
449
449
 
450
450
  declare const ExuluDatabase: {
451
451
  init: () => Promise<void>;
452
+ generateApiKey: (name: string, email: string) => Promise<{
453
+ key: string;
454
+ }>;
452
455
  };
453
456
 
454
457
  export { type STATISTICS_TYPE as EXULU_STATISTICS_TYPE, STATISTICS_TYPE_ENUM as EXULU_STATISTICS_TYPE_ENUM, ExuluAgent, ExuluApp, authentication as ExuluAuthentication, ExuluContext, ExuluDatabase, ExuluEmbedder, ExuluJobs, queues as ExuluQueues, ExuluSource, ExuluTool, ExuluWorkflow, ExuluZodFileType };
package/dist/index.d.ts CHANGED
@@ -449,6 +449,9 @@ declare const ExuluJobs: {
449
449
 
450
450
  declare const ExuluDatabase: {
451
451
  init: () => Promise<void>;
452
+ generateApiKey: (name: string, email: string) => Promise<{
453
+ key: string;
454
+ }>;
452
455
  };
453
456
 
454
457
  export { type STATISTICS_TYPE as EXULU_STATISTICS_TYPE, STATISTICS_TYPE_ENUM as EXULU_STATISTICS_TYPE_ENUM, ExuluAgent, ExuluApp, authentication as ExuluAuthentication, ExuluContext, ExuluDatabase, ExuluEmbedder, ExuluJobs, queues as ExuluQueues, ExuluSource, ExuluTool, ExuluWorkflow, ExuluZodFileType };
package/dist/index.js CHANGED
@@ -153,6 +153,10 @@ var usersSchema = {
153
153
  name: "apikey",
154
154
  type: "text"
155
155
  },
156
+ {
157
+ name: "last_used",
158
+ type: "date"
159
+ },
156
160
  {
157
161
  name: "role",
158
162
  type: "reference",
@@ -161,10 +165,6 @@ var usersSchema = {
161
165
  field: "id",
162
166
  onDelete: "CASCADE"
163
167
  }
164
- },
165
- {
166
- name: "last_used",
167
- type: "date"
168
168
  }
169
169
  ]
170
170
  };
@@ -363,7 +363,61 @@ var sanitizeName = (name) => {
363
363
  };
364
364
 
365
365
  // src/postgres/init-db.ts
366
+ import bcrypt2 from "bcryptjs";
367
+
368
+ // src/auth/generate-key.ts
366
369
  import bcrypt from "bcryptjs";
370
+ var SALT_ROUNDS = 12;
371
+ async function encryptApiKey(apikey) {
372
+ const hash = await bcrypt.hash(apikey, SALT_ROUNDS);
373
+ return hash;
374
+ }
375
+ var generateApiKey = async (name, email) => {
376
+ const { db: db2 } = await postgresClient();
377
+ console.log("[EXULU] Inserting default user and admin role.");
378
+ const existingRole = await db2.from("roles").where({ name: "admin" }).first();
379
+ let roleId;
380
+ if (!existingRole) {
381
+ console.log("[EXULU] Creating default admin role.");
382
+ const role = await db2.from("roles").insert({
383
+ name: "admin",
384
+ is_admin: true,
385
+ agents: []
386
+ }).returning("id");
387
+ roleId = role[0].id;
388
+ } else {
389
+ roleId = existingRole.id;
390
+ }
391
+ const newKeyName = name;
392
+ const plainKey = `sk_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
393
+ const postFix = `/${newKeyName.toLowerCase().trim().replaceAll(" ", "_")}`;
394
+ const encryptedKey = await encryptApiKey(plainKey);
395
+ const existingApiUser = await db2.from("users").where({ email }).first();
396
+ if (!existingApiUser) {
397
+ console.log("[EXULU] Creating default api user.");
398
+ await db2.from("users").insert({
399
+ name,
400
+ email,
401
+ super_admin: true,
402
+ createdAt: /* @__PURE__ */ new Date(),
403
+ updatedAt: /* @__PURE__ */ new Date(),
404
+ type: "api",
405
+ apikey: `${encryptedKey}${postFix}`,
406
+ // password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
407
+ role: roleId
408
+ });
409
+ console.log("[EXULU] Default api user created. Key: ", `${plainKey}${postFix}`);
410
+ } else {
411
+ console.log("[EXULU] API user with that name already exists.");
412
+ }
413
+ console.log("[EXULU] Key generated, copy and use the plain key from here, you will not be able to access it again.");
414
+ console.log("[EXULU] Key: ", `${plainKey}${postFix}`);
415
+ return {
416
+ key: `${plainKey}${postFix}`
417
+ };
418
+ };
419
+
420
+ // src/postgres/init-db.ts
367
421
  var up = async function(knex) {
368
422
  if (!await knex.schema.hasTable("roles")) {
369
423
  await knex.schema.createTable("roles", (table) => {
@@ -468,6 +522,7 @@ var up = async function(knex) {
468
522
  table.timestamp("emailVerified", { useTz: true });
469
523
  table.text("image");
470
524
  for (const field of usersSchema.fields) {
525
+ console.log("[EXULU] field", field);
471
526
  const { type, name, references, default: defaultValue } = field;
472
527
  if (name === "id" || name === "name" || name === "email" || name === "emailVerified" || name === "image") {
473
528
  continue;
@@ -511,9 +566,9 @@ var up = async function(knex) {
511
566
  });
512
567
  }
513
568
  };
514
- var SALT_ROUNDS = 12;
515
- async function encryptApiKey(apikey) {
516
- const hash = await bcrypt.hash(apikey, SALT_ROUNDS);
569
+ var SALT_ROUNDS2 = 12;
570
+ async function encryptApiKey2(apikey) {
571
+ const hash = await bcrypt2.hash(apikey, SALT_ROUNDS2);
517
572
  return hash;
518
573
  }
519
574
  var execute = async () => {
@@ -537,7 +592,7 @@ var execute = async () => {
537
592
  const newKeyName = "exulu_default_key";
538
593
  const plainKey = `sk_${Math.random().toString(36).substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`;
539
594
  const postFix = `/${newKeyName.toLowerCase().trim().replaceAll(" ", "_")}`;
540
- const encryptedKey = await encryptApiKey(plainKey);
595
+ const encryptedKey = await encryptApiKey2(plainKey);
541
596
  const existingUser = await db2.from("users").where({ email: "admin@exulu.com" }).first();
542
597
  if (!existingUser) {
543
598
  console.log("[EXULU] Creating default admin user.");
@@ -552,23 +607,9 @@ var execute = async () => {
552
607
  role: roleId
553
608
  });
554
609
  }
555
- const existingApiUser = await db2.from("users").where({ email: "api@exulu.com" }).first();
556
- if (!existingApiUser) {
557
- console.log("[EXULU] Creating default api user.");
558
- await db2.from("users").insert({
559
- name: "exulu",
560
- email: "admin@exulu.com",
561
- super_admin: true,
562
- createdAt: /* @__PURE__ */ new Date(),
563
- updatedAt: /* @__PURE__ */ new Date(),
564
- type: "api",
565
- apikey: `${encryptedKey}${postFix}`,
566
- // password: "admin", todo add this again when we implement password auth / encryption as alternative to OTP
567
- role: roleId
568
- });
569
- }
610
+ const { key } = await generateApiKey("exulu", "api@exulu.com");
570
611
  console.log("[EXULU] Database initialized.");
571
- console.log("[EXULU] Default api key: ", `${encryptedKey}${postFix}`);
612
+ console.log("[EXULU] Default api key: ", `${key}`);
572
613
  return;
573
614
  };
574
615
 
@@ -1428,13 +1469,14 @@ import "express";
1428
1469
  import { getToken } from "next-auth/jwt";
1429
1470
 
1430
1471
  // src/auth/auth.ts
1431
- import bcrypt2 from "bcryptjs";
1472
+ import bcrypt3 from "bcryptjs";
1432
1473
  var authentication = async ({
1433
1474
  apikey,
1434
1475
  authtoken,
1435
1476
  internalkey,
1436
1477
  db: db2
1437
1478
  }) => {
1479
+ console.log("[EXULU] apikey", apikey);
1438
1480
  if (internalkey) {
1439
1481
  if (!process.env.INTERNAL_SECRET) {
1440
1482
  return {
@@ -1502,31 +1544,38 @@ var authentication = async ({
1502
1544
  code: 401
1503
1545
  };
1504
1546
  }
1505
- const keyParts = apikey.split("/");
1506
- const keyName = keyParts.pop();
1507
- const keyValue = keyParts[0];
1508
- if (!keyName) {
1547
+ const request_key_parts = apikey.split("/");
1548
+ const request_key_name = request_key_parts.pop();
1549
+ const request_key_last_slash_index = apikey.lastIndexOf("/");
1550
+ const request_key_compare_value = apikey.substring(0, request_key_last_slash_index);
1551
+ if (!request_key_name) {
1509
1552
  return {
1510
1553
  error: true,
1511
1554
  message: "Provided api key does not include postfix with key name ({key}/{name}).",
1512
1555
  code: 401
1513
1556
  };
1514
1557
  }
1515
- if (!keyValue) {
1558
+ if (!request_key_compare_value) {
1516
1559
  return {
1517
1560
  error: true,
1518
1561
  message: "Provided api key is not in the correct format.",
1519
1562
  code: 401
1520
1563
  };
1521
1564
  }
1522
- const filtered = users.filter(({ apikey: apikey2, id }) => apikey2.includes(keyName));
1565
+ console.log("[EXULU] users", users);
1566
+ console.log("[EXULU] request_key_name", request_key_name);
1567
+ console.log("[EXULU] request_key_compare_value", request_key_compare_value);
1568
+ const filtered = users.filter(({ apikey: apikey2, id }) => apikey2.includes(request_key_name));
1569
+ console.log("[EXULU] filtered", filtered);
1523
1570
  for (const user of filtered) {
1524
- const lastSlashIndex = user.apikey.lastIndexOf("/");
1525
- const compareValue = lastSlashIndex !== -1 ? user.apikey.substring(0, lastSlashIndex) : user.apikey;
1526
- const isMatch = await bcrypt2.compare(keyValue, compareValue);
1571
+ const user_key_last_slash_index = user.apikey.lastIndexOf("/");
1572
+ const user_key_compare_value = user.apikey.substring(0, user_key_last_slash_index);
1573
+ console.log("[EXULU] user_key_compare_value", user_key_compare_value);
1574
+ const isMatch = await bcrypt3.compare(request_key_compare_value, user_key_compare_value);
1575
+ console.log("[EXULU] isMatch", isMatch);
1527
1576
  if (isMatch) {
1528
1577
  await db2.from("users").where({ id: user.id }).update({
1529
- lastUsed: /* @__PURE__ */ new Date()
1578
+ last_used: /* @__PURE__ */ new Date()
1530
1579
  }).returning("id");
1531
1580
  return {
1532
1581
  error: false,
@@ -1535,6 +1584,12 @@ var authentication = async ({
1535
1584
  };
1536
1585
  }
1537
1586
  }
1587
+ console.log("[EXULU] No matching api key found.");
1588
+ return {
1589
+ error: true,
1590
+ message: "No matching api key found.",
1591
+ code: 401
1592
+ };
1538
1593
  }
1539
1594
  return {
1540
1595
  error: true,
@@ -2682,13 +2737,22 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
2682
2737
  if (!exists) {
2683
2738
  throw new Error("Table with name " + context.getTableName() + " does not exist.");
2684
2739
  }
2685
- const mutation = db2.from(context.getTableName()).delete().returning("id");
2740
+ const query = db2.from(context.getTableName()).select("id");
2686
2741
  if (id) {
2687
- mutation.where({ id });
2742
+ query.where({ id });
2688
2743
  }
2689
2744
  if (external_id) {
2690
- mutation.where({ external_id });
2745
+ query.where({ external_id });
2746
+ }
2747
+ const item = await query.first();
2748
+ if (!item) {
2749
+ throw new Error("Item not found.");
2691
2750
  }
2751
+ const chunks = await db2.from(context.getChunksTableName()).where({ source: item.id }).select("id");
2752
+ if (chunks.length > 0) {
2753
+ await db2.from(context.getChunksTableName()).where({ source: item.id }).delete();
2754
+ }
2755
+ const mutation = db2.from(context.getTableName()).where({ id: item.id }).delete().returning("id");
2692
2756
  const result = await mutation;
2693
2757
  return result;
2694
2758
  };
@@ -2799,12 +2863,25 @@ var createExpressRoutes = async (app, agents, embedders, tools, workflows, conte
2799
2863
  });
2800
2864
  app.post("/items/:context", async (req, res) => {
2801
2865
  try {
2866
+ console.log("[EXULU] post items");
2802
2867
  if (!req.params.context) {
2803
2868
  res.status(400).json({
2804
2869
  message: "Missing context in request."
2805
2870
  });
2806
2871
  return;
2807
2872
  }
2873
+ if (!req.body) {
2874
+ res.status(400).json({
2875
+ message: "Missing body in request."
2876
+ });
2877
+ return;
2878
+ }
2879
+ if (!req.body.name) {
2880
+ res.status(400).json({
2881
+ message: "Missing in body of request."
2882
+ });
2883
+ return;
2884
+ }
2808
2885
  const authenticationResult = await requestValidators.authenticate(req);
2809
2886
  if (!authenticationResult.user?.id) {
2810
2887
  res.status(authenticationResult.code || 500).json({ detail: `${authenticationResult.message}` });
@@ -3742,6 +3819,9 @@ var ExuluJobs = {
3742
3819
  var ExuluDatabase = {
3743
3820
  init: async () => {
3744
3821
  await execute();
3822
+ },
3823
+ generateApiKey: async (name, email) => {
3824
+ return await generateApiKey(name, email);
3745
3825
  }
3746
3826
  };
3747
3827
  export {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@exulu/backend",
3
3
  "author": "Qventu Bv.",
4
- "version": "0.2.1",
4
+ "version": "0.2.3",
5
5
  "main": "./dist/index.js",
6
6
  "private": false,
7
7
  "publishConfig": {