@librechat/data-schemas 0.0.8 → 0.0.10
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 +724 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +724 -36
- package/dist/index.es.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/methods/index.d.ts +23 -1
- package/dist/types/methods/memory.d.ts +35 -0
- package/dist/types/methods/pluginAuth.d.ts +36 -0
- package/dist/types/methods/share.d.ts +38 -0
- package/dist/types/methods/share.test.d.ts +1 -0
- package/dist/types/methods/user.d.ts +1 -0
- package/dist/types/models/index.d.ts +1 -0
- package/dist/types/models/memory.d.ts +27 -0
- package/dist/types/models/plugins/mongoMeili.d.ts +23 -1
- package/dist/types/schema/index.d.ts +1 -0
- package/dist/types/schema/memory.d.ts +29 -0
- package/dist/types/schema/pluginAuth.d.ts +2 -9
- package/dist/types/types/index.d.ts +30 -0
- package/dist/types/types/memory.d.ts +63 -0
- package/dist/types/types/pluginAuth.d.ts +59 -0
- package/dist/types/types/share.d.ts +82 -0
- package/dist/types/types/user.d.ts +3 -0
- package/package.json +6 -4
- package/README.md +0 -114
package/dist/index.cjs
CHANGED
|
@@ -11,6 +11,7 @@ var winston = require('winston');
|
|
|
11
11
|
require('winston-daily-rotate-file');
|
|
12
12
|
var klona = require('klona');
|
|
13
13
|
var traverse = require('traverse');
|
|
14
|
+
var nanoid = require('nanoid');
|
|
14
15
|
|
|
15
16
|
async function signPayload({ payload, secret, expirationTime, }) {
|
|
16
17
|
return jwt.sign(payload, secret, { expiresIn: expirationTime });
|
|
@@ -870,7 +871,7 @@ const promptGroupSchema = new mongoose.Schema({
|
|
|
870
871
|
validator: function (v) {
|
|
871
872
|
return v === undefined || v === null || v === '' || /^[a-z0-9-]+$/.test(v);
|
|
872
873
|
},
|
|
873
|
-
message: (props) => `${props.value} is not a valid command. Only lowercase alphanumeric characters and hyphens are allowed
|
|
874
|
+
message: (props) => { var _a; return `${(_a = props === null || props === void 0 ? void 0 : props.value) !== null && _a !== void 0 ? _a : 'Value'} is not a valid command. Only lowercase alphanumeric characters and hyphens are allowed.`; },
|
|
874
875
|
},
|
|
875
876
|
maxlength: [
|
|
876
877
|
librechatDataProvider.Constants.COMMANDS_MAX_LENGTH,
|
|
@@ -892,6 +893,13 @@ const rolePermissionsSchema = new mongoose.Schema({
|
|
|
892
893
|
[librechatDataProvider.Permissions.USE]: { type: Boolean, default: true },
|
|
893
894
|
[librechatDataProvider.Permissions.CREATE]: { type: Boolean, default: true },
|
|
894
895
|
},
|
|
896
|
+
[librechatDataProvider.PermissionTypes.MEMORIES]: {
|
|
897
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean, default: true },
|
|
898
|
+
[librechatDataProvider.Permissions.CREATE]: { type: Boolean, default: true },
|
|
899
|
+
[librechatDataProvider.Permissions.UPDATE]: { type: Boolean, default: true },
|
|
900
|
+
[librechatDataProvider.Permissions.READ]: { type: Boolean, default: true },
|
|
901
|
+
[librechatDataProvider.Permissions.OPT_OUT]: { type: Boolean, default: true },
|
|
902
|
+
},
|
|
895
903
|
[librechatDataProvider.PermissionTypes.AGENTS]: {
|
|
896
904
|
[librechatDataProvider.Permissions.SHARED_GLOBAL]: { type: Boolean, default: false },
|
|
897
905
|
[librechatDataProvider.Permissions.USE]: { type: Boolean, default: true },
|
|
@@ -921,6 +929,12 @@ const roleSchema = new mongoose.Schema({
|
|
|
921
929
|
[librechatDataProvider.Permissions.USE]: true,
|
|
922
930
|
[librechatDataProvider.Permissions.CREATE]: true,
|
|
923
931
|
},
|
|
932
|
+
[librechatDataProvider.PermissionTypes.MEMORIES]: {
|
|
933
|
+
[librechatDataProvider.Permissions.USE]: true,
|
|
934
|
+
[librechatDataProvider.Permissions.CREATE]: true,
|
|
935
|
+
[librechatDataProvider.Permissions.UPDATE]: true,
|
|
936
|
+
[librechatDataProvider.Permissions.READ]: true,
|
|
937
|
+
},
|
|
924
938
|
[librechatDataProvider.PermissionTypes.AGENTS]: {
|
|
925
939
|
[librechatDataProvider.Permissions.SHARED_GLOBAL]: false,
|
|
926
940
|
[librechatDataProvider.Permissions.USE]: true,
|
|
@@ -1198,8 +1212,46 @@ const userSchema = new mongoose.Schema({
|
|
|
1198
1212
|
type: Boolean,
|
|
1199
1213
|
default: false,
|
|
1200
1214
|
},
|
|
1215
|
+
personalization: {
|
|
1216
|
+
type: {
|
|
1217
|
+
memories: {
|
|
1218
|
+
type: Boolean,
|
|
1219
|
+
default: true,
|
|
1220
|
+
},
|
|
1221
|
+
},
|
|
1222
|
+
default: {},
|
|
1223
|
+
},
|
|
1201
1224
|
}, { timestamps: true });
|
|
1202
1225
|
|
|
1226
|
+
const MemoryEntrySchema = new mongoose.Schema({
|
|
1227
|
+
userId: {
|
|
1228
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1229
|
+
ref: 'User',
|
|
1230
|
+
index: true,
|
|
1231
|
+
required: true,
|
|
1232
|
+
},
|
|
1233
|
+
key: {
|
|
1234
|
+
type: String,
|
|
1235
|
+
required: true,
|
|
1236
|
+
validate: {
|
|
1237
|
+
validator: (v) => /^[a-z_]+$/.test(v),
|
|
1238
|
+
message: 'Key must only contain lowercase letters and underscores',
|
|
1239
|
+
},
|
|
1240
|
+
},
|
|
1241
|
+
value: {
|
|
1242
|
+
type: String,
|
|
1243
|
+
required: true,
|
|
1244
|
+
},
|
|
1245
|
+
tokenCount: {
|
|
1246
|
+
type: Number,
|
|
1247
|
+
default: 0,
|
|
1248
|
+
},
|
|
1249
|
+
updated_at: {
|
|
1250
|
+
type: Date,
|
|
1251
|
+
default: Date.now,
|
|
1252
|
+
},
|
|
1253
|
+
});
|
|
1254
|
+
|
|
1203
1255
|
/**
|
|
1204
1256
|
* Creates or returns the User model using the provided mongoose instance and schema
|
|
1205
1257
|
*/
|
|
@@ -1228,7 +1280,7 @@ function createBalanceModel(mongoose) {
|
|
|
1228
1280
|
return mongoose.models.Balance || mongoose.model('Balance', balanceSchema);
|
|
1229
1281
|
}
|
|
1230
1282
|
|
|
1231
|
-
const logDir$1 = path.join(__dirname, '..', 'logs');
|
|
1283
|
+
const logDir$1 = path.join(__dirname, '..', '..', '..', 'api', 'logs');
|
|
1232
1284
|
const { NODE_ENV: NODE_ENV$1, DEBUG_LOGGING: DEBUG_LOGGING$1 = 'false' } = process.env;
|
|
1233
1285
|
const useDebugLogging$1 = (typeof DEBUG_LOGGING$1 === 'string' && DEBUG_LOGGING$1.toLowerCase() === 'true') ||
|
|
1234
1286
|
DEBUG_LOGGING$1 === 'true';
|
|
@@ -1415,7 +1467,7 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, }) => {
|
|
|
1415
1467
|
}
|
|
1416
1468
|
}
|
|
1417
1469
|
catch (error) {
|
|
1418
|
-
logger$1.error('[syncWithMeili] Error adding document to Meili', error);
|
|
1470
|
+
logger$1.error('[syncWithMeili] Error adding document to Meili:', error);
|
|
1419
1471
|
}
|
|
1420
1472
|
}
|
|
1421
1473
|
/**
|
|
@@ -1473,30 +1525,52 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, }) => {
|
|
|
1473
1525
|
/**
|
|
1474
1526
|
* Adds the current document to the MeiliSearch index
|
|
1475
1527
|
*/
|
|
1476
|
-
async addObjectToMeili() {
|
|
1528
|
+
async addObjectToMeili(next) {
|
|
1477
1529
|
const object = this.preprocessObjectForIndex();
|
|
1478
1530
|
try {
|
|
1479
1531
|
await index.addDocuments([object]);
|
|
1480
1532
|
}
|
|
1481
1533
|
catch (error) {
|
|
1482
|
-
logger$1.error('[addObjectToMeili] Error adding document to Meili', error);
|
|
1534
|
+
logger$1.error('[addObjectToMeili] Error adding document to Meili:', error);
|
|
1535
|
+
return next();
|
|
1483
1536
|
}
|
|
1484
|
-
|
|
1537
|
+
try {
|
|
1538
|
+
await this.collection.updateMany({ _id: this._id }, { $set: { _meiliIndex: true } });
|
|
1539
|
+
}
|
|
1540
|
+
catch (error) {
|
|
1541
|
+
logger$1.error('[addObjectToMeili] Error updating _meiliIndex field:', error);
|
|
1542
|
+
return next();
|
|
1543
|
+
}
|
|
1544
|
+
next();
|
|
1485
1545
|
}
|
|
1486
1546
|
/**
|
|
1487
1547
|
* Updates the current document in the MeiliSearch index
|
|
1488
1548
|
*/
|
|
1489
|
-
async updateObjectToMeili() {
|
|
1490
|
-
|
|
1491
|
-
|
|
1549
|
+
async updateObjectToMeili(next) {
|
|
1550
|
+
try {
|
|
1551
|
+
const object = _.omitBy(_.pick(this.toJSON(), attributesToIndex), (v, k) => k.startsWith('$'));
|
|
1552
|
+
await index.updateDocuments([object]);
|
|
1553
|
+
next();
|
|
1554
|
+
}
|
|
1555
|
+
catch (error) {
|
|
1556
|
+
logger$1.error('[updateObjectToMeili] Error updating document in Meili:', error);
|
|
1557
|
+
return next();
|
|
1558
|
+
}
|
|
1492
1559
|
}
|
|
1493
1560
|
/**
|
|
1494
1561
|
* Deletes the current document from the MeiliSearch index.
|
|
1495
1562
|
*
|
|
1496
1563
|
* @returns {Promise<void>}
|
|
1497
1564
|
*/
|
|
1498
|
-
async deleteObjectFromMeili() {
|
|
1499
|
-
|
|
1565
|
+
async deleteObjectFromMeili(next) {
|
|
1566
|
+
try {
|
|
1567
|
+
await index.deleteDocument(this._id);
|
|
1568
|
+
next();
|
|
1569
|
+
}
|
|
1570
|
+
catch (error) {
|
|
1571
|
+
logger$1.error('[deleteObjectFromMeili] Error deleting document from Meili:', error);
|
|
1572
|
+
return next();
|
|
1573
|
+
}
|
|
1500
1574
|
}
|
|
1501
1575
|
/**
|
|
1502
1576
|
* Post-save hook to synchronize the document with MeiliSearch.
|
|
@@ -1504,12 +1578,12 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, }) => {
|
|
|
1504
1578
|
* If the document is already indexed (i.e. `_meiliIndex` is true), it updates it;
|
|
1505
1579
|
* otherwise, it adds the document to the index.
|
|
1506
1580
|
*/
|
|
1507
|
-
postSaveHook() {
|
|
1581
|
+
postSaveHook(next) {
|
|
1508
1582
|
if (this._meiliIndex) {
|
|
1509
|
-
this.updateObjectToMeili();
|
|
1583
|
+
this.updateObjectToMeili(next);
|
|
1510
1584
|
}
|
|
1511
1585
|
else {
|
|
1512
|
-
this.addObjectToMeili();
|
|
1586
|
+
this.addObjectToMeili(next);
|
|
1513
1587
|
}
|
|
1514
1588
|
}
|
|
1515
1589
|
/**
|
|
@@ -1518,9 +1592,12 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, }) => {
|
|
|
1518
1592
|
* This hook is triggered after a document update, ensuring that changes are
|
|
1519
1593
|
* propagated to the MeiliSearch index if the document is indexed.
|
|
1520
1594
|
*/
|
|
1521
|
-
postUpdateHook() {
|
|
1595
|
+
postUpdateHook(next) {
|
|
1522
1596
|
if (this._meiliIndex) {
|
|
1523
|
-
this.updateObjectToMeili();
|
|
1597
|
+
this.updateObjectToMeili(next);
|
|
1598
|
+
}
|
|
1599
|
+
else {
|
|
1600
|
+
next();
|
|
1524
1601
|
}
|
|
1525
1602
|
}
|
|
1526
1603
|
/**
|
|
@@ -1529,9 +1606,12 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, }) => {
|
|
|
1529
1606
|
* This hook is triggered after a document is removed, ensuring that the document
|
|
1530
1607
|
* is also removed from the MeiliSearch index if it was previously indexed.
|
|
1531
1608
|
*/
|
|
1532
|
-
postRemoveHook() {
|
|
1609
|
+
postRemoveHook(next) {
|
|
1533
1610
|
if (this._meiliIndex) {
|
|
1534
|
-
this.deleteObjectFromMeili();
|
|
1611
|
+
this.deleteObjectFromMeili(next);
|
|
1612
|
+
}
|
|
1613
|
+
else {
|
|
1614
|
+
next();
|
|
1535
1615
|
}
|
|
1536
1616
|
}
|
|
1537
1617
|
}
|
|
@@ -1579,17 +1659,17 @@ function mongoMeili(schema, options) {
|
|
|
1579
1659
|
];
|
|
1580
1660
|
schema.loadClass(createMeiliMongooseModel({ index, attributesToIndex }));
|
|
1581
1661
|
// Register Mongoose hooks
|
|
1582
|
-
schema.post('save', function (doc) {
|
|
1662
|
+
schema.post('save', function (doc, next) {
|
|
1583
1663
|
var _a;
|
|
1584
|
-
(_a = doc.postSaveHook) === null || _a === void 0 ? void 0 : _a.call(doc);
|
|
1664
|
+
(_a = doc.postSaveHook) === null || _a === void 0 ? void 0 : _a.call(doc, next);
|
|
1585
1665
|
});
|
|
1586
|
-
schema.post('updateOne', function (doc) {
|
|
1666
|
+
schema.post('updateOne', function (doc, next) {
|
|
1587
1667
|
var _a;
|
|
1588
|
-
(_a = doc.postUpdateHook) === null || _a === void 0 ? void 0 : _a.call(doc);
|
|
1668
|
+
(_a = doc.postUpdateHook) === null || _a === void 0 ? void 0 : _a.call(doc, next);
|
|
1589
1669
|
});
|
|
1590
|
-
schema.post('deleteOne', function (doc) {
|
|
1670
|
+
schema.post('deleteOne', function (doc, next) {
|
|
1591
1671
|
var _a;
|
|
1592
|
-
(_a = doc.postRemoveHook) === null || _a === void 0 ? void 0 : _a.call(doc);
|
|
1672
|
+
(_a = doc.postRemoveHook) === null || _a === void 0 ? void 0 : _a.call(doc, next);
|
|
1593
1673
|
});
|
|
1594
1674
|
// Pre-deleteMany hook: remove corresponding documents from MeiliSearch when multiple documents are deleted.
|
|
1595
1675
|
schema.pre('deleteMany', async function (next) {
|
|
@@ -1626,13 +1706,13 @@ function mongoMeili(schema, options) {
|
|
|
1626
1706
|
}
|
|
1627
1707
|
});
|
|
1628
1708
|
// Post-findOneAndUpdate hook
|
|
1629
|
-
schema.post('findOneAndUpdate', async function (doc) {
|
|
1709
|
+
schema.post('findOneAndUpdate', async function (doc, next) {
|
|
1630
1710
|
var _a;
|
|
1631
1711
|
if (!meiliEnabled) {
|
|
1632
|
-
return;
|
|
1712
|
+
return next();
|
|
1633
1713
|
}
|
|
1634
1714
|
if (doc.unfinished) {
|
|
1635
|
-
return;
|
|
1715
|
+
return next();
|
|
1636
1716
|
}
|
|
1637
1717
|
let meiliDoc;
|
|
1638
1718
|
if (doc.messages) {
|
|
@@ -1645,9 +1725,9 @@ function mongoMeili(schema, options) {
|
|
|
1645
1725
|
}
|
|
1646
1726
|
}
|
|
1647
1727
|
if (meiliDoc && meiliDoc.title === doc.title) {
|
|
1648
|
-
return;
|
|
1728
|
+
return next();
|
|
1649
1729
|
}
|
|
1650
|
-
(_a = doc.postSaveHook) === null || _a === void 0 ? void 0 : _a.call(doc);
|
|
1730
|
+
(_a = doc.postSaveHook) === null || _a === void 0 ? void 0 : _a.call(doc, next);
|
|
1651
1731
|
});
|
|
1652
1732
|
}
|
|
1653
1733
|
|
|
@@ -1798,6 +1878,10 @@ function createToolCallModel(mongoose) {
|
|
|
1798
1878
|
return mongoose.models.ToolCall || mongoose.model('ToolCall', toolCallSchema);
|
|
1799
1879
|
}
|
|
1800
1880
|
|
|
1881
|
+
function createMemoryModel(mongoose) {
|
|
1882
|
+
return mongoose.models.MemoryEntry || mongoose.model('MemoryEntry', MemoryEntrySchema);
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1801
1885
|
/**
|
|
1802
1886
|
* Creates all database models for all collections
|
|
1803
1887
|
*/
|
|
@@ -1825,6 +1909,7 @@ function createModels(mongoose) {
|
|
|
1825
1909
|
ConversationTag: createConversationTagModel(mongoose),
|
|
1826
1910
|
SharedLink: createSharedLinkModel(mongoose),
|
|
1827
1911
|
ToolCall: createToolCallModel(mongoose),
|
|
1912
|
+
MemoryEntry: createMemoryModel(mongoose),
|
|
1828
1913
|
};
|
|
1829
1914
|
}
|
|
1830
1915
|
|
|
@@ -1960,6 +2045,28 @@ function createUserMethods(mongoose) {
|
|
|
1960
2045
|
expirationTime: expires / 1000,
|
|
1961
2046
|
});
|
|
1962
2047
|
}
|
|
2048
|
+
/**
|
|
2049
|
+
* Update a user's personalization memories setting.
|
|
2050
|
+
* Handles the edge case where the personalization object doesn't exist.
|
|
2051
|
+
*/
|
|
2052
|
+
async function toggleUserMemories(userId, memoriesEnabled) {
|
|
2053
|
+
const User = mongoose.models.User;
|
|
2054
|
+
// First, ensure the personalization object exists
|
|
2055
|
+
const user = await User.findById(userId);
|
|
2056
|
+
if (!user) {
|
|
2057
|
+
return null;
|
|
2058
|
+
}
|
|
2059
|
+
// Use $set to update the nested field, which will create the personalization object if it doesn't exist
|
|
2060
|
+
const updateOperation = {
|
|
2061
|
+
$set: {
|
|
2062
|
+
'personalization.memories': memoriesEnabled,
|
|
2063
|
+
},
|
|
2064
|
+
};
|
|
2065
|
+
return (await User.findByIdAndUpdate(userId, updateOperation, {
|
|
2066
|
+
new: true,
|
|
2067
|
+
runValidators: true,
|
|
2068
|
+
}).lean());
|
|
2069
|
+
}
|
|
1963
2070
|
// Return all methods
|
|
1964
2071
|
return {
|
|
1965
2072
|
findUser,
|
|
@@ -1969,6 +2076,7 @@ function createUserMethods(mongoose) {
|
|
|
1969
2076
|
getUserById,
|
|
1970
2077
|
deleteUserById,
|
|
1971
2078
|
generateToken,
|
|
2079
|
+
toggleUserMemories,
|
|
1972
2080
|
};
|
|
1973
2081
|
}
|
|
1974
2082
|
|
|
@@ -2173,14 +2281,11 @@ const jsonTruncateFormat = winston.format((info) => {
|
|
|
2173
2281
|
return truncateObject(info);
|
|
2174
2282
|
});
|
|
2175
2283
|
|
|
2176
|
-
|
|
2177
|
-
const logDir = path.join(__dirname, '..', 'logs');
|
|
2178
|
-
// Type-safe environment variables
|
|
2284
|
+
const logDir = path.join(__dirname, '..', '..', '..', 'api', 'logs');
|
|
2179
2285
|
const { NODE_ENV, DEBUG_LOGGING, CONSOLE_JSON, DEBUG_CONSOLE } = process.env;
|
|
2180
2286
|
const useConsoleJson = typeof CONSOLE_JSON === 'string' && CONSOLE_JSON.toLowerCase() === 'true';
|
|
2181
2287
|
const useDebugConsole = typeof DEBUG_CONSOLE === 'string' && DEBUG_CONSOLE.toLowerCase() === 'true';
|
|
2182
2288
|
const useDebugLogging = typeof DEBUG_LOGGING === 'string' && DEBUG_LOGGING.toLowerCase() === 'true';
|
|
2183
|
-
// Define custom log levels
|
|
2184
2289
|
const levels = {
|
|
2185
2290
|
error: 0,
|
|
2186
2291
|
warn: 1,
|
|
@@ -2260,7 +2365,7 @@ const logger = winston.createLogger({
|
|
|
2260
2365
|
transports,
|
|
2261
2366
|
});
|
|
2262
2367
|
|
|
2263
|
-
var _a
|
|
2368
|
+
var _a;
|
|
2264
2369
|
class SessionError extends Error {
|
|
2265
2370
|
constructor(message, code = 'SESSION_ERROR') {
|
|
2266
2371
|
super(message);
|
|
@@ -2269,7 +2374,9 @@ class SessionError extends Error {
|
|
|
2269
2374
|
}
|
|
2270
2375
|
}
|
|
2271
2376
|
const { REFRESH_TOKEN_EXPIRY } = (_a = process.env) !== null && _a !== void 0 ? _a : {};
|
|
2272
|
-
const expires =
|
|
2377
|
+
const expires = REFRESH_TOKEN_EXPIRY
|
|
2378
|
+
? eval(REFRESH_TOKEN_EXPIRY)
|
|
2379
|
+
: 1000 * 60 * 60 * 24 * 7; // 7 days default
|
|
2273
2380
|
// Factory function that takes mongoose instance and returns the methods
|
|
2274
2381
|
function createSessionMethods(mongoose) {
|
|
2275
2382
|
const Session = mongoose.models.Session;
|
|
@@ -2599,6 +2706,584 @@ function createRoleMethods(mongoose) {
|
|
|
2599
2706
|
};
|
|
2600
2707
|
}
|
|
2601
2708
|
|
|
2709
|
+
/**
|
|
2710
|
+
* Formats a date in YYYY-MM-DD format
|
|
2711
|
+
*/
|
|
2712
|
+
const formatDate = (date) => {
|
|
2713
|
+
return date.toISOString().split('T')[0];
|
|
2714
|
+
};
|
|
2715
|
+
// Factory function that takes mongoose instance and returns the methods
|
|
2716
|
+
function createMemoryMethods(mongoose) {
|
|
2717
|
+
const MemoryEntry = mongoose.models.MemoryEntry;
|
|
2718
|
+
/**
|
|
2719
|
+
* Creates a new memory entry for a user
|
|
2720
|
+
* Throws an error if a memory with the same key already exists
|
|
2721
|
+
*/
|
|
2722
|
+
async function createMemory({ userId, key, value, tokenCount = 0, }) {
|
|
2723
|
+
try {
|
|
2724
|
+
if ((key === null || key === void 0 ? void 0 : key.toLowerCase()) === 'nothing') {
|
|
2725
|
+
return { ok: false };
|
|
2726
|
+
}
|
|
2727
|
+
const existingMemory = await MemoryEntry.findOne({ userId, key });
|
|
2728
|
+
if (existingMemory) {
|
|
2729
|
+
throw new Error('Memory with this key already exists');
|
|
2730
|
+
}
|
|
2731
|
+
await MemoryEntry.create({
|
|
2732
|
+
userId,
|
|
2733
|
+
key,
|
|
2734
|
+
value,
|
|
2735
|
+
tokenCount,
|
|
2736
|
+
updated_at: new Date(),
|
|
2737
|
+
});
|
|
2738
|
+
return { ok: true };
|
|
2739
|
+
}
|
|
2740
|
+
catch (error) {
|
|
2741
|
+
throw new Error(`Failed to create memory: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
/**
|
|
2745
|
+
* Sets or updates a memory entry for a user
|
|
2746
|
+
*/
|
|
2747
|
+
async function setMemory({ userId, key, value, tokenCount = 0, }) {
|
|
2748
|
+
try {
|
|
2749
|
+
if ((key === null || key === void 0 ? void 0 : key.toLowerCase()) === 'nothing') {
|
|
2750
|
+
return { ok: false };
|
|
2751
|
+
}
|
|
2752
|
+
await MemoryEntry.findOneAndUpdate({ userId, key }, {
|
|
2753
|
+
value,
|
|
2754
|
+
tokenCount,
|
|
2755
|
+
updated_at: new Date(),
|
|
2756
|
+
}, {
|
|
2757
|
+
upsert: true,
|
|
2758
|
+
new: true,
|
|
2759
|
+
});
|
|
2760
|
+
return { ok: true };
|
|
2761
|
+
}
|
|
2762
|
+
catch (error) {
|
|
2763
|
+
throw new Error(`Failed to set memory: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
/**
|
|
2767
|
+
* Deletes a specific memory entry for a user
|
|
2768
|
+
*/
|
|
2769
|
+
async function deleteMemory({ userId, key }) {
|
|
2770
|
+
try {
|
|
2771
|
+
const result = await MemoryEntry.findOneAndDelete({ userId, key });
|
|
2772
|
+
return { ok: !!result };
|
|
2773
|
+
}
|
|
2774
|
+
catch (error) {
|
|
2775
|
+
throw new Error(`Failed to delete memory: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
/**
|
|
2779
|
+
* Gets all memory entries for a user
|
|
2780
|
+
*/
|
|
2781
|
+
async function getAllUserMemories(userId) {
|
|
2782
|
+
try {
|
|
2783
|
+
return (await MemoryEntry.find({ userId }).lean());
|
|
2784
|
+
}
|
|
2785
|
+
catch (error) {
|
|
2786
|
+
throw new Error(`Failed to get all memories: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
/**
|
|
2790
|
+
* Gets and formats all memories for a user in two different formats
|
|
2791
|
+
*/
|
|
2792
|
+
async function getFormattedMemories({ userId, }) {
|
|
2793
|
+
try {
|
|
2794
|
+
const memories = await getAllUserMemories(userId);
|
|
2795
|
+
if (!memories || memories.length === 0) {
|
|
2796
|
+
return { withKeys: '', withoutKeys: '', totalTokens: 0 };
|
|
2797
|
+
}
|
|
2798
|
+
const sortedMemories = memories.sort((a, b) => new Date(a.updated_at).getTime() - new Date(b.updated_at).getTime());
|
|
2799
|
+
const totalTokens = sortedMemories.reduce((sum, memory) => {
|
|
2800
|
+
return sum + (memory.tokenCount || 0);
|
|
2801
|
+
}, 0);
|
|
2802
|
+
const withKeys = sortedMemories
|
|
2803
|
+
.map((memory, index) => {
|
|
2804
|
+
const date = formatDate(new Date(memory.updated_at));
|
|
2805
|
+
const tokenInfo = memory.tokenCount ? ` [${memory.tokenCount} tokens]` : '';
|
|
2806
|
+
return `${index + 1}. [${date}]. ["key": "${memory.key}"]${tokenInfo}. ["value": "${memory.value}"]`;
|
|
2807
|
+
})
|
|
2808
|
+
.join('\n\n');
|
|
2809
|
+
const withoutKeys = sortedMemories
|
|
2810
|
+
.map((memory, index) => {
|
|
2811
|
+
const date = formatDate(new Date(memory.updated_at));
|
|
2812
|
+
return `${index + 1}. [${date}]. ${memory.value}`;
|
|
2813
|
+
})
|
|
2814
|
+
.join('\n\n');
|
|
2815
|
+
return { withKeys, withoutKeys, totalTokens };
|
|
2816
|
+
}
|
|
2817
|
+
catch (error) {
|
|
2818
|
+
logger.error('Failed to get formatted memories:', error);
|
|
2819
|
+
return { withKeys: '', withoutKeys: '', totalTokens: 0 };
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
return {
|
|
2823
|
+
setMemory,
|
|
2824
|
+
createMemory,
|
|
2825
|
+
deleteMemory,
|
|
2826
|
+
getAllUserMemories,
|
|
2827
|
+
getFormattedMemories,
|
|
2828
|
+
};
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
class ShareServiceError extends Error {
|
|
2832
|
+
constructor(message, code) {
|
|
2833
|
+
super(message);
|
|
2834
|
+
this.name = 'ShareServiceError';
|
|
2835
|
+
this.code = code;
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
function memoizedAnonymizeId(prefix) {
|
|
2839
|
+
const memo = new Map();
|
|
2840
|
+
return (id) => {
|
|
2841
|
+
if (!memo.has(id)) {
|
|
2842
|
+
memo.set(id, `${prefix}_${nanoid.nanoid()}`);
|
|
2843
|
+
}
|
|
2844
|
+
return memo.get(id);
|
|
2845
|
+
};
|
|
2846
|
+
}
|
|
2847
|
+
const anonymizeConvoId = memoizedAnonymizeId('convo');
|
|
2848
|
+
const anonymizeAssistantId = memoizedAnonymizeId('a');
|
|
2849
|
+
const anonymizeMessageId = (id) => id === librechatDataProvider.Constants.NO_PARENT ? id : memoizedAnonymizeId('msg')(id);
|
|
2850
|
+
function anonymizeConvo(conversation) {
|
|
2851
|
+
if (!conversation) {
|
|
2852
|
+
return null;
|
|
2853
|
+
}
|
|
2854
|
+
const newConvo = { ...conversation };
|
|
2855
|
+
if (newConvo.assistant_id) {
|
|
2856
|
+
newConvo.assistant_id = anonymizeAssistantId(newConvo.assistant_id);
|
|
2857
|
+
}
|
|
2858
|
+
return newConvo;
|
|
2859
|
+
}
|
|
2860
|
+
function anonymizeMessages(messages, newConvoId) {
|
|
2861
|
+
if (!Array.isArray(messages)) {
|
|
2862
|
+
return [];
|
|
2863
|
+
}
|
|
2864
|
+
const idMap = new Map();
|
|
2865
|
+
return messages.map((message) => {
|
|
2866
|
+
var _a, _b;
|
|
2867
|
+
const newMessageId = anonymizeMessageId(message.messageId);
|
|
2868
|
+
idMap.set(message.messageId, newMessageId);
|
|
2869
|
+
const anonymizedAttachments = (_a = message.attachments) === null || _a === void 0 ? void 0 : _a.map((attachment) => {
|
|
2870
|
+
return {
|
|
2871
|
+
...attachment,
|
|
2872
|
+
messageId: newMessageId,
|
|
2873
|
+
conversationId: newConvoId,
|
|
2874
|
+
};
|
|
2875
|
+
});
|
|
2876
|
+
return {
|
|
2877
|
+
...message,
|
|
2878
|
+
messageId: newMessageId,
|
|
2879
|
+
parentMessageId: idMap.get(message.parentMessageId || '') ||
|
|
2880
|
+
anonymizeMessageId(message.parentMessageId || ''),
|
|
2881
|
+
conversationId: newConvoId,
|
|
2882
|
+
model: ((_b = message.model) === null || _b === void 0 ? void 0 : _b.startsWith('asst_'))
|
|
2883
|
+
? anonymizeAssistantId(message.model)
|
|
2884
|
+
: message.model,
|
|
2885
|
+
attachments: anonymizedAttachments,
|
|
2886
|
+
};
|
|
2887
|
+
});
|
|
2888
|
+
}
|
|
2889
|
+
/** Factory function that takes mongoose instance and returns the methods */
|
|
2890
|
+
function createShareMethods(mongoose) {
|
|
2891
|
+
/**
|
|
2892
|
+
* Get shared messages for a public share link
|
|
2893
|
+
*/
|
|
2894
|
+
async function getSharedMessages(shareId) {
|
|
2895
|
+
try {
|
|
2896
|
+
const SharedLink = mongoose.models.SharedLink;
|
|
2897
|
+
const share = (await SharedLink.findOne({ shareId, isPublic: true })
|
|
2898
|
+
.populate({
|
|
2899
|
+
path: 'messages',
|
|
2900
|
+
select: '-_id -__v -user',
|
|
2901
|
+
})
|
|
2902
|
+
.select('-_id -__v -user')
|
|
2903
|
+
.lean());
|
|
2904
|
+
if (!(share === null || share === void 0 ? void 0 : share.conversationId) || !share.isPublic) {
|
|
2905
|
+
return null;
|
|
2906
|
+
}
|
|
2907
|
+
const newConvoId = anonymizeConvoId(share.conversationId);
|
|
2908
|
+
const result = {
|
|
2909
|
+
shareId: share.shareId || shareId,
|
|
2910
|
+
title: share.title,
|
|
2911
|
+
isPublic: share.isPublic,
|
|
2912
|
+
createdAt: share.createdAt,
|
|
2913
|
+
updatedAt: share.updatedAt,
|
|
2914
|
+
conversationId: newConvoId,
|
|
2915
|
+
messages: anonymizeMessages(share.messages, newConvoId),
|
|
2916
|
+
};
|
|
2917
|
+
return result;
|
|
2918
|
+
}
|
|
2919
|
+
catch (error) {
|
|
2920
|
+
logger.error('[getSharedMessages] Error getting share link', {
|
|
2921
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
2922
|
+
shareId,
|
|
2923
|
+
});
|
|
2924
|
+
throw new ShareServiceError('Error getting share link', 'SHARE_FETCH_ERROR');
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
/**
|
|
2928
|
+
* Get shared links for a specific user with pagination and search
|
|
2929
|
+
*/
|
|
2930
|
+
async function getSharedLinks(user, pageParam, pageSize = 10, isPublic = true, sortBy = 'createdAt', sortDirection = 'desc', search) {
|
|
2931
|
+
var _a;
|
|
2932
|
+
try {
|
|
2933
|
+
const SharedLink = mongoose.models.SharedLink;
|
|
2934
|
+
const Conversation = mongoose.models.Conversation;
|
|
2935
|
+
const query = { user, isPublic };
|
|
2936
|
+
if (pageParam) {
|
|
2937
|
+
if (sortDirection === 'desc') {
|
|
2938
|
+
query[sortBy] = { $lt: pageParam };
|
|
2939
|
+
}
|
|
2940
|
+
else {
|
|
2941
|
+
query[sortBy] = { $gt: pageParam };
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
if (search && search.trim()) {
|
|
2945
|
+
try {
|
|
2946
|
+
const searchResults = await Conversation.meiliSearch(search);
|
|
2947
|
+
if (!((_a = searchResults === null || searchResults === void 0 ? void 0 : searchResults.hits) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
2948
|
+
return {
|
|
2949
|
+
links: [],
|
|
2950
|
+
nextCursor: undefined,
|
|
2951
|
+
hasNextPage: false,
|
|
2952
|
+
};
|
|
2953
|
+
}
|
|
2954
|
+
const conversationIds = searchResults.hits.map((hit) => hit.conversationId);
|
|
2955
|
+
query['conversationId'] = { $in: conversationIds };
|
|
2956
|
+
}
|
|
2957
|
+
catch (searchError) {
|
|
2958
|
+
logger.error('[getSharedLinks] Meilisearch error', {
|
|
2959
|
+
error: searchError instanceof Error ? searchError.message : 'Unknown error',
|
|
2960
|
+
user,
|
|
2961
|
+
});
|
|
2962
|
+
return {
|
|
2963
|
+
links: [],
|
|
2964
|
+
nextCursor: undefined,
|
|
2965
|
+
hasNextPage: false,
|
|
2966
|
+
};
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
const sort = {};
|
|
2970
|
+
sort[sortBy] = sortDirection === 'desc' ? -1 : 1;
|
|
2971
|
+
const sharedLinks = await SharedLink.find(query)
|
|
2972
|
+
.sort(sort)
|
|
2973
|
+
.limit(pageSize + 1)
|
|
2974
|
+
.select('-__v -user')
|
|
2975
|
+
.lean();
|
|
2976
|
+
const hasNextPage = sharedLinks.length > pageSize;
|
|
2977
|
+
const links = sharedLinks.slice(0, pageSize);
|
|
2978
|
+
const nextCursor = hasNextPage
|
|
2979
|
+
? links[links.length - 1][sortBy]
|
|
2980
|
+
: undefined;
|
|
2981
|
+
return {
|
|
2982
|
+
links: links.map((link) => ({
|
|
2983
|
+
shareId: link.shareId || '',
|
|
2984
|
+
title: (link === null || link === void 0 ? void 0 : link.title) || 'Untitled',
|
|
2985
|
+
isPublic: link.isPublic,
|
|
2986
|
+
createdAt: link.createdAt || new Date(),
|
|
2987
|
+
conversationId: link.conversationId,
|
|
2988
|
+
})),
|
|
2989
|
+
nextCursor,
|
|
2990
|
+
hasNextPage,
|
|
2991
|
+
};
|
|
2992
|
+
}
|
|
2993
|
+
catch (error) {
|
|
2994
|
+
logger.error('[getSharedLinks] Error getting shares', {
|
|
2995
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
2996
|
+
user,
|
|
2997
|
+
});
|
|
2998
|
+
throw new ShareServiceError('Error getting shares', 'SHARES_FETCH_ERROR');
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
/**
|
|
3002
|
+
* Delete all shared links for a user
|
|
3003
|
+
*/
|
|
3004
|
+
async function deleteAllSharedLinks(user) {
|
|
3005
|
+
try {
|
|
3006
|
+
const SharedLink = mongoose.models.SharedLink;
|
|
3007
|
+
const result = await SharedLink.deleteMany({ user });
|
|
3008
|
+
return {
|
|
3009
|
+
message: 'All shared links deleted successfully',
|
|
3010
|
+
deletedCount: result.deletedCount,
|
|
3011
|
+
};
|
|
3012
|
+
}
|
|
3013
|
+
catch (error) {
|
|
3014
|
+
logger.error('[deleteAllSharedLinks] Error deleting shared links', {
|
|
3015
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
3016
|
+
user,
|
|
3017
|
+
});
|
|
3018
|
+
throw new ShareServiceError('Error deleting shared links', 'BULK_DELETE_ERROR');
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
/**
|
|
3022
|
+
* Create a new shared link for a conversation
|
|
3023
|
+
*/
|
|
3024
|
+
async function createSharedLink(user, conversationId) {
|
|
3025
|
+
if (!user || !conversationId) {
|
|
3026
|
+
throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
|
|
3027
|
+
}
|
|
3028
|
+
try {
|
|
3029
|
+
const Message = mongoose.models.Message;
|
|
3030
|
+
const SharedLink = mongoose.models.SharedLink;
|
|
3031
|
+
const Conversation = mongoose.models.Conversation;
|
|
3032
|
+
const [existingShare, conversationMessages] = await Promise.all([
|
|
3033
|
+
SharedLink.findOne({ conversationId, user, isPublic: true })
|
|
3034
|
+
.select('-_id -__v -user')
|
|
3035
|
+
.lean(),
|
|
3036
|
+
Message.find({ conversationId, user }).sort({ createdAt: 1 }).lean(),
|
|
3037
|
+
]);
|
|
3038
|
+
if (existingShare && existingShare.isPublic) {
|
|
3039
|
+
logger.error('[createSharedLink] Share already exists', {
|
|
3040
|
+
user,
|
|
3041
|
+
conversationId,
|
|
3042
|
+
});
|
|
3043
|
+
throw new ShareServiceError('Share already exists', 'SHARE_EXISTS');
|
|
3044
|
+
}
|
|
3045
|
+
else if (existingShare) {
|
|
3046
|
+
await SharedLink.deleteOne({ conversationId, user });
|
|
3047
|
+
}
|
|
3048
|
+
const conversation = (await Conversation.findOne({ conversationId, user }).lean());
|
|
3049
|
+
// Check if user owns the conversation
|
|
3050
|
+
if (!conversation) {
|
|
3051
|
+
throw new ShareServiceError('Conversation not found or access denied', 'CONVERSATION_NOT_FOUND');
|
|
3052
|
+
}
|
|
3053
|
+
// Check if there are any messages to share
|
|
3054
|
+
if (!conversationMessages || conversationMessages.length === 0) {
|
|
3055
|
+
throw new ShareServiceError('No messages to share', 'NO_MESSAGES');
|
|
3056
|
+
}
|
|
3057
|
+
const title = conversation.title || 'Untitled';
|
|
3058
|
+
const shareId = nanoid.nanoid();
|
|
3059
|
+
await SharedLink.create({
|
|
3060
|
+
shareId,
|
|
3061
|
+
conversationId,
|
|
3062
|
+
messages: conversationMessages,
|
|
3063
|
+
title,
|
|
3064
|
+
user,
|
|
3065
|
+
});
|
|
3066
|
+
return { shareId, conversationId };
|
|
3067
|
+
}
|
|
3068
|
+
catch (error) {
|
|
3069
|
+
if (error instanceof ShareServiceError) {
|
|
3070
|
+
throw error;
|
|
3071
|
+
}
|
|
3072
|
+
logger.error('[createSharedLink] Error creating shared link', {
|
|
3073
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
3074
|
+
user,
|
|
3075
|
+
conversationId,
|
|
3076
|
+
});
|
|
3077
|
+
throw new ShareServiceError('Error creating shared link', 'SHARE_CREATE_ERROR');
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
/**
|
|
3081
|
+
* Get a shared link for a conversation
|
|
3082
|
+
*/
|
|
3083
|
+
async function getSharedLink(user, conversationId) {
|
|
3084
|
+
if (!user || !conversationId) {
|
|
3085
|
+
throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
|
|
3086
|
+
}
|
|
3087
|
+
try {
|
|
3088
|
+
const SharedLink = mongoose.models.SharedLink;
|
|
3089
|
+
const share = (await SharedLink.findOne({ conversationId, user, isPublic: true })
|
|
3090
|
+
.select('shareId -_id')
|
|
3091
|
+
.lean());
|
|
3092
|
+
if (!share) {
|
|
3093
|
+
return { shareId: null, success: false };
|
|
3094
|
+
}
|
|
3095
|
+
return { shareId: share.shareId || null, success: true };
|
|
3096
|
+
}
|
|
3097
|
+
catch (error) {
|
|
3098
|
+
logger.error('[getSharedLink] Error getting shared link', {
|
|
3099
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
3100
|
+
user,
|
|
3101
|
+
conversationId,
|
|
3102
|
+
});
|
|
3103
|
+
throw new ShareServiceError('Error getting shared link', 'SHARE_FETCH_ERROR');
|
|
3104
|
+
}
|
|
3105
|
+
}
|
|
3106
|
+
/**
|
|
3107
|
+
* Update a shared link with new messages
|
|
3108
|
+
*/
|
|
3109
|
+
async function updateSharedLink(user, shareId) {
|
|
3110
|
+
if (!user || !shareId) {
|
|
3111
|
+
throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
|
|
3112
|
+
}
|
|
3113
|
+
try {
|
|
3114
|
+
const SharedLink = mongoose.models.SharedLink;
|
|
3115
|
+
const Message = mongoose.models.Message;
|
|
3116
|
+
const share = (await SharedLink.findOne({ shareId, user })
|
|
3117
|
+
.select('-_id -__v -user')
|
|
3118
|
+
.lean());
|
|
3119
|
+
if (!share) {
|
|
3120
|
+
throw new ShareServiceError('Share not found', 'SHARE_NOT_FOUND');
|
|
3121
|
+
}
|
|
3122
|
+
const updatedMessages = await Message.find({ conversationId: share.conversationId, user })
|
|
3123
|
+
.sort({ createdAt: 1 })
|
|
3124
|
+
.lean();
|
|
3125
|
+
const newShareId = nanoid.nanoid();
|
|
3126
|
+
const update = {
|
|
3127
|
+
messages: updatedMessages,
|
|
3128
|
+
user,
|
|
3129
|
+
shareId: newShareId,
|
|
3130
|
+
};
|
|
3131
|
+
const updatedShare = (await SharedLink.findOneAndUpdate({ shareId, user }, update, {
|
|
3132
|
+
new: true,
|
|
3133
|
+
upsert: false,
|
|
3134
|
+
runValidators: true,
|
|
3135
|
+
}).lean());
|
|
3136
|
+
if (!updatedShare) {
|
|
3137
|
+
throw new ShareServiceError('Share update failed', 'SHARE_UPDATE_ERROR');
|
|
3138
|
+
}
|
|
3139
|
+
anonymizeConvo(updatedShare);
|
|
3140
|
+
return { shareId: newShareId, conversationId: updatedShare.conversationId };
|
|
3141
|
+
}
|
|
3142
|
+
catch (error) {
|
|
3143
|
+
logger.error('[updateSharedLink] Error updating shared link', {
|
|
3144
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
3145
|
+
user,
|
|
3146
|
+
shareId,
|
|
3147
|
+
});
|
|
3148
|
+
throw new ShareServiceError(error instanceof ShareServiceError ? error.message : 'Error updating shared link', error instanceof ShareServiceError ? error.code : 'SHARE_UPDATE_ERROR');
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
/**
|
|
3152
|
+
* Delete a shared link
|
|
3153
|
+
*/
|
|
3154
|
+
async function deleteSharedLink(user, shareId) {
|
|
3155
|
+
if (!user || !shareId) {
|
|
3156
|
+
throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
|
|
3157
|
+
}
|
|
3158
|
+
try {
|
|
3159
|
+
const SharedLink = mongoose.models.SharedLink;
|
|
3160
|
+
const result = await SharedLink.findOneAndDelete({ shareId, user }).lean();
|
|
3161
|
+
if (!result) {
|
|
3162
|
+
return null;
|
|
3163
|
+
}
|
|
3164
|
+
return {
|
|
3165
|
+
success: true,
|
|
3166
|
+
shareId,
|
|
3167
|
+
message: 'Share deleted successfully',
|
|
3168
|
+
};
|
|
3169
|
+
}
|
|
3170
|
+
catch (error) {
|
|
3171
|
+
logger.error('[deleteSharedLink] Error deleting shared link', {
|
|
3172
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
3173
|
+
user,
|
|
3174
|
+
shareId,
|
|
3175
|
+
});
|
|
3176
|
+
throw new ShareServiceError('Error deleting shared link', 'SHARE_DELETE_ERROR');
|
|
3177
|
+
}
|
|
3178
|
+
}
|
|
3179
|
+
// Return all methods
|
|
3180
|
+
return {
|
|
3181
|
+
getSharedLink,
|
|
3182
|
+
getSharedLinks,
|
|
3183
|
+
createSharedLink,
|
|
3184
|
+
updateSharedLink,
|
|
3185
|
+
deleteSharedLink,
|
|
3186
|
+
getSharedMessages,
|
|
3187
|
+
deleteAllSharedLinks,
|
|
3188
|
+
};
|
|
3189
|
+
}
|
|
3190
|
+
|
|
3191
|
+
// Factory function that takes mongoose instance and returns the methods
|
|
3192
|
+
function createPluginAuthMethods(mongoose) {
|
|
3193
|
+
const PluginAuth = mongoose.models.PluginAuth;
|
|
3194
|
+
/**
|
|
3195
|
+
* Finds a single plugin auth entry by userId and authField
|
|
3196
|
+
*/
|
|
3197
|
+
async function findOnePluginAuth({ userId, authField, }) {
|
|
3198
|
+
try {
|
|
3199
|
+
return await PluginAuth.findOne({ userId, authField }).lean();
|
|
3200
|
+
}
|
|
3201
|
+
catch (error) {
|
|
3202
|
+
throw new Error(`Failed to find plugin auth: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
/**
|
|
3206
|
+
* Finds multiple plugin auth entries by userId and pluginKeys
|
|
3207
|
+
*/
|
|
3208
|
+
async function findPluginAuthsByKeys({ userId, pluginKeys, }) {
|
|
3209
|
+
try {
|
|
3210
|
+
if (!pluginKeys || pluginKeys.length === 0) {
|
|
3211
|
+
return [];
|
|
3212
|
+
}
|
|
3213
|
+
return await PluginAuth.find({
|
|
3214
|
+
userId,
|
|
3215
|
+
pluginKey: { $in: pluginKeys },
|
|
3216
|
+
}).lean();
|
|
3217
|
+
}
|
|
3218
|
+
catch (error) {
|
|
3219
|
+
throw new Error(`Failed to find plugin auths: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
3220
|
+
}
|
|
3221
|
+
}
|
|
3222
|
+
/**
|
|
3223
|
+
* Updates or creates a plugin auth entry
|
|
3224
|
+
*/
|
|
3225
|
+
async function updatePluginAuth({ userId, authField, pluginKey, value, }) {
|
|
3226
|
+
try {
|
|
3227
|
+
const existingAuth = await PluginAuth.findOne({ userId, pluginKey, authField }).lean();
|
|
3228
|
+
if (existingAuth) {
|
|
3229
|
+
return await PluginAuth.findOneAndUpdate({ userId, pluginKey, authField }, { $set: { value } }, { new: true, upsert: true }).lean();
|
|
3230
|
+
}
|
|
3231
|
+
else {
|
|
3232
|
+
const newPluginAuth = await new PluginAuth({
|
|
3233
|
+
userId,
|
|
3234
|
+
authField,
|
|
3235
|
+
value,
|
|
3236
|
+
pluginKey,
|
|
3237
|
+
});
|
|
3238
|
+
await newPluginAuth.save();
|
|
3239
|
+
return newPluginAuth.toObject();
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
catch (error) {
|
|
3243
|
+
throw new Error(`Failed to update plugin auth: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
/**
|
|
3247
|
+
* Deletes plugin auth entries based on provided parameters
|
|
3248
|
+
*/
|
|
3249
|
+
async function deletePluginAuth({ userId, authField, pluginKey, all = false, }) {
|
|
3250
|
+
try {
|
|
3251
|
+
if (all) {
|
|
3252
|
+
const filter = { userId };
|
|
3253
|
+
if (pluginKey) {
|
|
3254
|
+
filter.pluginKey = pluginKey;
|
|
3255
|
+
}
|
|
3256
|
+
return await PluginAuth.deleteMany(filter);
|
|
3257
|
+
}
|
|
3258
|
+
if (!authField) {
|
|
3259
|
+
throw new Error('authField is required when all is false');
|
|
3260
|
+
}
|
|
3261
|
+
return await PluginAuth.deleteOne({ userId, authField });
|
|
3262
|
+
}
|
|
3263
|
+
catch (error) {
|
|
3264
|
+
throw new Error(`Failed to delete plugin auth: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
/**
|
|
3268
|
+
* Deletes all plugin auth entries for a user
|
|
3269
|
+
*/
|
|
3270
|
+
async function deleteAllUserPluginAuths(userId) {
|
|
3271
|
+
try {
|
|
3272
|
+
return await PluginAuth.deleteMany({ userId });
|
|
3273
|
+
}
|
|
3274
|
+
catch (error) {
|
|
3275
|
+
throw new Error(`Failed to delete all user plugin auths: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
3276
|
+
}
|
|
3277
|
+
}
|
|
3278
|
+
return {
|
|
3279
|
+
findOnePluginAuth,
|
|
3280
|
+
findPluginAuthsByKeys,
|
|
3281
|
+
updatePluginAuth,
|
|
3282
|
+
deletePluginAuth,
|
|
3283
|
+
deleteAllUserPluginAuths,
|
|
3284
|
+
};
|
|
3285
|
+
}
|
|
3286
|
+
|
|
2602
3287
|
/**
|
|
2603
3288
|
* Creates all database methods for all collections
|
|
2604
3289
|
*/
|
|
@@ -2608,6 +3293,9 @@ function createMethods(mongoose) {
|
|
|
2608
3293
|
...createSessionMethods(mongoose),
|
|
2609
3294
|
...createTokenMethods(mongoose),
|
|
2610
3295
|
...createRoleMethods(mongoose),
|
|
3296
|
+
...createMemoryMethods(mongoose),
|
|
3297
|
+
...createShareMethods(mongoose),
|
|
3298
|
+
...createPluginAuthMethods(mongoose),
|
|
2611
3299
|
};
|
|
2612
3300
|
}
|
|
2613
3301
|
|
|
@@ -2626,6 +3314,7 @@ exports.hashToken = hashToken;
|
|
|
2626
3314
|
exports.keySchema = keySchema;
|
|
2627
3315
|
exports.logger = logger;
|
|
2628
3316
|
exports.meiliLogger = logger$1;
|
|
3317
|
+
exports.memorySchema = MemoryEntrySchema;
|
|
2629
3318
|
exports.messageSchema = messageSchema;
|
|
2630
3319
|
exports.pluginAuthSchema = pluginAuthSchema;
|
|
2631
3320
|
exports.presetSchema = presetSchema;
|