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