@okf/ootils 1.42.0 → 1.44.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/node.d.mts +6556 -1
- package/dist/node.d.ts +6556 -1
- package/dist/node.js +810 -19
- package/dist/node.mjs +796 -19
- package/package.json +2 -1
package/dist/node.mjs
CHANGED
|
@@ -940,7 +940,7 @@ var init_Tpl = __esm({
|
|
|
940
940
|
var require_MongoConnector = __commonJS({
|
|
941
941
|
"src/db/MongoConnector.js"(exports, module) {
|
|
942
942
|
"use strict";
|
|
943
|
-
var
|
|
943
|
+
var mongoose10 = __require("mongoose");
|
|
944
944
|
var { ServerApiVersion } = __require("mongodb");
|
|
945
945
|
var AnnotationsSchema = (init_Annotations(), __toCommonJS(Annotations_exports));
|
|
946
946
|
var PlatformConfigsSchema2 = (init_PlatformConfigs(), __toCommonJS(PlatformConfigs_exports));
|
|
@@ -1004,7 +1004,7 @@ var require_MongoConnector = __commonJS({
|
|
|
1004
1004
|
`Missing CLUSTER_NAME or CLUSTER_URI in cluster conf: ${JSON.stringify(clusterConf)}`
|
|
1005
1005
|
);
|
|
1006
1006
|
}
|
|
1007
|
-
this.clusterConnections[CLUSTER_NAME] =
|
|
1007
|
+
this.clusterConnections[CLUSTER_NAME] = mongoose10.createConnection(
|
|
1008
1008
|
CLUSTER_URI,
|
|
1009
1009
|
this.mongoOptions
|
|
1010
1010
|
);
|
|
@@ -1031,7 +1031,7 @@ var require_MongoConnector = __commonJS({
|
|
|
1031
1031
|
this.skippedClusters.add(CLUSTER_NAME);
|
|
1032
1032
|
return;
|
|
1033
1033
|
}
|
|
1034
|
-
const connection =
|
|
1034
|
+
const connection = mongoose10.createConnection(CLUSTER_URI, this.mongoOptions);
|
|
1035
1035
|
this.clusterConnections[CLUSTER_NAME] = connection;
|
|
1036
1036
|
this.initiateConnectionEventListeners(CLUSTER_NAME);
|
|
1037
1037
|
await new Promise((resolve, reject) => {
|
|
@@ -1496,7 +1496,7 @@ var require_getModelByTenant = __commonJS({
|
|
|
1496
1496
|
"use strict";
|
|
1497
1497
|
var { getDbByTenant: getDbByTenant2 } = (init_getDbByTenant(), __toCommonJS(getDbByTenant_exports));
|
|
1498
1498
|
var { AIChatSchema: AIChatSchema2, AnnotationSchema: AnnotationSchema2, PlatformConfigsSchema: PlatformConfigsSchema2, TplSchema: TplSchema2, GeneratedTopicsSchema: GeneratedTopicsSchema2, GeneratedEntitiesSchema: GeneratedEntitiesSchema2 } = (init_models(), __toCommonJS(models_exports));
|
|
1499
|
-
var
|
|
1499
|
+
var getModelByTenant4 = ({ tenant, modelName, schema, env }) => {
|
|
1500
1500
|
if (!tenant) {
|
|
1501
1501
|
throw new Error("tenant id has not been provided");
|
|
1502
1502
|
}
|
|
@@ -1506,48 +1506,48 @@ var require_getModelByTenant = __commonJS({
|
|
|
1506
1506
|
}
|
|
1507
1507
|
return db.model(modelName);
|
|
1508
1508
|
};
|
|
1509
|
-
var getAnnotationsModelByTenant2 = ({ tenant, env, mongodb, modelName }) =>
|
|
1509
|
+
var getAnnotationsModelByTenant2 = ({ tenant, env, mongodb, modelName }) => getModelByTenant4({
|
|
1510
1510
|
tenant,
|
|
1511
1511
|
modelName: modelName || "annotations",
|
|
1512
1512
|
schema: AnnotationSchema2,
|
|
1513
1513
|
env
|
|
1514
1514
|
});
|
|
1515
|
-
var getPlatformConfigsModelByTenant2 = ({ tenant, env, mongodb }) =>
|
|
1515
|
+
var getPlatformConfigsModelByTenant2 = ({ tenant, env, mongodb }) => getModelByTenant4({
|
|
1516
1516
|
tenant,
|
|
1517
1517
|
modelName: "platformConfigs",
|
|
1518
1518
|
schema: PlatformConfigsSchema2,
|
|
1519
1519
|
env
|
|
1520
1520
|
});
|
|
1521
|
-
var
|
|
1521
|
+
var getTplModelByTenant3 = ({ tenant, env, mongodb }) => getModelByTenant4({
|
|
1522
1522
|
tenant,
|
|
1523
1523
|
modelName: "tpl",
|
|
1524
1524
|
schema: TplSchema2,
|
|
1525
1525
|
env
|
|
1526
1526
|
});
|
|
1527
|
-
var getAIChatModelByTenant2 = ({ tenant, env, mongodb }) =>
|
|
1527
|
+
var getAIChatModelByTenant2 = ({ tenant, env, mongodb }) => getModelByTenant4({
|
|
1528
1528
|
tenant,
|
|
1529
1529
|
modelName: "aiChat",
|
|
1530
1530
|
schema: AIChatSchema2,
|
|
1531
1531
|
env
|
|
1532
1532
|
});
|
|
1533
|
-
var getGeneratedTopicsModelByTenant2 = ({ tenant, env }) =>
|
|
1533
|
+
var getGeneratedTopicsModelByTenant2 = ({ tenant, env }) => getModelByTenant4({
|
|
1534
1534
|
tenant,
|
|
1535
1535
|
modelName: "generatedTopics",
|
|
1536
1536
|
schema: GeneratedTopicsSchema2,
|
|
1537
1537
|
env
|
|
1538
1538
|
});
|
|
1539
|
-
var getGeneratedEntitiesModelByTenant2 = ({ tenant, env }) =>
|
|
1539
|
+
var getGeneratedEntitiesModelByTenant2 = ({ tenant, env }) => getModelByTenant4({
|
|
1540
1540
|
tenant,
|
|
1541
1541
|
modelName: "generatedEntities",
|
|
1542
1542
|
schema: GeneratedEntitiesSchema2,
|
|
1543
1543
|
env
|
|
1544
1544
|
});
|
|
1545
1545
|
module.exports = {
|
|
1546
|
-
getModelByTenant:
|
|
1546
|
+
getModelByTenant: getModelByTenant4,
|
|
1547
1547
|
getAIChatModelByTenant: getAIChatModelByTenant2,
|
|
1548
1548
|
getAnnotationsModelByTenant: getAnnotationsModelByTenant2,
|
|
1549
1549
|
getPlatformConfigsModelByTenant: getPlatformConfigsModelByTenant2,
|
|
1550
|
-
getTplModelByTenant:
|
|
1550
|
+
getTplModelByTenant: getTplModelByTenant3,
|
|
1551
1551
|
getGeneratedTopicsModelByTenant: getGeneratedTopicsModelByTenant2,
|
|
1552
1552
|
getGeneratedEntitiesModelByTenant: getGeneratedEntitiesModelByTenant2
|
|
1553
1553
|
};
|
|
@@ -5019,8 +5019,771 @@ RedisCacheConnector.instance = null;
|
|
|
5019
5019
|
// src/node.ts
|
|
5020
5020
|
init_SecretManagerConnector();
|
|
5021
5021
|
init_getDbByTenant();
|
|
5022
|
+
var import_getModelByTenant4 = __toESM(require_getModelByTenant());
|
|
5023
|
+
|
|
5024
|
+
// src/contentSchema/genContentTypeSchema.js
|
|
5025
|
+
import mongoose9 from "mongoose";
|
|
5026
|
+
|
|
5027
|
+
// src/contentSchema/components/_backOfficeFields__contr.js
|
|
5028
|
+
import mongoose5 from "mongoose";
|
|
5029
|
+
var _backOfficeFields__contr = (thisContentModelRef) => ({
|
|
5030
|
+
//----- (USUSED AT THE MOMENT) version 2 properties for better tracking & interlinking of document clones ---- //
|
|
5031
|
+
isPrimaryDoc: Boolean,
|
|
5032
|
+
cloneStack: [mongoose5.Schema.Types.ObjectId],
|
|
5033
|
+
// the last item in the array being the last clone
|
|
5034
|
+
ogStack: [mongoose5.Schema.Types.ObjectId],
|
|
5035
|
+
// the last item in the array being the og-est og ( the primaryDoc )
|
|
5036
|
+
//----- END version 2 properties ---- //
|
|
5037
|
+
tagId: String,
|
|
5038
|
+
kp_published_status: {
|
|
5039
|
+
type: String,
|
|
5040
|
+
// options : draft | published | editPublished | awaitingModeration | underModeration
|
|
5041
|
+
default: "draft",
|
|
5042
|
+
required: true
|
|
5043
|
+
},
|
|
5044
|
+
warnings: [Object],
|
|
5045
|
+
kp_og_published_doc: {
|
|
5046
|
+
type: mongoose5.Schema.Types.ObjectId,
|
|
5047
|
+
ref: thisContentModelRef
|
|
5048
|
+
},
|
|
5049
|
+
// ----- mod rel --- //
|
|
5050
|
+
kp_pre_mod_doc: {
|
|
5051
|
+
type: mongoose5.Schema.Types.ObjectId
|
|
5052
|
+
},
|
|
5053
|
+
kp_is_pbl_taken_into_mod: Boolean,
|
|
5054
|
+
kp_is_mod_clone: Boolean,
|
|
5055
|
+
kp_moderator: {
|
|
5056
|
+
type: mongoose5.Schema.Types.ObjectId,
|
|
5057
|
+
ref: "user"
|
|
5058
|
+
},
|
|
5059
|
+
kp_date_mod_begin: Date,
|
|
5060
|
+
kp_date_mod_end: Date,
|
|
5061
|
+
kp_date_submitted: Date,
|
|
5062
|
+
// ----- END mod rel --- //
|
|
5063
|
+
kp_date_created: Date,
|
|
5064
|
+
kp_date_last_saved: Date,
|
|
5065
|
+
kp_date_published: {
|
|
5066
|
+
type: Date
|
|
5067
|
+
},
|
|
5068
|
+
editPublishedDocId: {
|
|
5069
|
+
//only comes on og docs that have an editPbl clone
|
|
5070
|
+
type: mongoose5.Schema.Types.ObjectId,
|
|
5071
|
+
ref: thisContentModelRef
|
|
5072
|
+
},
|
|
5073
|
+
currentEditor: {
|
|
5074
|
+
type: mongoose5.Schema.Types.ObjectId,
|
|
5075
|
+
//relevant for segments : staticPages & collection, where author dont matter.
|
|
5076
|
+
ref: "user"
|
|
5077
|
+
},
|
|
5078
|
+
lastActivity: {
|
|
5079
|
+
date: {
|
|
5080
|
+
type: Date
|
|
5081
|
+
}
|
|
5082
|
+
}
|
|
5083
|
+
});
|
|
5084
|
+
|
|
5085
|
+
// src/contentSchema/components/_comments__contr.js
|
|
5086
|
+
import mongoose6 from "mongoose";
|
|
5087
|
+
var baseCommentsObj = {
|
|
5088
|
+
user: {
|
|
5089
|
+
userId: { type: mongoose6.Schema.Types.ObjectId, ref: "user" },
|
|
5090
|
+
profileType: String,
|
|
5091
|
+
name: String,
|
|
5092
|
+
avatar: Object
|
|
5093
|
+
},
|
|
5094
|
+
text: Object,
|
|
5095
|
+
dateCreated: Date,
|
|
5096
|
+
dateModified: [Date]
|
|
5097
|
+
//the start of tracking mod dates on things..experiment...
|
|
5098
|
+
};
|
|
5099
|
+
var _comments__contr = {
|
|
5100
|
+
comments: [
|
|
5101
|
+
{
|
|
5102
|
+
...baseCommentsObj,
|
|
5103
|
+
responses: [baseCommentsObj]
|
|
5104
|
+
}
|
|
5105
|
+
]
|
|
5106
|
+
};
|
|
5107
|
+
|
|
5108
|
+
// src/contentSchema/components/_reaction_contr.js
|
|
5109
|
+
import mongoose7 from "mongoose";
|
|
5110
|
+
var baseSchema = {
|
|
5111
|
+
type: {
|
|
5112
|
+
type: String,
|
|
5113
|
+
enum: ["like", "celebrate", "inspiring", "learnings"]
|
|
5114
|
+
},
|
|
5115
|
+
dateCreated: Date,
|
|
5116
|
+
userId: { type: mongoose7.Schema.Types.ObjectId, ref: "user" }
|
|
5117
|
+
};
|
|
5118
|
+
var _reaction_contr = {
|
|
5119
|
+
reactions: [
|
|
5120
|
+
{
|
|
5121
|
+
...baseSchema
|
|
5122
|
+
}
|
|
5123
|
+
]
|
|
5124
|
+
};
|
|
5125
|
+
|
|
5126
|
+
// src/contentSchema/components/_constantMeta__contr.js
|
|
5127
|
+
import mongoose8 from "mongoose";
|
|
5128
|
+
var _constantMeta__contr = {
|
|
5129
|
+
kp_contributed_by: {
|
|
5130
|
+
type: mongoose8.Schema.Types.ObjectId,
|
|
5131
|
+
ref: "user",
|
|
5132
|
+
required: true
|
|
5133
|
+
},
|
|
5134
|
+
kp_content_type: {
|
|
5135
|
+
type: String,
|
|
5136
|
+
required: true
|
|
5137
|
+
},
|
|
5138
|
+
// "thematic" or "attribute" — distinguishes thematic sub-themes/tags from
|
|
5139
|
+
// attribute classification categories (speech act, emotion, etc.).
|
|
5140
|
+
taxonomyRole: {
|
|
5141
|
+
type: String
|
|
5142
|
+
},
|
|
5143
|
+
// Only meaningful on sub-theme docs. When false, new tags cannot be created under
|
|
5144
|
+
// this sub-theme (by humans via API or by the inductive AI annotator).
|
|
5145
|
+
// Absent/true = allowed (default).
|
|
5146
|
+
allowNewTags: {
|
|
5147
|
+
type: Boolean
|
|
5148
|
+
},
|
|
5149
|
+
// Only meaningful on attribute-role sub-themes. "single" = pick one tag,
|
|
5150
|
+
// "multi" = pick one or more. Default "multi".
|
|
5151
|
+
selectMode: {
|
|
5152
|
+
type: String
|
|
5153
|
+
},
|
|
5154
|
+
// "autoAI" | "humanInTheLoop" — absent means human editor (default).
|
|
5155
|
+
createdVia: {
|
|
5156
|
+
type: String
|
|
5157
|
+
}
|
|
5158
|
+
};
|
|
5159
|
+
|
|
5160
|
+
// src/contentSchema/components/_fixedMainFields__contr.js
|
|
5161
|
+
var _fixedMainFields__contr = {
|
|
5162
|
+
/**
|
|
5163
|
+
* hard coding title & subtitle is required because,
|
|
5164
|
+
* in tpl categories like 'researchNotes' the title comp is never defined in the template.
|
|
5165
|
+
* instead, it is hardcoded in the code, and it expects a 'main.title' value path.
|
|
5166
|
+
* Hence the hardcode below. Besides its not a problem, since, if in the template a
|
|
5167
|
+
* main.title component is indeed defined, then these hardcodes would be overwritten by
|
|
5168
|
+
* mainExtract. Which is what we want.
|
|
5169
|
+
*/
|
|
5170
|
+
title: {
|
|
5171
|
+
type: String,
|
|
5172
|
+
cast: (v) => typeof v === "string" ? String(v) : Object(v)
|
|
5173
|
+
},
|
|
5174
|
+
subtitle: {
|
|
5175
|
+
type: String,
|
|
5176
|
+
cast: (v) => typeof v === "string" ? String(v) : Object(v)
|
|
5177
|
+
},
|
|
5178
|
+
titleInfo: String
|
|
5179
|
+
// this is used to show the meta text ("This story is supported by AI-assisted bot") on the published page
|
|
5180
|
+
};
|
|
5181
|
+
|
|
5182
|
+
// src/contentSchema/extractAllUniqueAnnoTagTypesFromTpl.js
|
|
5183
|
+
var extractAllUniqueAnnoTagTypesFromTpl = (extractedBlocks, { smTagTypesConfig } = {}) => {
|
|
5184
|
+
return Array.from(
|
|
5185
|
+
new Set(
|
|
5186
|
+
blockRegistry.getAnnotationEnabledBlocks(extractedBlocks).flatMap((bl) => [
|
|
5187
|
+
...blockRegistry.getTagTypesConfig(bl, smTagTypesConfig).map((tt) => tt.tagType),
|
|
5188
|
+
...bl.props?.annotation?.toggleTagTypesConfig?.map((tt) => tt.tagType) || []
|
|
5189
|
+
])
|
|
5190
|
+
)
|
|
5191
|
+
);
|
|
5192
|
+
};
|
|
5193
|
+
|
|
5194
|
+
// src/contentSchema/getTypesForSchemaFromTpl/compToTypeMap/getConditionalDataType.js
|
|
5195
|
+
var getConditionalDataType = ({ block }) => {
|
|
5196
|
+
if (block.props?.saveValueAsString)
|
|
5197
|
+
return {
|
|
5198
|
+
type: Number,
|
|
5199
|
+
cast: (v) => {
|
|
5200
|
+
if (typeof v === "number" && !isNaN(v)) {
|
|
5201
|
+
return Number(v);
|
|
5202
|
+
} else if (typeof v === "string") {
|
|
5203
|
+
return String(v);
|
|
5204
|
+
} else {
|
|
5205
|
+
return Boolean(v);
|
|
5206
|
+
}
|
|
5207
|
+
}
|
|
5208
|
+
};
|
|
5209
|
+
else {
|
|
5210
|
+
const returnValue = ["DropdownMulti", "CheckboxList"].includes(block.comp) ? { type: Array } : { type: Object };
|
|
5211
|
+
return returnValue;
|
|
5212
|
+
}
|
|
5213
|
+
};
|
|
5214
|
+
|
|
5215
|
+
// src/contentSchema/utils/extractNumberFromValue.js
|
|
5216
|
+
var extractNumberFromValue = (value) => {
|
|
5217
|
+
if (value === null || value === void 0) return void 0;
|
|
5218
|
+
if (typeof value === "number") return isNaN(value) ? void 0 : value;
|
|
5219
|
+
const str = String(value).trim();
|
|
5220
|
+
if (str === "") return void 0;
|
|
5221
|
+
const directParse = Number(str);
|
|
5222
|
+
if (!isNaN(directParse)) return directParse;
|
|
5223
|
+
const commaNumberMatch = str.match(/-?\d[\d,]*\d(?:\.\d+)?/);
|
|
5224
|
+
if (commaNumberMatch && commaNumberMatch[0].includes(",")) {
|
|
5225
|
+
const num = Number(commaNumberMatch[0].replace(/,/g, ""));
|
|
5226
|
+
if (!isNaN(num)) return num;
|
|
5227
|
+
}
|
|
5228
|
+
const numberMatch = str.match(/-?\d+(?:\.\d+)?/);
|
|
5229
|
+
if (numberMatch) {
|
|
5230
|
+
const num = Number(numberMatch[0]);
|
|
5231
|
+
return isNaN(num) ? void 0 : num;
|
|
5232
|
+
}
|
|
5233
|
+
return void 0;
|
|
5234
|
+
};
|
|
5235
|
+
|
|
5236
|
+
// src/contentSchema/getTypesForSchemaFromTpl/compToTypeMap/index.js
|
|
5237
|
+
var compToTypeMap = ({ block }) => {
|
|
5238
|
+
const comp = block.comp;
|
|
5239
|
+
const blockDef = blockRegistry.getBlock(comp);
|
|
5240
|
+
if (blockDef) return blockDef.mongoSchemaType;
|
|
5241
|
+
switch (comp) {
|
|
5242
|
+
case "SummaryInput":
|
|
5243
|
+
case "KPRichInput":
|
|
5244
|
+
//deprecated
|
|
5245
|
+
case "RichTextEditor":
|
|
5246
|
+
//deprecated
|
|
5247
|
+
case "StaticRichText":
|
|
5248
|
+
case "CardRadioInput":
|
|
5249
|
+
case "NumberRangeInput":
|
|
5250
|
+
case "KPLikeContactChannelsBlock":
|
|
5251
|
+
case "TitleInput":
|
|
5252
|
+
case "SubtitleInput":
|
|
5253
|
+
case "PluginSentinel":
|
|
5254
|
+
case "DynamicRefetchDropdown":
|
|
5255
|
+
case "VideoInput":
|
|
5256
|
+
// data type for videoinput should actually be array, but since the old version of the comp used a string data type, we are currently setting it to object to avoid error
|
|
5257
|
+
case "SimpleTable":
|
|
5258
|
+
case "GroupQuestionsInputSingle":
|
|
5259
|
+
return { type: Object };
|
|
5260
|
+
case "ProfileImageInput":
|
|
5261
|
+
case "ResourceInput":
|
|
5262
|
+
case "ImageInput":
|
|
5263
|
+
case "VideoInput":
|
|
5264
|
+
case "Repeater":
|
|
5265
|
+
case "RepeaterTabs":
|
|
5266
|
+
case "PDFInput":
|
|
5267
|
+
case "TextInputToArray":
|
|
5268
|
+
return { type: Array };
|
|
5269
|
+
case "RichTextAsPlainText":
|
|
5270
|
+
case "PasswordInput":
|
|
5271
|
+
case "EmailInput":
|
|
5272
|
+
case "TextInput":
|
|
5273
|
+
case "URLInput":
|
|
5274
|
+
case "PhoneInput":
|
|
5275
|
+
case "KPMetaPrimary":
|
|
5276
|
+
case "IFrameInput":
|
|
5277
|
+
case "JSONInput":
|
|
5278
|
+
return { type: String };
|
|
5279
|
+
case "NumberInput":
|
|
5280
|
+
return {
|
|
5281
|
+
type: Number,
|
|
5282
|
+
// Smart extraction of numbers from messy values (e.g. "18+", "18 years old", "$100")
|
|
5283
|
+
// Uses extractNumberFromValue utility for consistent behavior with direct import
|
|
5284
|
+
set: extractNumberFromValue
|
|
5285
|
+
};
|
|
5286
|
+
case "DropdownSingleLanguage":
|
|
5287
|
+
case "ComboboxSingleLanguage":
|
|
5288
|
+
return {
|
|
5289
|
+
type: [
|
|
5290
|
+
{
|
|
5291
|
+
display: String,
|
|
5292
|
+
value: String
|
|
5293
|
+
}
|
|
5294
|
+
]
|
|
5295
|
+
};
|
|
5296
|
+
case "DatePicker":
|
|
5297
|
+
return { type: Date };
|
|
5298
|
+
case "DateTimePicker":
|
|
5299
|
+
return { type: Date };
|
|
5300
|
+
case "TimePicker":
|
|
5301
|
+
return {
|
|
5302
|
+
type: String,
|
|
5303
|
+
// Validates time is in 24-hour format (00:00-23:59) with hours 00-23, a colon, and minutes 00-59
|
|
5304
|
+
validate: {
|
|
5305
|
+
validator: function(v) {
|
|
5306
|
+
return /^([01]\d|2[0-3]):([0-5]\d)$/.test(v);
|
|
5307
|
+
},
|
|
5308
|
+
message: (props) => `${props.value} is not a valid time format!`
|
|
5309
|
+
}
|
|
5310
|
+
};
|
|
5311
|
+
case "CheckboxButton":
|
|
5312
|
+
return { type: Boolean };
|
|
5313
|
+
case "TagsInputMulti":
|
|
5314
|
+
case "FragmentsSet":
|
|
5315
|
+
case "FragmentsDict":
|
|
5316
|
+
case "TagsInputSingle":
|
|
5317
|
+
return {
|
|
5318
|
+
type: {
|
|
5319
|
+
collectionId: String,
|
|
5320
|
+
data: [
|
|
5321
|
+
{
|
|
5322
|
+
_id: {
|
|
5323
|
+
type: String,
|
|
5324
|
+
index: block.index === true
|
|
5325
|
+
},
|
|
5326
|
+
display: String,
|
|
5327
|
+
tagId: String
|
|
5328
|
+
}
|
|
5329
|
+
]
|
|
5330
|
+
}
|
|
5331
|
+
};
|
|
5332
|
+
case "SPECIAL_AnnotationTagsField":
|
|
5333
|
+
return {
|
|
5334
|
+
/**
|
|
5335
|
+
* very important that we wrap the whole thing in type,
|
|
5336
|
+
* because, if the tag name itself is type (like in the case of noora),
|
|
5337
|
+
* then it completely confuses mongoose, since type is a reserved word,
|
|
5338
|
+
* and causes all sorts of bugs.
|
|
5339
|
+
*/
|
|
5340
|
+
type: {
|
|
5341
|
+
collectionId: String,
|
|
5342
|
+
data: Array
|
|
5343
|
+
//leaving this weakly typed for now cuz annotations have several other properties in here which i am not aware of..
|
|
5344
|
+
}
|
|
5345
|
+
};
|
|
5346
|
+
case "LinkEmbedWithInput":
|
|
5347
|
+
return {
|
|
5348
|
+
type: {
|
|
5349
|
+
url: String,
|
|
5350
|
+
metadata: Object
|
|
5351
|
+
}
|
|
5352
|
+
};
|
|
5353
|
+
case "CheckboxList":
|
|
5354
|
+
//new
|
|
5355
|
+
case "RadioList":
|
|
5356
|
+
//new
|
|
5357
|
+
case "DropdownSingle":
|
|
5358
|
+
//new
|
|
5359
|
+
case "DropdownMulti":
|
|
5360
|
+
//new
|
|
5361
|
+
case "SwitchDouble":
|
|
5362
|
+
case "SwitchSingle":
|
|
5363
|
+
return getConditionalDataType({ block });
|
|
5364
|
+
case "DateTimeRangePicker":
|
|
5365
|
+
return {
|
|
5366
|
+
type: {
|
|
5367
|
+
date: Date,
|
|
5368
|
+
timeRange: Array
|
|
5369
|
+
}
|
|
5370
|
+
};
|
|
5371
|
+
case "DateRangePicker":
|
|
5372
|
+
return { type: Array };
|
|
5373
|
+
}
|
|
5374
|
+
};
|
|
5375
|
+
|
|
5376
|
+
// src/contentSchema/getTypesForSchemaFromTpl/index.js
|
|
5377
|
+
var getTypesForSchemaFromTpl = (options = {}) => {
|
|
5378
|
+
const { tpl, smTagTypesConfig } = options;
|
|
5379
|
+
const defaultSchemaFieldsByTplLayout = {
|
|
5380
|
+
researchNotes2: {
|
|
5381
|
+
tags: {
|
|
5382
|
+
quotes: {
|
|
5383
|
+
collectionId: String,
|
|
5384
|
+
data: Array
|
|
5385
|
+
},
|
|
5386
|
+
vocabs: {
|
|
5387
|
+
collectionId: String,
|
|
5388
|
+
data: Array
|
|
5389
|
+
}
|
|
5390
|
+
}
|
|
5391
|
+
}
|
|
5392
|
+
};
|
|
5393
|
+
let mainExtract = {};
|
|
5394
|
+
let metaExtract = {};
|
|
5395
|
+
let tagsExtract = {};
|
|
5396
|
+
let rootExtract = {};
|
|
5397
|
+
let annoExtract = {
|
|
5398
|
+
...defaultSchemaFieldsByTplLayout[tpl?.category] || {}
|
|
5399
|
+
};
|
|
5400
|
+
const extractedBlocks = extractAllBlocksFromTpl({ tpl });
|
|
5401
|
+
const annotationTagTypes = extractAllUniqueAnnoTagTypesFromTpl(extractedBlocks, {
|
|
5402
|
+
smTagTypesConfig
|
|
5403
|
+
});
|
|
5404
|
+
annotationTagTypes.forEach((annoTagType) => {
|
|
5405
|
+
const annotationFieldDef = compToTypeMap({
|
|
5406
|
+
block: { comp: "SPECIAL_AnnotationTagsField" }
|
|
5407
|
+
});
|
|
5408
|
+
annoExtract = setVal(annoExtract, `tags.${annoTagType}`, annotationFieldDef);
|
|
5409
|
+
});
|
|
5410
|
+
extractedBlocks.forEach((block) => {
|
|
5411
|
+
const { valuePath } = block;
|
|
5412
|
+
if (!valuePath) return;
|
|
5413
|
+
const pathSegments = valuePath.split(".");
|
|
5414
|
+
const [prefix, ...remainingPath] = pathSegments;
|
|
5415
|
+
const nestedPath = remainingPath.join(".");
|
|
5416
|
+
const fieldDefinition = compToTypeMap({ block });
|
|
5417
|
+
switch (prefix) {
|
|
5418
|
+
case "meta":
|
|
5419
|
+
metaExtract = setVal(
|
|
5420
|
+
metaExtract,
|
|
5421
|
+
nestedPath,
|
|
5422
|
+
// "author.name" (without "meta" prefix)
|
|
5423
|
+
fieldDefinition
|
|
5424
|
+
);
|
|
5425
|
+
break;
|
|
5426
|
+
case "main":
|
|
5427
|
+
mainExtract = setVal(
|
|
5428
|
+
mainExtract,
|
|
5429
|
+
nestedPath,
|
|
5430
|
+
// "content.title" (without "main" prefix)
|
|
5431
|
+
fieldDefinition
|
|
5432
|
+
);
|
|
5433
|
+
break;
|
|
5434
|
+
case "tags":
|
|
5435
|
+
tagsExtract = setVal(
|
|
5436
|
+
tagsExtract,
|
|
5437
|
+
nestedPath,
|
|
5438
|
+
// "categories.primary" (without "tags" prefix)
|
|
5439
|
+
fieldDefinition
|
|
5440
|
+
);
|
|
5441
|
+
break;
|
|
5442
|
+
default:
|
|
5443
|
+
if (block.comp && block.comp !== "TplMetaBlock" && valuePath !== ".") {
|
|
5444
|
+
rootExtract = setVal(
|
|
5445
|
+
rootExtract,
|
|
5446
|
+
valuePath,
|
|
5447
|
+
// Use full path since it's not prefixed
|
|
5448
|
+
fieldDefinition
|
|
5449
|
+
);
|
|
5450
|
+
}
|
|
5451
|
+
break;
|
|
5452
|
+
}
|
|
5453
|
+
});
|
|
5454
|
+
return {
|
|
5455
|
+
metaExtract,
|
|
5456
|
+
mainExtract,
|
|
5457
|
+
tagsExtract,
|
|
5458
|
+
rootExtract,
|
|
5459
|
+
annoExtract
|
|
5460
|
+
};
|
|
5461
|
+
};
|
|
5462
|
+
|
|
5463
|
+
// src/contentSchema/genContentTypeSchema.js
|
|
5464
|
+
var genContentTypeSchema = ({ contentType, segment, contentTypeConfig, smTagTypesConfig }) => {
|
|
5465
|
+
let SchemaToReturn;
|
|
5466
|
+
let {
|
|
5467
|
+
mainExtract = {},
|
|
5468
|
+
metaExtract = {},
|
|
5469
|
+
tagsExtract = {},
|
|
5470
|
+
rootExtract = {},
|
|
5471
|
+
annoExtract = {}
|
|
5472
|
+
} = getTypesForSchemaFromTpl({ tpl: contentTypeConfig, smTagTypesConfig });
|
|
5473
|
+
const schemaDef = {
|
|
5474
|
+
/**
|
|
5475
|
+
* this metadata is v.important from an optimization point of view.
|
|
5476
|
+
* it helps with getAllContrModelsByTenant, without having to
|
|
5477
|
+
* query the database for content type configurations.
|
|
5478
|
+
*/
|
|
5479
|
+
metadata: {
|
|
5480
|
+
isContentType: { type: String, default: true },
|
|
5481
|
+
contentType: { type: String, default: contentType },
|
|
5482
|
+
segment: { type: String, default: segment }
|
|
5483
|
+
},
|
|
5484
|
+
..._backOfficeFields__contr(contentType),
|
|
5485
|
+
...rootExtract,
|
|
5486
|
+
tags: {
|
|
5487
|
+
...tagsExtract
|
|
5488
|
+
},
|
|
5489
|
+
annotations: {
|
|
5490
|
+
...annoExtract
|
|
5491
|
+
},
|
|
5492
|
+
meta: {
|
|
5493
|
+
..._constantMeta__contr,
|
|
5494
|
+
...metaExtract
|
|
5495
|
+
},
|
|
5496
|
+
main: {
|
|
5497
|
+
..._fixedMainFields__contr,
|
|
5498
|
+
...mainExtract
|
|
5499
|
+
},
|
|
5500
|
+
archive: Object,
|
|
5501
|
+
//burial ground for past fields that have eventually been removed from the tpl (and therefore the schema)
|
|
5502
|
+
translations: Object,
|
|
5503
|
+
reviewerNotes: Object,
|
|
5504
|
+
..._reaction_contr,
|
|
5505
|
+
..._comments__contr,
|
|
5506
|
+
...segment === "publishing" && {
|
|
5507
|
+
shares: {
|
|
5508
|
+
count: {
|
|
5509
|
+
type: Number,
|
|
5510
|
+
default: 0
|
|
5511
|
+
}
|
|
5512
|
+
},
|
|
5513
|
+
views: {
|
|
5514
|
+
count: {
|
|
5515
|
+
type: Number,
|
|
5516
|
+
default: 0
|
|
5517
|
+
}
|
|
5518
|
+
}
|
|
5519
|
+
},
|
|
5520
|
+
updates: Object
|
|
5521
|
+
// DEPRECATED. DONT USE IT. DONT DELETE EITHER. ELSE WE WILL HAVE TO MAKE DATA UPDATES
|
|
5522
|
+
};
|
|
5523
|
+
SchemaToReturn = new mongoose9.Schema(schemaDef, {
|
|
5524
|
+
collection: contentType,
|
|
5525
|
+
toJSON: { virtuals: true },
|
|
5526
|
+
// So `res.json()` and other `JSON.stringify()` functions include virtuals
|
|
5527
|
+
toObject: { virtuals: true },
|
|
5528
|
+
// So `toObject()` output includes virtuals
|
|
5529
|
+
strict: "throw"
|
|
5530
|
+
//will throw an error if we try to add properties that arent on this schema
|
|
5531
|
+
});
|
|
5532
|
+
SchemaToReturn.index(
|
|
5533
|
+
{ tagId: 1 },
|
|
5534
|
+
...segment === "collections" ? [
|
|
5535
|
+
{
|
|
5536
|
+
unique: true,
|
|
5537
|
+
partialFilterExpression: {
|
|
5538
|
+
kp_published_status: { $eq: "published" }
|
|
5539
|
+
}
|
|
5540
|
+
}
|
|
5541
|
+
] : []
|
|
5542
|
+
);
|
|
5543
|
+
SchemaToReturn.index({
|
|
5544
|
+
kp_published_status: 1,
|
|
5545
|
+
kp_date_published: -1,
|
|
5546
|
+
_id: -1
|
|
5547
|
+
});
|
|
5548
|
+
SchemaToReturn.index(
|
|
5549
|
+
{ kp_published_status: 1, "main.title": 1, _id: 1 },
|
|
5550
|
+
{ collation: { locale: "en", numericOrdering: true } }
|
|
5551
|
+
);
|
|
5552
|
+
SchemaToReturn.index({ kp_published_status: 1, kp_is_mod_clone: 1 });
|
|
5553
|
+
return SchemaToReturn;
|
|
5554
|
+
};
|
|
5555
|
+
|
|
5556
|
+
// src/TenantRegistry.js
|
|
5557
|
+
import { Storage } from "@google-cloud/storage";
|
|
5558
|
+
var BUCKET_NAME = "dots-system-configs";
|
|
5559
|
+
var FILE_NAME = "tenantRegistry.json";
|
|
5560
|
+
var TenantRegistry = class {
|
|
5561
|
+
// ─── Initialization ─────────────────────────────────
|
|
5562
|
+
/**
|
|
5563
|
+
* Must be awaited at startup before any sync getter is called.
|
|
5564
|
+
* Uses Application Default Credentials (ADC) for GCS auth.
|
|
5565
|
+
*/
|
|
5566
|
+
static async init() {
|
|
5567
|
+
this._data = await this._load();
|
|
5568
|
+
this._rebuildCaches();
|
|
5569
|
+
this._lastRefreshAt = Date.now();
|
|
5570
|
+
}
|
|
5571
|
+
/**
|
|
5572
|
+
* Reload from GCS when this instance sees an unknown tenant/origin — likely one
|
|
5573
|
+
* provisioned on another instance after startup. Rate-limited; on failure keeps
|
|
5574
|
+
* the existing cache (never throws). Returns true if a reload actually ran.
|
|
5575
|
+
*/
|
|
5576
|
+
static async refreshIfStale() {
|
|
5577
|
+
const now = Date.now();
|
|
5578
|
+
if (now - this._lastRefreshAt < this.REFRESH_COOLDOWN_MS) return false;
|
|
5579
|
+
this._lastRefreshAt = now;
|
|
5580
|
+
try {
|
|
5581
|
+
this._data = await this._load();
|
|
5582
|
+
this._rebuildCaches();
|
|
5583
|
+
return true;
|
|
5584
|
+
} catch (err) {
|
|
5585
|
+
console.error(`[TenantRegistry] refresh failed (keeping cache): ${err.message}`);
|
|
5586
|
+
return false;
|
|
5587
|
+
}
|
|
5588
|
+
}
|
|
5589
|
+
// ─── Storage layer (swap only these to change backend) ───
|
|
5590
|
+
static async _load() {
|
|
5591
|
+
const storage = new Storage();
|
|
5592
|
+
const file = storage.bucket(BUCKET_NAME).file(FILE_NAME);
|
|
5593
|
+
const [buffer] = await file.download();
|
|
5594
|
+
const { data } = JSON.parse(buffer.toString("utf-8"));
|
|
5595
|
+
console.log(`[TenantRegistry] Loaded ${data.length} tenants from GCS`);
|
|
5596
|
+
return data;
|
|
5597
|
+
}
|
|
5598
|
+
static async _save() {
|
|
5599
|
+
const storage = new Storage();
|
|
5600
|
+
const file = storage.bucket(BUCKET_NAME).file(FILE_NAME);
|
|
5601
|
+
await file.save(JSON.stringify({ data: this._data }, null, 2), {
|
|
5602
|
+
contentType: "application/json"
|
|
5603
|
+
});
|
|
5604
|
+
}
|
|
5605
|
+
// ─── End storage layer ──────────────────────────────
|
|
5606
|
+
static _rebuildCaches() {
|
|
5607
|
+
this._byEnv = {};
|
|
5608
|
+
this._selfManagedSet = /* @__PURE__ */ new Set();
|
|
5609
|
+
for (const entry of this._data) {
|
|
5610
|
+
const { tenantId, urls, isSelfManaged } = entry;
|
|
5611
|
+
if (isSelfManaged) this._selfManagedSet.add(tenantId);
|
|
5612
|
+
for (const env of ["dev", "staging", "prod"]) {
|
|
5613
|
+
if (!urls[env]) continue;
|
|
5614
|
+
if (!this._byEnv[env]) this._byEnv[env] = {};
|
|
5615
|
+
this._byEnv[env][tenantId] = urls[env];
|
|
5616
|
+
}
|
|
5617
|
+
}
|
|
5618
|
+
}
|
|
5619
|
+
// ─── Sync getters ───────────────────────────────────
|
|
5620
|
+
/** { tenantId: url } for the given env */
|
|
5621
|
+
static getMappingsForEnv(env) {
|
|
5622
|
+
return this._byEnv[env] || {};
|
|
5623
|
+
}
|
|
5624
|
+
/** [url, url, ...] for the given env */
|
|
5625
|
+
static getUrlsForEnv(env) {
|
|
5626
|
+
return Object.values(this._byEnv[env] || {});
|
|
5627
|
+
}
|
|
5628
|
+
/** [tenantId, tenantId, ...] for the given env */
|
|
5629
|
+
static getTenantIdsForEnv(env) {
|
|
5630
|
+
return Object.keys(this._byEnv[env] || {});
|
|
5631
|
+
}
|
|
5632
|
+
/** Single URL for a tenant+env, or undefined */
|
|
5633
|
+
static getUrl(tenant, env) {
|
|
5634
|
+
return (this._byEnv[env] || {})[tenant];
|
|
5635
|
+
}
|
|
5636
|
+
static isSelfManaged(tenant) {
|
|
5637
|
+
return this._selfManagedSet.has(tenant);
|
|
5638
|
+
}
|
|
5639
|
+
static getSelfManagedTenantIds() {
|
|
5640
|
+
return [...this._selfManagedSet];
|
|
5641
|
+
}
|
|
5642
|
+
/** Full registry data array (read-only snapshot) */
|
|
5643
|
+
static getData() {
|
|
5644
|
+
return this._data;
|
|
5645
|
+
}
|
|
5646
|
+
// ─── Mutator ────────────────────────────────────────
|
|
5647
|
+
/**
|
|
5648
|
+
* Idempotent: removes existing entry for tenantId (if any), then adds.
|
|
5649
|
+
* Persists to GCS and updates in-memory caches.
|
|
5650
|
+
*/
|
|
5651
|
+
static async addTenant({ tenantId, urls, isSelfManaged = false }) {
|
|
5652
|
+
this._data = this._data.filter((e) => e.tenantId !== tenantId);
|
|
5653
|
+
this._data.push({ tenantId, urls, isSelfManaged });
|
|
5654
|
+
await this._save();
|
|
5655
|
+
this._rebuildCaches();
|
|
5656
|
+
}
|
|
5657
|
+
/**
|
|
5658
|
+
* Idempotent inverse of addTenant: drops the tenant's entry from the registry,
|
|
5659
|
+
* persists to GCS, and rebuilds in-memory caches (so the tenant stops resolving
|
|
5660
|
+
* on THIS instance immediately). Returns true if an entry was actually removed.
|
|
5661
|
+
* Other running instances pick up the removal via refreshIfStale() on their next
|
|
5662
|
+
* unknown-origin miss.
|
|
5663
|
+
*/
|
|
5664
|
+
static async removeTenant(tenantId) {
|
|
5665
|
+
const before = this._data.length;
|
|
5666
|
+
this._data = this._data.filter((e) => e.tenantId !== tenantId);
|
|
5667
|
+
const removed = this._data.length < before;
|
|
5668
|
+
if (removed) {
|
|
5669
|
+
await this._save();
|
|
5670
|
+
this._rebuildCaches();
|
|
5671
|
+
}
|
|
5672
|
+
return removed;
|
|
5673
|
+
}
|
|
5674
|
+
};
|
|
5675
|
+
// ─── In-memory state ────────────────────────────────
|
|
5676
|
+
__publicField(TenantRegistry, "_data", null);
|
|
5677
|
+
// [{ tenantId, urls: { dev, staging, prod }, isSelfManaged }]
|
|
5678
|
+
__publicField(TenantRegistry, "_byEnv", {});
|
|
5679
|
+
// { dev: { tenantId: url }, staging: {...}, prod: {...} }
|
|
5680
|
+
__publicField(TenantRegistry, "_selfManagedSet", /* @__PURE__ */ new Set());
|
|
5681
|
+
// On-miss refresh rate-limit (see refreshIfStale).
|
|
5682
|
+
__publicField(TenantRegistry, "_lastRefreshAt", 0);
|
|
5683
|
+
__publicField(TenantRegistry, "REFRESH_COOLDOWN_MS", 3e4);
|
|
5684
|
+
|
|
5685
|
+
// src/contentSchema/selfManagedAnnotationTagTypesConfig.js
|
|
5686
|
+
var SM_ANNOTATION_TAG_TYPES_CONFIG = [{ tagType: "tags" }];
|
|
5687
|
+
var getSmTagTypesConfigForTenant = async (tenant) => {
|
|
5688
|
+
return TenantRegistry.isSelfManaged(tenant) ? SM_ANNOTATION_TAG_TYPES_CONFIG : null;
|
|
5689
|
+
};
|
|
5690
|
+
|
|
5691
|
+
// src/db/getContrModelByTenant.js
|
|
5692
|
+
var import_getModelByTenant3 = __toESM(require_getModelByTenant());
|
|
5693
|
+
init_getDbByTenant();
|
|
5694
|
+
|
|
5695
|
+
// src/db/getTpl.js
|
|
5022
5696
|
var import_getModelByTenant2 = __toESM(require_getModelByTenant());
|
|
5697
|
+
var getTpl = async ({ tenant, contentType, env, source = "db" }) => {
|
|
5698
|
+
if (source === "cache") {
|
|
5699
|
+
return RedisCacheConnector.findOneConfigInCache({
|
|
5700
|
+
tenant,
|
|
5701
|
+
modelName: "tpl",
|
|
5702
|
+
type: contentType,
|
|
5703
|
+
env
|
|
5704
|
+
});
|
|
5705
|
+
}
|
|
5706
|
+
return (0, import_getModelByTenant2.getTplModelByTenant)({ tenant, env }).findOne({ kp_content_type: contentType }).lean();
|
|
5707
|
+
};
|
|
5708
|
+
|
|
5709
|
+
// src/db/getContrModelByTenant.js
|
|
5710
|
+
var getContrModelByTenant = async ({
|
|
5711
|
+
tenant,
|
|
5712
|
+
contentType,
|
|
5713
|
+
env = process.env.ENV,
|
|
5714
|
+
// v.imp, else the reuse check below always fails when env isn't passed (env is meant to be optional)
|
|
5715
|
+
tpl,
|
|
5716
|
+
//optional : if passed uses it instead of fetching the tpl for this contenttype from db. important in the case of _createTpl, where, within a transaction we create a tpl and then use this tpl to create some content against it. since this is within a transaction, this newly created tpl wont be available in the db just yet.
|
|
5717
|
+
tplSource = "db",
|
|
5718
|
+
// "db" (okf-be default, original semantics) | "cache" (okf-sub — tpl cache is kept in sync on every tpl write)
|
|
5719
|
+
/**
|
|
5720
|
+
* When true, the registered-model reuse is SKIPPED — the schema is rebuilt
|
|
5721
|
+
* from the current tpl on every call (~5-10ms CPU + the tpl read).
|
|
5722
|
+
*
|
|
5723
|
+
* okf-sub passes this on every collab call: unlike okf-be — which
|
|
5724
|
+
* invalidates registered models on tpl change via
|
|
5725
|
+
* reRegisterModelInLocalCache + the '${env}-tpl-model-recache' Pub/Sub —
|
|
5726
|
+
* okf-sub subscribes to nothing, so a reused model could carry a stale
|
|
5727
|
+
* schema after a tpl edit, and strict:"throw" would reject collab flushes
|
|
5728
|
+
* for newly added fields. Rebuilding every time is correct by
|
|
5729
|
+
* construction: no freshness bookkeeping for tpl write paths (or raw
|
|
5730
|
+
* mongodbscripts that mutate tpls + recache) to ever get wrong.
|
|
5731
|
+
*/
|
|
5732
|
+
rebuild = false
|
|
5733
|
+
}) => {
|
|
5734
|
+
try {
|
|
5735
|
+
const db = getDbByTenant({ tenant });
|
|
5736
|
+
if (!rebuild && db.models[contentType] && env === process.env.ENV && !tpl) {
|
|
5737
|
+
const modelToReturn = db.model(contentType);
|
|
5738
|
+
if (modelToReturn.schema.obj.metadata && modelToReturn.schema.obj.metadata.isContentType && modelToReturn.schema.obj.metadata.isContentType.default === true) {
|
|
5739
|
+
return modelToReturn;
|
|
5740
|
+
}
|
|
5741
|
+
return void 0;
|
|
5742
|
+
}
|
|
5743
|
+
const contentTypeConfig = tpl || await getTpl({ tenant, contentType, env, source: tplSource });
|
|
5744
|
+
if (!contentTypeConfig) return void 0;
|
|
5745
|
+
const smTagTypesConfig = await getSmTagTypesConfigForTenant(tenant);
|
|
5746
|
+
const thisSchema = genContentTypeSchema({
|
|
5747
|
+
contentType,
|
|
5748
|
+
segment: contentTypeConfig.general?.segment,
|
|
5749
|
+
contentTypeConfig,
|
|
5750
|
+
smTagTypesConfig
|
|
5751
|
+
});
|
|
5752
|
+
if (rebuild && db.models[contentType]) {
|
|
5753
|
+
db.deleteModel(contentType);
|
|
5754
|
+
}
|
|
5755
|
+
return (0, import_getModelByTenant3.getModelByTenant)({
|
|
5756
|
+
tenant,
|
|
5757
|
+
modelName: contentType,
|
|
5758
|
+
schema: thisSchema,
|
|
5759
|
+
env
|
|
5760
|
+
});
|
|
5761
|
+
} catch (err) {
|
|
5762
|
+
throw err;
|
|
5763
|
+
}
|
|
5764
|
+
};
|
|
5765
|
+
|
|
5766
|
+
// src/node.ts
|
|
5023
5767
|
init_models();
|
|
5768
|
+
|
|
5769
|
+
// src/collab/liveCollabDocMarker.js
|
|
5770
|
+
var TTL_SECONDS = 300;
|
|
5771
|
+
var LIVE_COLLAB_DOC_REFRESH_MS = 12e4;
|
|
5772
|
+
var buildKey = ({ env, tenant, contentType, docId }) => `${env || RedisCacheConnector.getEnv()}:liveCollabDoc:${tenant}:${contentType}:${docId}`;
|
|
5773
|
+
var markLiveCollabDoc = async ({ tenant, contentType, docId, env }) => {
|
|
5774
|
+
const client = RedisCacheConnector.getClient(env || RedisCacheConnector.getEnv());
|
|
5775
|
+
await client.set(buildKey({ env, tenant, contentType, docId }), Date.now(), "EX", TTL_SECONDS);
|
|
5776
|
+
};
|
|
5777
|
+
var clearLiveCollabDoc = async ({ tenant, contentType, docId, env }) => {
|
|
5778
|
+
const client = RedisCacheConnector.getClient(env || RedisCacheConnector.getEnv());
|
|
5779
|
+
await client.del(buildKey({ env, tenant, contentType, docId }));
|
|
5780
|
+
};
|
|
5781
|
+
var isLiveCollabDoc = async ({ tenant, contentType, docId, env }) => {
|
|
5782
|
+
const client = RedisCacheConnector.getClient(env || RedisCacheConnector.getEnv());
|
|
5783
|
+
return await client.exists(buildKey({ env, tenant, contentType, docId })) === 1;
|
|
5784
|
+
};
|
|
5785
|
+
|
|
5786
|
+
// src/node.ts
|
|
5024
5787
|
var import_WorkerManager = __toESM(require_WorkerManager());
|
|
5025
5788
|
var import_ProducerManager = __toESM(require_ProducerManager());
|
|
5026
5789
|
var import_BaseProducer = __toESM(require_BaseProducer());
|
|
@@ -5041,13 +5804,13 @@ var export_GET_GLOBAL_BULLMQ_CONFIG = import_GET_GLOBAL_BULLMQ_CONFIG.GET_GLOBAL
|
|
|
5041
5804
|
var export_MongoConnector = import_MongoConnector3.MongoConnector;
|
|
5042
5805
|
var export_ProducerManager = import_ProducerManager.ProducerManager;
|
|
5043
5806
|
var export_WorkerManager = import_WorkerManager.WorkerManager;
|
|
5044
|
-
var export_getAIChatModelByTenant =
|
|
5045
|
-
var export_getAnnotationsModelByTenant =
|
|
5046
|
-
var export_getGeneratedEntitiesModelByTenant =
|
|
5047
|
-
var export_getGeneratedTopicsModelByTenant =
|
|
5048
|
-
var export_getModelByTenant =
|
|
5049
|
-
var export_getPlatformConfigsModelByTenant =
|
|
5050
|
-
var export_getTplModelByTenant =
|
|
5807
|
+
var export_getAIChatModelByTenant = import_getModelByTenant4.getAIChatModelByTenant;
|
|
5808
|
+
var export_getAnnotationsModelByTenant = import_getModelByTenant4.getAnnotationsModelByTenant;
|
|
5809
|
+
var export_getGeneratedEntitiesModelByTenant = import_getModelByTenant4.getGeneratedEntitiesModelByTenant;
|
|
5810
|
+
var export_getGeneratedTopicsModelByTenant = import_getModelByTenant4.getGeneratedTopicsModelByTenant;
|
|
5811
|
+
var export_getModelByTenant = import_getModelByTenant4.getModelByTenant;
|
|
5812
|
+
var export_getPlatformConfigsModelByTenant = import_getModelByTenant4.getPlatformConfigsModelByTenant;
|
|
5813
|
+
var export_getTplModelByTenant = import_getModelByTenant4.getTplModelByTenant;
|
|
5051
5814
|
export {
|
|
5052
5815
|
AIChat_default as AIChatSchema,
|
|
5053
5816
|
export_AnnosElasticSyncProducer as AnnosElasticSyncProducer,
|
|
@@ -5066,6 +5829,7 @@ export {
|
|
|
5066
5829
|
export_GET_GLOBAL_BULLMQ_CONFIG as GET_GLOBAL_BULLMQ_CONFIG,
|
|
5067
5830
|
GeneratedEntities_default as GeneratedEntitiesSchema,
|
|
5068
5831
|
GeneratedTopics_default as GeneratedTopicsSchema,
|
|
5832
|
+
LIVE_COLLAB_DOC_REFRESH_MS,
|
|
5069
5833
|
MONGO_SCHEMA_PRESETS,
|
|
5070
5834
|
export_MongoConnector as MongoConnector,
|
|
5071
5835
|
PlatformConfigs_default as PlatformConfigsSchema,
|
|
@@ -5073,9 +5837,13 @@ export {
|
|
|
5073
5837
|
RedisCacheConnector,
|
|
5074
5838
|
SecretManagerConnector,
|
|
5075
5839
|
TEMP_removeDuplicateFilters,
|
|
5840
|
+
TenantRegistry,
|
|
5076
5841
|
Tpl_default as TplSchema,
|
|
5077
5842
|
UI_CONTENT,
|
|
5078
5843
|
export_WorkerManager as WorkerManager,
|
|
5844
|
+
_backOfficeFields__contr,
|
|
5845
|
+
_constantMeta__contr,
|
|
5846
|
+
_fixedMainFields__contr,
|
|
5079
5847
|
_self_managed_buildAnnoHierarchyConfig,
|
|
5080
5848
|
_self_managed_buildDocHierarchyConfig,
|
|
5081
5849
|
_self_managed_getFixedAnnoRollupBlocks,
|
|
@@ -5083,17 +5851,22 @@ export {
|
|
|
5083
5851
|
autoGenFilterConfigsFromTpl,
|
|
5084
5852
|
blockRegistry,
|
|
5085
5853
|
buildFilterConfigurations,
|
|
5854
|
+
clearLiveCollabDoc,
|
|
5086
5855
|
collectMarkIdsInOrder,
|
|
5087
5856
|
compareAndGroupBlocks,
|
|
5088
5857
|
deleteVal,
|
|
5089
5858
|
extractAllBlocksFromTpl,
|
|
5859
|
+
extractAllUniqueAnnoTagTypesFromTpl,
|
|
5090
5860
|
extractAndOrganizeBlocks,
|
|
5861
|
+
extractNumberFromValue,
|
|
5091
5862
|
genCleanCamelCaseId,
|
|
5863
|
+
genContentTypeSchema,
|
|
5092
5864
|
genTagId,
|
|
5093
5865
|
generateFilterKey,
|
|
5094
5866
|
export_getAIChatModelByTenant as getAIChatModelByTenant,
|
|
5095
5867
|
getAnnoFilterBucketKey,
|
|
5096
5868
|
export_getAnnotationsModelByTenant as getAnnotationsModelByTenant,
|
|
5869
|
+
getContrModelByTenant,
|
|
5097
5870
|
getDbByTenant,
|
|
5098
5871
|
getFilterKeyForBlock,
|
|
5099
5872
|
export_getGeneratedEntitiesModelByTenant as getGeneratedEntitiesModelByTenant,
|
|
@@ -5110,9 +5883,13 @@ export {
|
|
|
5110
5883
|
getRoutePathToReviewDashboard,
|
|
5111
5884
|
getRoutePathToTCI,
|
|
5112
5885
|
getRoutePathToTagCategoryLanding,
|
|
5886
|
+
getTpl,
|
|
5113
5887
|
export_getTplModelByTenant as getTplModelByTenant,
|
|
5888
|
+
getTypesForSchemaFromTpl,
|
|
5114
5889
|
getVal,
|
|
5890
|
+
isLiveCollabDoc,
|
|
5115
5891
|
isTplAnnotationEnabled,
|
|
5892
|
+
markLiveCollabDoc,
|
|
5116
5893
|
mergeAnnoDataIntoAnnotationsTags,
|
|
5117
5894
|
parseSpecialConfigSyntax,
|
|
5118
5895
|
plainTextToLexical,
|