@okf/ootils 1.26.3 → 1.27.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.
@@ -1184,4 +1184,27 @@ declare const UI_CONTENT: {
1184
1184
  };
1185
1185
  };
1186
1186
 
1187
- export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
1187
+ declare const genCleanCamelCaseId: (id: string) => string;
1188
+
1189
+ /**
1190
+ * Generates a clean, short, unique ID from text input.
1191
+ * Used for both contentType IDs and block valuePaths.
1192
+ *
1193
+ * 1. Strips all characters except A-Z, a-z, 0-9
1194
+ * 2. Lowercases the result
1195
+ * 3. Prepends 'a' if starts with a digit
1196
+ * 4. Truncates to maxLength (default 10)
1197
+ * 5. Appends _{random id} (default 4 chars)
1198
+ *
1199
+ * @param text - The input text to convert
1200
+ * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1201
+ * @param shortIdLength - Length of the random suffix (default 4)
1202
+ *
1203
+ * @example
1204
+ * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1205
+ * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1206
+ * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1207
+ */
1208
+ declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1209
+
1210
+ export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genCleanIdForContentTypeAndValuePaths, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/browser.d.ts CHANGED
@@ -1184,4 +1184,27 @@ declare const UI_CONTENT: {
1184
1184
  };
1185
1185
  };
1186
1186
 
1187
- export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
1187
+ declare const genCleanCamelCaseId: (id: string) => string;
1188
+
1189
+ /**
1190
+ * Generates a clean, short, unique ID from text input.
1191
+ * Used for both contentType IDs and block valuePaths.
1192
+ *
1193
+ * 1. Strips all characters except A-Z, a-z, 0-9
1194
+ * 2. Lowercases the result
1195
+ * 3. Prepends 'a' if starts with a digit
1196
+ * 4. Truncates to maxLength (default 10)
1197
+ * 5. Appends _{random id} (default 4 chars)
1198
+ *
1199
+ * @param text - The input text to convert
1200
+ * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1201
+ * @param shortIdLength - Length of the random suffix (default 4)
1202
+ *
1203
+ * @example
1204
+ * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1205
+ * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1206
+ * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1207
+ */
1208
+ declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1209
+
1210
+ export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genCleanIdForContentTypeAndValuePaths, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/browser.js CHANGED
@@ -33,6 +33,8 @@ __export(browser_exports, {
33
33
  deleteVal: () => deleteVal,
34
34
  extractAllBlocksFromTpl: () => extractAllBlocksFromTpl,
35
35
  extractAndOrganizeBlocks: () => extractAndOrganizeBlocks,
36
+ genCleanCamelCaseId: () => genCleanCamelCaseId,
37
+ genCleanIdForContentTypeAndValuePaths: () => genCleanIdForContentTypeAndValuePaths,
36
38
  genTagId: () => genTagId,
37
39
  generateFilterKey: () => generateFilterKey,
38
40
  getFilterKeyForBlock: () => getFilterKeyForBlock,
@@ -1860,6 +1862,40 @@ var autoGenFilterConfigsFromTpl = ({
1860
1862
  ].filter(Boolean);
1861
1863
  return result;
1862
1864
  };
1865
+
1866
+ // src/utils/genCleanCamelCaseId.ts
1867
+ var genCleanCamelCaseId = (id) => {
1868
+ if (!id || typeof id !== "string") return id;
1869
+ const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
1870
+ if (isAlreadyClean) return id;
1871
+ const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
1872
+ if (words.length === 0) return "a";
1873
+ const result = words.map((word, i) => {
1874
+ const lower = word.toLowerCase();
1875
+ return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
1876
+ }).join("");
1877
+ return /^\d/.test(result) ? "a" + result : result;
1878
+ };
1879
+
1880
+ // src/utils/genCleanIdForContentTypeAndValuePaths.ts
1881
+ var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
1882
+ function genShortId(length = 4) {
1883
+ let result = "";
1884
+ for (let i = 0; i < length; i++) {
1885
+ result += CHARS[Math.floor(Math.random() * CHARS.length)];
1886
+ }
1887
+ return result;
1888
+ }
1889
+ var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
1890
+ if (!text || typeof text !== "string") return text;
1891
+ let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
1892
+ if (!cleaned) {
1893
+ throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
1894
+ }
1895
+ if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
1896
+ const truncated = cleaned.slice(0, maxLength);
1897
+ return `${truncated}_${genShortId(shortIdLength)}`;
1898
+ };
1863
1899
  // Annotate the CommonJS export names for ESM import in node:
1864
1900
  0 && (module.exports = {
1865
1901
  BASE_BULLMQ_CONFIG,
@@ -1875,6 +1911,8 @@ var autoGenFilterConfigsFromTpl = ({
1875
1911
  deleteVal,
1876
1912
  extractAllBlocksFromTpl,
1877
1913
  extractAndOrganizeBlocks,
1914
+ genCleanCamelCaseId,
1915
+ genCleanIdForContentTypeAndValuePaths,
1878
1916
  genTagId,
1879
1917
  generateFilterKey,
1880
1918
  getFilterKeyForBlock,
package/dist/browser.mjs CHANGED
@@ -1806,6 +1806,40 @@ var autoGenFilterConfigsFromTpl = ({
1806
1806
  ].filter(Boolean);
1807
1807
  return result;
1808
1808
  };
1809
+
1810
+ // src/utils/genCleanCamelCaseId.ts
1811
+ var genCleanCamelCaseId = (id) => {
1812
+ if (!id || typeof id !== "string") return id;
1813
+ const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
1814
+ if (isAlreadyClean) return id;
1815
+ const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
1816
+ if (words.length === 0) return "a";
1817
+ const result = words.map((word, i) => {
1818
+ const lower = word.toLowerCase();
1819
+ return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
1820
+ }).join("");
1821
+ return /^\d/.test(result) ? "a" + result : result;
1822
+ };
1823
+
1824
+ // src/utils/genCleanIdForContentTypeAndValuePaths.ts
1825
+ var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
1826
+ function genShortId(length = 4) {
1827
+ let result = "";
1828
+ for (let i = 0; i < length; i++) {
1829
+ result += CHARS[Math.floor(Math.random() * CHARS.length)];
1830
+ }
1831
+ return result;
1832
+ }
1833
+ var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
1834
+ if (!text || typeof text !== "string") return text;
1835
+ let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
1836
+ if (!cleaned) {
1837
+ throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
1838
+ }
1839
+ if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
1840
+ const truncated = cleaned.slice(0, maxLength);
1841
+ return `${truncated}_${genShortId(shortIdLength)}`;
1842
+ };
1809
1843
  export {
1810
1844
  BASE_BULLMQ_CONFIG,
1811
1845
  FILTER_IDS,
@@ -1820,6 +1854,8 @@ export {
1820
1854
  deleteVal,
1821
1855
  extractAllBlocksFromTpl,
1822
1856
  extractAndOrganizeBlocks,
1857
+ genCleanCamelCaseId,
1858
+ genCleanIdForContentTypeAndValuePaths,
1823
1859
  genTagId,
1824
1860
  generateFilterKey,
1825
1861
  getFilterKeyForBlock,
package/dist/node.d.mts CHANGED
@@ -1191,6 +1191,29 @@ declare const UI_CONTENT: {
1191
1191
  };
1192
1192
  };
1193
1193
 
1194
+ declare const genCleanCamelCaseId: (id: string) => string;
1195
+
1196
+ /**
1197
+ * Generates a clean, short, unique ID from text input.
1198
+ * Used for both contentType IDs and block valuePaths.
1199
+ *
1200
+ * 1. Strips all characters except A-Z, a-z, 0-9
1201
+ * 2. Lowercases the result
1202
+ * 3. Prepends 'a' if starts with a digit
1203
+ * 4. Truncates to maxLength (default 10)
1204
+ * 5. Appends _{random id} (default 4 chars)
1205
+ *
1206
+ * @param text - The input text to convert
1207
+ * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1208
+ * @param shortIdLength - Length of the random suffix (default 4)
1209
+ *
1210
+ * @example
1211
+ * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1212
+ * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1213
+ * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1214
+ */
1215
+ declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1216
+
1194
1217
  declare class MongoConnector {
1195
1218
  static getInstance(): any;
1196
1219
  static getClusterConnections(): any;
@@ -1606,6 +1629,7 @@ interface IAIChat extends Document {
1606
1629
  lastActivity: Date;
1607
1630
  messages: IMessage[];
1608
1631
  ACLScope: "aiChat" | "reports";
1632
+ widgetAskAI_Id?: string;
1609
1633
  immutableActiveFilters?: any;
1610
1634
  immutableContentTypes?: string[];
1611
1635
  }
@@ -1920,4 +1944,4 @@ declare function GET_GLOBAL_BULLMQ_CONFIG({ env, redisCredentials }: {
1920
1944
  };
1921
1945
  }): Object;
1922
1946
 
1923
- export { AIChatSchema, AnnosElasticSyncProducer, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, ChunksElasticSyncProducer, ElasticSearchConnector, FILTER_IDS, GET_GLOBAL_BULLMQ_CONFIG, GeneratedEntitiesSchema, GeneratedTopicsSchema, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, SecretManagerConnector, TEMP_removeDuplicateFilters, TplSchema, UI_CONTENT, WorkerManager, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genTagId, generateFilterKey, getAIChatModelByTenant, getAnnotationsModelByTenant, getDbByTenant, getFilterKeyForBlock, getGeneratedEntitiesModelByTenant, getGeneratedTopicsModelByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getTplModelByTenant, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
1947
+ export { AIChatSchema, AnnosElasticSyncProducer, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, ChunksElasticSyncProducer, ElasticSearchConnector, FILTER_IDS, GET_GLOBAL_BULLMQ_CONFIG, GeneratedEntitiesSchema, GeneratedTopicsSchema, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, SecretManagerConnector, TEMP_removeDuplicateFilters, TplSchema, UI_CONTENT, WorkerManager, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genCleanIdForContentTypeAndValuePaths, genTagId, generateFilterKey, getAIChatModelByTenant, getAnnotationsModelByTenant, getDbByTenant, getFilterKeyForBlock, getGeneratedEntitiesModelByTenant, getGeneratedTopicsModelByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getTplModelByTenant, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/node.d.ts CHANGED
@@ -1191,6 +1191,29 @@ declare const UI_CONTENT: {
1191
1191
  };
1192
1192
  };
1193
1193
 
1194
+ declare const genCleanCamelCaseId: (id: string) => string;
1195
+
1196
+ /**
1197
+ * Generates a clean, short, unique ID from text input.
1198
+ * Used for both contentType IDs and block valuePaths.
1199
+ *
1200
+ * 1. Strips all characters except A-Z, a-z, 0-9
1201
+ * 2. Lowercases the result
1202
+ * 3. Prepends 'a' if starts with a digit
1203
+ * 4. Truncates to maxLength (default 10)
1204
+ * 5. Appends _{random id} (default 4 chars)
1205
+ *
1206
+ * @param text - The input text to convert
1207
+ * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1208
+ * @param shortIdLength - Length of the random suffix (default 4)
1209
+ *
1210
+ * @example
1211
+ * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1212
+ * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1213
+ * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1214
+ */
1215
+ declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1216
+
1194
1217
  declare class MongoConnector {
1195
1218
  static getInstance(): any;
1196
1219
  static getClusterConnections(): any;
@@ -1606,6 +1629,7 @@ interface IAIChat extends Document {
1606
1629
  lastActivity: Date;
1607
1630
  messages: IMessage[];
1608
1631
  ACLScope: "aiChat" | "reports";
1632
+ widgetAskAI_Id?: string;
1609
1633
  immutableActiveFilters?: any;
1610
1634
  immutableContentTypes?: string[];
1611
1635
  }
@@ -1920,4 +1944,4 @@ declare function GET_GLOBAL_BULLMQ_CONFIG({ env, redisCredentials }: {
1920
1944
  };
1921
1945
  }): Object;
1922
1946
 
1923
- export { AIChatSchema, AnnosElasticSyncProducer, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, ChunksElasticSyncProducer, ElasticSearchConnector, FILTER_IDS, GET_GLOBAL_BULLMQ_CONFIG, GeneratedEntitiesSchema, GeneratedTopicsSchema, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, SecretManagerConnector, TEMP_removeDuplicateFilters, TplSchema, UI_CONTENT, WorkerManager, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genTagId, generateFilterKey, getAIChatModelByTenant, getAnnotationsModelByTenant, getDbByTenant, getFilterKeyForBlock, getGeneratedEntitiesModelByTenant, getGeneratedTopicsModelByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getTplModelByTenant, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
1947
+ export { AIChatSchema, AnnosElasticSyncProducer, AnnotationSchema, BASE_BULLMQ_CONFIG, BaseProducer, BaseWorker, ChunksElasticSyncProducer, ElasticSearchConnector, FILTER_IDS, GET_GLOBAL_BULLMQ_CONFIG, GeneratedEntitiesSchema, GeneratedTopicsSchema, MongoConnector, PlatformConfigsSchema, ProducerManager, RedisCacheConnector, SecretManagerConnector, TEMP_removeDuplicateFilters, TplSchema, UI_CONTENT, WorkerManager, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genCleanIdForContentTypeAndValuePaths, genTagId, generateFilterKey, getAIChatModelByTenant, getAnnotationsModelByTenant, getDbByTenant, getFilterKeyForBlock, getGeneratedEntitiesModelByTenant, getGeneratedTopicsModelByTenant, getModelByTenant, getPlatformConfigsModelByTenant, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getTplModelByTenant, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/node.js CHANGED
@@ -1023,6 +1023,17 @@ var init_AIChat = __esm({
1023
1023
  default: "aiChat",
1024
1024
  index: true
1025
1025
  },
1026
+ // Deterministic ID linking this chat to a specific WidgetAskAI widget in a report.
1027
+ // The Report Agent generates widget configs on the backend, so at report creation
1028
+ // time no chat exists yet — the LLM query hasn't been fired. Without this ID,
1029
+ // every page load would trigger a fresh LLM call. With it, the first render runs
1030
+ // the LLM and saves the chat under this ID; subsequent renders find the existing
1031
+ // chat and return the cached response immediately.
1032
+ widgetAskAI_Id: {
1033
+ type: String,
1034
+ sparse: true,
1035
+ unique: true
1036
+ },
1026
1037
  immutableActiveFilters: {
1027
1038
  type: import_mongoose4.default.Schema.Types.Mixed,
1028
1039
  default: void 0
@@ -1936,6 +1947,8 @@ __export(node_exports, {
1936
1947
  deleteVal: () => deleteVal,
1937
1948
  extractAllBlocksFromTpl: () => extractAllBlocksFromTpl,
1938
1949
  extractAndOrganizeBlocks: () => extractAndOrganizeBlocks,
1950
+ genCleanCamelCaseId: () => genCleanCamelCaseId,
1951
+ genCleanIdForContentTypeAndValuePaths: () => genCleanIdForContentTypeAndValuePaths,
1939
1952
  genTagId: () => genTagId,
1940
1953
  generateFilterKey: () => generateFilterKey,
1941
1954
  getAIChatModelByTenant: () => import_getModelByTenant2.getAIChatModelByTenant,
@@ -3444,6 +3457,40 @@ var autoGenFilterConfigsFromTpl = ({
3444
3457
  return result;
3445
3458
  };
3446
3459
 
3460
+ // src/utils/genCleanCamelCaseId.ts
3461
+ var genCleanCamelCaseId = (id) => {
3462
+ if (!id || typeof id !== "string") return id;
3463
+ const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
3464
+ if (isAlreadyClean) return id;
3465
+ const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
3466
+ if (words.length === 0) return "a";
3467
+ const result = words.map((word, i) => {
3468
+ const lower = word.toLowerCase();
3469
+ return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
3470
+ }).join("");
3471
+ return /^\d/.test(result) ? "a" + result : result;
3472
+ };
3473
+
3474
+ // src/utils/genCleanIdForContentTypeAndValuePaths.ts
3475
+ var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
3476
+ function genShortId(length = 4) {
3477
+ let result = "";
3478
+ for (let i = 0; i < length; i++) {
3479
+ result += CHARS[Math.floor(Math.random() * CHARS.length)];
3480
+ }
3481
+ return result;
3482
+ }
3483
+ var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
3484
+ if (!text || typeof text !== "string") return text;
3485
+ let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
3486
+ if (!cleaned) {
3487
+ throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
3488
+ }
3489
+ if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
3490
+ const truncated = cleaned.slice(0, maxLength);
3491
+ return `${truncated}_${genShortId(shortIdLength)}`;
3492
+ };
3493
+
3447
3494
  // src/node.ts
3448
3495
  var import_MongoConnector3 = __toESM(require_MongoConnector());
3449
3496
  var import_ElasticSearchConnector = __toESM(require_ElasticSearchConnector());
@@ -3859,6 +3906,8 @@ var import_GET_GLOBAL_BULLMQ_CONFIG = __toESM(require_GET_GLOBAL_BULLMQ_CONFIG()
3859
3906
  deleteVal,
3860
3907
  extractAllBlocksFromTpl,
3861
3908
  extractAndOrganizeBlocks,
3909
+ genCleanCamelCaseId,
3910
+ genCleanIdForContentTypeAndValuePaths,
3862
3911
  genTagId,
3863
3912
  generateFilterKey,
3864
3913
  getAIChatModelByTenant,
package/dist/node.mjs CHANGED
@@ -1028,6 +1028,17 @@ var init_AIChat = __esm({
1028
1028
  default: "aiChat",
1029
1029
  index: true
1030
1030
  },
1031
+ // Deterministic ID linking this chat to a specific WidgetAskAI widget in a report.
1032
+ // The Report Agent generates widget configs on the backend, so at report creation
1033
+ // time no chat exists yet — the LLM query hasn't been fired. Without this ID,
1034
+ // every page load would trigger a fresh LLM call. With it, the first render runs
1035
+ // the LLM and saves the chat under this ID; subsequent renders find the existing
1036
+ // chat and return the cached response immediately.
1037
+ widgetAskAI_Id: {
1038
+ type: String,
1039
+ sparse: true,
1040
+ unique: true
1041
+ },
1031
1042
  immutableActiveFilters: {
1032
1043
  type: mongoose4.Schema.Types.Mixed,
1033
1044
  default: void 0
@@ -3389,6 +3400,40 @@ var autoGenFilterConfigsFromTpl = ({
3389
3400
  return result;
3390
3401
  };
3391
3402
 
3403
+ // src/utils/genCleanCamelCaseId.ts
3404
+ var genCleanCamelCaseId = (id) => {
3405
+ if (!id || typeof id !== "string") return id;
3406
+ const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
3407
+ if (isAlreadyClean) return id;
3408
+ const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
3409
+ if (words.length === 0) return "a";
3410
+ const result = words.map((word, i) => {
3411
+ const lower = word.toLowerCase();
3412
+ return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
3413
+ }).join("");
3414
+ return /^\d/.test(result) ? "a" + result : result;
3415
+ };
3416
+
3417
+ // src/utils/genCleanIdForContentTypeAndValuePaths.ts
3418
+ var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
3419
+ function genShortId(length = 4) {
3420
+ let result = "";
3421
+ for (let i = 0; i < length; i++) {
3422
+ result += CHARS[Math.floor(Math.random() * CHARS.length)];
3423
+ }
3424
+ return result;
3425
+ }
3426
+ var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
3427
+ if (!text || typeof text !== "string") return text;
3428
+ let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
3429
+ if (!cleaned) {
3430
+ throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
3431
+ }
3432
+ if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
3433
+ const truncated = cleaned.slice(0, maxLength);
3434
+ return `${truncated}_${genShortId(shortIdLength)}`;
3435
+ };
3436
+
3392
3437
  // src/node.ts
3393
3438
  var import_MongoConnector3 = __toESM(require_MongoConnector());
3394
3439
  var import_ElasticSearchConnector = __toESM(require_ElasticSearchConnector());
@@ -3819,6 +3864,8 @@ export {
3819
3864
  deleteVal,
3820
3865
  extractAllBlocksFromTpl,
3821
3866
  extractAndOrganizeBlocks,
3867
+ genCleanCamelCaseId,
3868
+ genCleanIdForContentTypeAndValuePaths,
3822
3869
  genTagId,
3823
3870
  generateFilterKey,
3824
3871
  export_getAIChatModelByTenant as getAIChatModelByTenant,
@@ -1184,4 +1184,27 @@ declare const UI_CONTENT: {
1184
1184
  };
1185
1185
  };
1186
1186
 
1187
- export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
1187
+ declare const genCleanCamelCaseId: (id: string) => string;
1188
+
1189
+ /**
1190
+ * Generates a clean, short, unique ID from text input.
1191
+ * Used for both contentType IDs and block valuePaths.
1192
+ *
1193
+ * 1. Strips all characters except A-Z, a-z, 0-9
1194
+ * 2. Lowercases the result
1195
+ * 3. Prepends 'a' if starts with a digit
1196
+ * 4. Truncates to maxLength (default 10)
1197
+ * 5. Appends _{random id} (default 4 chars)
1198
+ *
1199
+ * @param text - The input text to convert
1200
+ * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1201
+ * @param shortIdLength - Length of the random suffix (default 4)
1202
+ *
1203
+ * @example
1204
+ * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1205
+ * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1206
+ * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1207
+ */
1208
+ declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1209
+
1210
+ export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genCleanIdForContentTypeAndValuePaths, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
@@ -1184,4 +1184,27 @@ declare const UI_CONTENT: {
1184
1184
  };
1185
1185
  };
1186
1186
 
1187
- export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
1187
+ declare const genCleanCamelCaseId: (id: string) => string;
1188
+
1189
+ /**
1190
+ * Generates a clean, short, unique ID from text input.
1191
+ * Used for both contentType IDs and block valuePaths.
1192
+ *
1193
+ * 1. Strips all characters except A-Z, a-z, 0-9
1194
+ * 2. Lowercases the result
1195
+ * 3. Prepends 'a' if starts with a digit
1196
+ * 4. Truncates to maxLength (default 10)
1197
+ * 5. Appends _{random id} (default 4 chars)
1198
+ *
1199
+ * @param text - The input text to convert
1200
+ * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1201
+ * @param shortIdLength - Length of the random suffix (default 4)
1202
+ *
1203
+ * @example
1204
+ * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1205
+ * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1206
+ * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1207
+ */
1208
+ declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1209
+
1210
+ export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genCleanIdForContentTypeAndValuePaths, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/universal.js CHANGED
@@ -33,6 +33,8 @@ __export(universal_exports, {
33
33
  deleteVal: () => deleteVal,
34
34
  extractAllBlocksFromTpl: () => extractAllBlocksFromTpl,
35
35
  extractAndOrganizeBlocks: () => extractAndOrganizeBlocks,
36
+ genCleanCamelCaseId: () => genCleanCamelCaseId,
37
+ genCleanIdForContentTypeAndValuePaths: () => genCleanIdForContentTypeAndValuePaths,
36
38
  genTagId: () => genTagId,
37
39
  generateFilterKey: () => generateFilterKey,
38
40
  getFilterKeyForBlock: () => getFilterKeyForBlock,
@@ -1860,6 +1862,40 @@ var autoGenFilterConfigsFromTpl = ({
1860
1862
  ].filter(Boolean);
1861
1863
  return result;
1862
1864
  };
1865
+
1866
+ // src/utils/genCleanCamelCaseId.ts
1867
+ var genCleanCamelCaseId = (id) => {
1868
+ if (!id || typeof id !== "string") return id;
1869
+ const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
1870
+ if (isAlreadyClean) return id;
1871
+ const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
1872
+ if (words.length === 0) return "a";
1873
+ const result = words.map((word, i) => {
1874
+ const lower = word.toLowerCase();
1875
+ return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
1876
+ }).join("");
1877
+ return /^\d/.test(result) ? "a" + result : result;
1878
+ };
1879
+
1880
+ // src/utils/genCleanIdForContentTypeAndValuePaths.ts
1881
+ var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
1882
+ function genShortId(length = 4) {
1883
+ let result = "";
1884
+ for (let i = 0; i < length; i++) {
1885
+ result += CHARS[Math.floor(Math.random() * CHARS.length)];
1886
+ }
1887
+ return result;
1888
+ }
1889
+ var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
1890
+ if (!text || typeof text !== "string") return text;
1891
+ let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
1892
+ if (!cleaned) {
1893
+ throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
1894
+ }
1895
+ if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
1896
+ const truncated = cleaned.slice(0, maxLength);
1897
+ return `${truncated}_${genShortId(shortIdLength)}`;
1898
+ };
1863
1899
  // Annotate the CommonJS export names for ESM import in node:
1864
1900
  0 && (module.exports = {
1865
1901
  BASE_BULLMQ_CONFIG,
@@ -1875,6 +1911,8 @@ var autoGenFilterConfigsFromTpl = ({
1875
1911
  deleteVal,
1876
1912
  extractAllBlocksFromTpl,
1877
1913
  extractAndOrganizeBlocks,
1914
+ genCleanCamelCaseId,
1915
+ genCleanIdForContentTypeAndValuePaths,
1878
1916
  genTagId,
1879
1917
  generateFilterKey,
1880
1918
  getFilterKeyForBlock,
@@ -1806,6 +1806,40 @@ var autoGenFilterConfigsFromTpl = ({
1806
1806
  ].filter(Boolean);
1807
1807
  return result;
1808
1808
  };
1809
+
1810
+ // src/utils/genCleanCamelCaseId.ts
1811
+ var genCleanCamelCaseId = (id) => {
1812
+ if (!id || typeof id !== "string") return id;
1813
+ const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
1814
+ if (isAlreadyClean) return id;
1815
+ const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
1816
+ if (words.length === 0) return "a";
1817
+ const result = words.map((word, i) => {
1818
+ const lower = word.toLowerCase();
1819
+ return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
1820
+ }).join("");
1821
+ return /^\d/.test(result) ? "a" + result : result;
1822
+ };
1823
+
1824
+ // src/utils/genCleanIdForContentTypeAndValuePaths.ts
1825
+ var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
1826
+ function genShortId(length = 4) {
1827
+ let result = "";
1828
+ for (let i = 0; i < length; i++) {
1829
+ result += CHARS[Math.floor(Math.random() * CHARS.length)];
1830
+ }
1831
+ return result;
1832
+ }
1833
+ var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
1834
+ if (!text || typeof text !== "string") return text;
1835
+ let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
1836
+ if (!cleaned) {
1837
+ throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
1838
+ }
1839
+ if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
1840
+ const truncated = cleaned.slice(0, maxLength);
1841
+ return `${truncated}_${genShortId(shortIdLength)}`;
1842
+ };
1809
1843
  export {
1810
1844
  BASE_BULLMQ_CONFIG,
1811
1845
  FILTER_IDS,
@@ -1820,6 +1854,8 @@ export {
1820
1854
  deleteVal,
1821
1855
  extractAllBlocksFromTpl,
1822
1856
  extractAndOrganizeBlocks,
1857
+ genCleanCamelCaseId,
1858
+ genCleanIdForContentTypeAndValuePaths,
1823
1859
  genTagId,
1824
1860
  generateFilterKey,
1825
1861
  getFilterKeyForBlock,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.26.3",
6
+ "version": "1.27.0",
7
7
  "description": "Utility functions for both browser and Node.js",
8
8
  "main": "dist/index.js",
9
9
  "module": "dist/index.mjs",