@okf/ootils 1.28.0 → 1.28.2

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.
@@ -1260,27 +1260,27 @@ declare const UI_CONTENT: {
1260
1260
  };
1261
1261
  };
1262
1262
 
1263
- declare const genCleanCamelCaseId: (id: string) => string;
1264
-
1265
1263
  /**
1266
- * Generates a clean, short, unique ID from text input.
1267
- * Used for both contentType IDs and block valuePaths.
1264
+ * Generates a clean, deterministic, alphanumeric camelCase ID from text.
1268
1265
  *
1269
- * 1. Strips all characters except A-Z, a-z, 0-9
1270
- * 2. Lowercases the result
1271
- * 3. Prepends 'a' if starts with a digit
1272
- * 4. Truncates to maxLength (default 10)
1273
- * 5. Appends _{random id} (default 4 chars)
1266
+ * 1. Splits on non-alphanumeric characters, builds camelCase
1267
+ * 2. Strips all non a-zA-Z0-9 from result
1268
+ * 3. If input had no unicode letters/numbers at all (e.g. "---"), returns 'a'
1269
+ * 4. If camelCase had content but nothing survived ASCII strip (pure non-Latin),
1270
+ * generates a deterministic hash (FNV-1a) of the unicode camelCase
1271
+ * 5. Prepends 'a' if starts with digit
1272
+ * 6. Truncates to 40 chars
1274
1273
  *
1275
- * @param text - The input text to convert
1276
- * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1277
- * @param shortIdLength - Length of the random suffix (default 4)
1274
+ * Idempotent: running twice produces the same output.
1278
1275
  *
1279
1276
  * @example
1280
- * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1281
- * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1282
- * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1277
+ * genCleanCamelCaseId("Author Name") => "authorName"
1278
+ * genCleanCamelCaseId("authorName") => "authorName" (idempotent)
1279
+ * genCleanCamelCaseId("123 Test") => "a123Test"
1280
+ * genCleanCamelCaseId("café latté") => "cafLatt"
1281
+ * genCleanCamelCaseId("مرحبا") => deterministic hash
1282
+ * genCleanCamelCaseId("---") => "a"
1283
1283
  */
1284
- declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1284
+ declare const genCleanCamelCaseId: (id: string) => string;
1285
1285
 
1286
- export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _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 };
1286
+ export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/browser.d.ts CHANGED
@@ -1260,27 +1260,27 @@ declare const UI_CONTENT: {
1260
1260
  };
1261
1261
  };
1262
1262
 
1263
- declare const genCleanCamelCaseId: (id: string) => string;
1264
-
1265
1263
  /**
1266
- * Generates a clean, short, unique ID from text input.
1267
- * Used for both contentType IDs and block valuePaths.
1264
+ * Generates a clean, deterministic, alphanumeric camelCase ID from text.
1268
1265
  *
1269
- * 1. Strips all characters except A-Z, a-z, 0-9
1270
- * 2. Lowercases the result
1271
- * 3. Prepends 'a' if starts with a digit
1272
- * 4. Truncates to maxLength (default 10)
1273
- * 5. Appends _{random id} (default 4 chars)
1266
+ * 1. Splits on non-alphanumeric characters, builds camelCase
1267
+ * 2. Strips all non a-zA-Z0-9 from result
1268
+ * 3. If input had no unicode letters/numbers at all (e.g. "---"), returns 'a'
1269
+ * 4. If camelCase had content but nothing survived ASCII strip (pure non-Latin),
1270
+ * generates a deterministic hash (FNV-1a) of the unicode camelCase
1271
+ * 5. Prepends 'a' if starts with digit
1272
+ * 6. Truncates to 40 chars
1274
1273
  *
1275
- * @param text - The input text to convert
1276
- * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1277
- * @param shortIdLength - Length of the random suffix (default 4)
1274
+ * Idempotent: running twice produces the same output.
1278
1275
  *
1279
1276
  * @example
1280
- * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1281
- * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1282
- * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1277
+ * genCleanCamelCaseId("Author Name") => "authorName"
1278
+ * genCleanCamelCaseId("authorName") => "authorName" (idempotent)
1279
+ * genCleanCamelCaseId("123 Test") => "a123Test"
1280
+ * genCleanCamelCaseId("café latté") => "cafLatt"
1281
+ * genCleanCamelCaseId("مرحبا") => deterministic hash
1282
+ * genCleanCamelCaseId("---") => "a"
1283
1283
  */
1284
- declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1284
+ declare const genCleanCamelCaseId: (id: string) => string;
1285
1285
 
1286
- export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _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 };
1286
+ export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/browser.js CHANGED
@@ -35,7 +35,6 @@ __export(browser_exports, {
35
35
  extractAllBlocksFromTpl: () => extractAllBlocksFromTpl,
36
36
  extractAndOrganizeBlocks: () => extractAndOrganizeBlocks,
37
37
  genCleanCamelCaseId: () => genCleanCamelCaseId,
38
- genCleanIdForContentTypeAndValuePaths: () => genCleanIdForContentTypeAndValuePaths,
39
38
  genTagId: () => genTagId,
40
39
  generateFilterKey: () => generateFilterKey,
41
40
  getFilterKeyForBlock: () => getFilterKeyForBlock,
@@ -2127,37 +2126,28 @@ var autoGenFilterConfigsFromTpl = ({
2127
2126
  };
2128
2127
 
2129
2128
  // src/utils/genCleanCamelCaseId.ts
2129
+ var MAX_LENGTH = 40;
2130
+ function fnv1a(str, length = 8) {
2131
+ let hash = 2166136261;
2132
+ for (let i = 0; i < str.length; i++) {
2133
+ hash ^= str.charCodeAt(i);
2134
+ hash = hash * 16777619 >>> 0;
2135
+ }
2136
+ return hash.toString(36).slice(0, length);
2137
+ }
2130
2138
  var genCleanCamelCaseId = (id) => {
2131
2139
  if (!id || typeof id !== "string") return id;
2132
- const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
2133
- if (isAlreadyClean) return id;
2140
+ if ((/^[a-z][a-zA-Z0-9]*$/.test(id) || /^a\d[a-zA-Z0-9]*$/.test(id)) && id.length <= MAX_LENGTH) return id;
2134
2141
  const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
2135
2142
  if (words.length === 0) return "a";
2136
- const result = words.map((word, i) => {
2143
+ let result = words.map((word, i) => {
2137
2144
  const lower = word.toLowerCase();
2138
2145
  return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
2139
2146
  }).join("");
2140
- return /^\d/.test(result) ? "a" + result : result;
2141
- };
2142
-
2143
- // src/utils/genCleanIdForContentTypeAndValuePaths.ts
2144
- var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
2145
- function genShortId(length = 4) {
2146
- let result = "";
2147
- for (let i = 0; i < length; i++) {
2148
- result += CHARS[Math.floor(Math.random() * CHARS.length)];
2149
- }
2150
- return result;
2151
- }
2152
- var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
2153
- if (!text || typeof text !== "string") return text;
2154
- let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
2155
- if (!cleaned) {
2156
- throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
2157
- }
2158
- if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
2159
- const truncated = cleaned.slice(0, maxLength);
2160
- return `${truncated}_${genShortId(shortIdLength)}`;
2147
+ const strippedResult = result.replace(/[^a-zA-Z0-9]/g, "");
2148
+ result = strippedResult || fnv1a(result);
2149
+ if (/^\d/.test(result)) result = "a" + result;
2150
+ return result.slice(0, MAX_LENGTH);
2161
2151
  };
2162
2152
  // Annotate the CommonJS export names for ESM import in node:
2163
2153
  0 && (module.exports = {
@@ -2176,7 +2166,6 @@ var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength
2176
2166
  extractAllBlocksFromTpl,
2177
2167
  extractAndOrganizeBlocks,
2178
2168
  genCleanCamelCaseId,
2179
- genCleanIdForContentTypeAndValuePaths,
2180
2169
  genTagId,
2181
2170
  generateFilterKey,
2182
2171
  getFilterKeyForBlock,
package/dist/browser.mjs CHANGED
@@ -2070,37 +2070,28 @@ var autoGenFilterConfigsFromTpl = ({
2070
2070
  };
2071
2071
 
2072
2072
  // src/utils/genCleanCamelCaseId.ts
2073
+ var MAX_LENGTH = 40;
2074
+ function fnv1a(str, length = 8) {
2075
+ let hash = 2166136261;
2076
+ for (let i = 0; i < str.length; i++) {
2077
+ hash ^= str.charCodeAt(i);
2078
+ hash = hash * 16777619 >>> 0;
2079
+ }
2080
+ return hash.toString(36).slice(0, length);
2081
+ }
2073
2082
  var genCleanCamelCaseId = (id) => {
2074
2083
  if (!id || typeof id !== "string") return id;
2075
- const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
2076
- if (isAlreadyClean) return id;
2084
+ if ((/^[a-z][a-zA-Z0-9]*$/.test(id) || /^a\d[a-zA-Z0-9]*$/.test(id)) && id.length <= MAX_LENGTH) return id;
2077
2085
  const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
2078
2086
  if (words.length === 0) return "a";
2079
- const result = words.map((word, i) => {
2087
+ let result = words.map((word, i) => {
2080
2088
  const lower = word.toLowerCase();
2081
2089
  return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
2082
2090
  }).join("");
2083
- return /^\d/.test(result) ? "a" + result : result;
2084
- };
2085
-
2086
- // src/utils/genCleanIdForContentTypeAndValuePaths.ts
2087
- var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
2088
- function genShortId(length = 4) {
2089
- let result = "";
2090
- for (let i = 0; i < length; i++) {
2091
- result += CHARS[Math.floor(Math.random() * CHARS.length)];
2092
- }
2093
- return result;
2094
- }
2095
- var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
2096
- if (!text || typeof text !== "string") return text;
2097
- let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
2098
- if (!cleaned) {
2099
- throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
2100
- }
2101
- if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
2102
- const truncated = cleaned.slice(0, maxLength);
2103
- return `${truncated}_${genShortId(shortIdLength)}`;
2091
+ const strippedResult = result.replace(/[^a-zA-Z0-9]/g, "");
2092
+ result = strippedResult || fnv1a(result);
2093
+ if (/^\d/.test(result)) result = "a" + result;
2094
+ return result.slice(0, MAX_LENGTH);
2104
2095
  };
2105
2096
  export {
2106
2097
  BASE_BULLMQ_CONFIG,
@@ -2118,7 +2109,6 @@ export {
2118
2109
  extractAllBlocksFromTpl,
2119
2110
  extractAndOrganizeBlocks,
2120
2111
  genCleanCamelCaseId,
2121
- genCleanIdForContentTypeAndValuePaths,
2122
2112
  genTagId,
2123
2113
  generateFilterKey,
2124
2114
  getFilterKeyForBlock,
package/dist/node.d.mts CHANGED
@@ -1267,28 +1267,28 @@ declare const UI_CONTENT: {
1267
1267
  };
1268
1268
  };
1269
1269
 
1270
- declare const genCleanCamelCaseId: (id: string) => string;
1271
-
1272
1270
  /**
1273
- * Generates a clean, short, unique ID from text input.
1274
- * Used for both contentType IDs and block valuePaths.
1271
+ * Generates a clean, deterministic, alphanumeric camelCase ID from text.
1275
1272
  *
1276
- * 1. Strips all characters except A-Z, a-z, 0-9
1277
- * 2. Lowercases the result
1278
- * 3. Prepends 'a' if starts with a digit
1279
- * 4. Truncates to maxLength (default 10)
1280
- * 5. Appends _{random id} (default 4 chars)
1273
+ * 1. Splits on non-alphanumeric characters, builds camelCase
1274
+ * 2. Strips all non a-zA-Z0-9 from result
1275
+ * 3. If input had no unicode letters/numbers at all (e.g. "---"), returns 'a'
1276
+ * 4. If camelCase had content but nothing survived ASCII strip (pure non-Latin),
1277
+ * generates a deterministic hash (FNV-1a) of the unicode camelCase
1278
+ * 5. Prepends 'a' if starts with digit
1279
+ * 6. Truncates to 40 chars
1281
1280
  *
1282
- * @param text - The input text to convert
1283
- * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1284
- * @param shortIdLength - Length of the random suffix (default 4)
1281
+ * Idempotent: running twice produces the same output.
1285
1282
  *
1286
1283
  * @example
1287
- * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1288
- * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1289
- * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1284
+ * genCleanCamelCaseId("Author Name") => "authorName"
1285
+ * genCleanCamelCaseId("authorName") => "authorName" (idempotent)
1286
+ * genCleanCamelCaseId("123 Test") => "a123Test"
1287
+ * genCleanCamelCaseId("café latté") => "cafLatt"
1288
+ * genCleanCamelCaseId("مرحبا") => deterministic hash
1289
+ * genCleanCamelCaseId("---") => "a"
1290
1290
  */
1291
- declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1291
+ declare const genCleanCamelCaseId: (id: string) => string;
1292
1292
 
1293
1293
  declare class MongoConnector {
1294
1294
  static getInstance(): any;
@@ -2020,4 +2020,4 @@ declare function GET_GLOBAL_BULLMQ_CONFIG({ env, redisCredentials }: {
2020
2020
  };
2021
2021
  }): Object;
2022
2022
 
2023
- 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_buildDocHierarchyConfig, _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 };
2023
+ 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_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, 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
@@ -1267,28 +1267,28 @@ declare const UI_CONTENT: {
1267
1267
  };
1268
1268
  };
1269
1269
 
1270
- declare const genCleanCamelCaseId: (id: string) => string;
1271
-
1272
1270
  /**
1273
- * Generates a clean, short, unique ID from text input.
1274
- * Used for both contentType IDs and block valuePaths.
1271
+ * Generates a clean, deterministic, alphanumeric camelCase ID from text.
1275
1272
  *
1276
- * 1. Strips all characters except A-Z, a-z, 0-9
1277
- * 2. Lowercases the result
1278
- * 3. Prepends 'a' if starts with a digit
1279
- * 4. Truncates to maxLength (default 10)
1280
- * 5. Appends _{random id} (default 4 chars)
1273
+ * 1. Splits on non-alphanumeric characters, builds camelCase
1274
+ * 2. Strips all non a-zA-Z0-9 from result
1275
+ * 3. If input had no unicode letters/numbers at all (e.g. "---"), returns 'a'
1276
+ * 4. If camelCase had content but nothing survived ASCII strip (pure non-Latin),
1277
+ * generates a deterministic hash (FNV-1a) of the unicode camelCase
1278
+ * 5. Prepends 'a' if starts with digit
1279
+ * 6. Truncates to 40 chars
1281
1280
  *
1282
- * @param text - The input text to convert
1283
- * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1284
- * @param shortIdLength - Length of the random suffix (default 4)
1281
+ * Idempotent: running twice produces the same output.
1285
1282
  *
1286
1283
  * @example
1287
- * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1288
- * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1289
- * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1284
+ * genCleanCamelCaseId("Author Name") => "authorName"
1285
+ * genCleanCamelCaseId("authorName") => "authorName" (idempotent)
1286
+ * genCleanCamelCaseId("123 Test") => "a123Test"
1287
+ * genCleanCamelCaseId("café latté") => "cafLatt"
1288
+ * genCleanCamelCaseId("مرحبا") => deterministic hash
1289
+ * genCleanCamelCaseId("---") => "a"
1290
1290
  */
1291
- declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1291
+ declare const genCleanCamelCaseId: (id: string) => string;
1292
1292
 
1293
1293
  declare class MongoConnector {
1294
1294
  static getInstance(): any;
@@ -2020,4 +2020,4 @@ declare function GET_GLOBAL_BULLMQ_CONFIG({ env, redisCredentials }: {
2020
2020
  };
2021
2021
  }): Object;
2022
2022
 
2023
- 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_buildDocHierarchyConfig, _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 };
2023
+ 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_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, 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
@@ -1949,7 +1949,6 @@ __export(node_exports, {
1949
1949
  extractAllBlocksFromTpl: () => extractAllBlocksFromTpl,
1950
1950
  extractAndOrganizeBlocks: () => extractAndOrganizeBlocks,
1951
1951
  genCleanCamelCaseId: () => genCleanCamelCaseId,
1952
- genCleanIdForContentTypeAndValuePaths: () => genCleanIdForContentTypeAndValuePaths,
1953
1952
  genTagId: () => genTagId,
1954
1953
  generateFilterKey: () => generateFilterKey,
1955
1954
  getAIChatModelByTenant: () => import_getModelByTenant2.getAIChatModelByTenant,
@@ -3721,37 +3720,28 @@ var autoGenFilterConfigsFromTpl = ({
3721
3720
  };
3722
3721
 
3723
3722
  // src/utils/genCleanCamelCaseId.ts
3723
+ var MAX_LENGTH = 40;
3724
+ function fnv1a(str, length = 8) {
3725
+ let hash = 2166136261;
3726
+ for (let i = 0; i < str.length; i++) {
3727
+ hash ^= str.charCodeAt(i);
3728
+ hash = hash * 16777619 >>> 0;
3729
+ }
3730
+ return hash.toString(36).slice(0, length);
3731
+ }
3724
3732
  var genCleanCamelCaseId = (id) => {
3725
3733
  if (!id || typeof id !== "string") return id;
3726
- const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
3727
- if (isAlreadyClean) return id;
3734
+ if ((/^[a-z][a-zA-Z0-9]*$/.test(id) || /^a\d[a-zA-Z0-9]*$/.test(id)) && id.length <= MAX_LENGTH) return id;
3728
3735
  const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
3729
3736
  if (words.length === 0) return "a";
3730
- const result = words.map((word, i) => {
3737
+ let result = words.map((word, i) => {
3731
3738
  const lower = word.toLowerCase();
3732
3739
  return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
3733
3740
  }).join("");
3734
- return /^\d/.test(result) ? "a" + result : result;
3735
- };
3736
-
3737
- // src/utils/genCleanIdForContentTypeAndValuePaths.ts
3738
- var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
3739
- function genShortId(length = 4) {
3740
- let result = "";
3741
- for (let i = 0; i < length; i++) {
3742
- result += CHARS[Math.floor(Math.random() * CHARS.length)];
3743
- }
3744
- return result;
3745
- }
3746
- var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
3747
- if (!text || typeof text !== "string") return text;
3748
- let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
3749
- if (!cleaned) {
3750
- throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
3751
- }
3752
- if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
3753
- const truncated = cleaned.slice(0, maxLength);
3754
- return `${truncated}_${genShortId(shortIdLength)}`;
3741
+ const strippedResult = result.replace(/[^a-zA-Z0-9]/g, "");
3742
+ result = strippedResult || fnv1a(result);
3743
+ if (/^\d/.test(result)) result = "a" + result;
3744
+ return result.slice(0, MAX_LENGTH);
3755
3745
  };
3756
3746
 
3757
3747
  // src/node.ts
@@ -4171,7 +4161,6 @@ var import_GET_GLOBAL_BULLMQ_CONFIG = __toESM(require_GET_GLOBAL_BULLMQ_CONFIG()
4171
4161
  extractAllBlocksFromTpl,
4172
4162
  extractAndOrganizeBlocks,
4173
4163
  genCleanCamelCaseId,
4174
- genCleanIdForContentTypeAndValuePaths,
4175
4164
  genTagId,
4176
4165
  generateFilterKey,
4177
4166
  getAIChatModelByTenant,
package/dist/node.mjs CHANGED
@@ -3663,37 +3663,28 @@ var autoGenFilterConfigsFromTpl = ({
3663
3663
  };
3664
3664
 
3665
3665
  // src/utils/genCleanCamelCaseId.ts
3666
+ var MAX_LENGTH = 40;
3667
+ function fnv1a(str, length = 8) {
3668
+ let hash = 2166136261;
3669
+ for (let i = 0; i < str.length; i++) {
3670
+ hash ^= str.charCodeAt(i);
3671
+ hash = hash * 16777619 >>> 0;
3672
+ }
3673
+ return hash.toString(36).slice(0, length);
3674
+ }
3666
3675
  var genCleanCamelCaseId = (id) => {
3667
3676
  if (!id || typeof id !== "string") return id;
3668
- const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
3669
- if (isAlreadyClean) return id;
3677
+ if ((/^[a-z][a-zA-Z0-9]*$/.test(id) || /^a\d[a-zA-Z0-9]*$/.test(id)) && id.length <= MAX_LENGTH) return id;
3670
3678
  const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
3671
3679
  if (words.length === 0) return "a";
3672
- const result = words.map((word, i) => {
3680
+ let result = words.map((word, i) => {
3673
3681
  const lower = word.toLowerCase();
3674
3682
  return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
3675
3683
  }).join("");
3676
- return /^\d/.test(result) ? "a" + result : result;
3677
- };
3678
-
3679
- // src/utils/genCleanIdForContentTypeAndValuePaths.ts
3680
- var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
3681
- function genShortId(length = 4) {
3682
- let result = "";
3683
- for (let i = 0; i < length; i++) {
3684
- result += CHARS[Math.floor(Math.random() * CHARS.length)];
3685
- }
3686
- return result;
3687
- }
3688
- var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
3689
- if (!text || typeof text !== "string") return text;
3690
- let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
3691
- if (!cleaned) {
3692
- throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
3693
- }
3694
- if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
3695
- const truncated = cleaned.slice(0, maxLength);
3696
- return `${truncated}_${genShortId(shortIdLength)}`;
3684
+ const strippedResult = result.replace(/[^a-zA-Z0-9]/g, "");
3685
+ result = strippedResult || fnv1a(result);
3686
+ if (/^\d/.test(result)) result = "a" + result;
3687
+ return result.slice(0, MAX_LENGTH);
3697
3688
  };
3698
3689
 
3699
3690
  // src/node.ts
@@ -4128,7 +4119,6 @@ export {
4128
4119
  extractAllBlocksFromTpl,
4129
4120
  extractAndOrganizeBlocks,
4130
4121
  genCleanCamelCaseId,
4131
- genCleanIdForContentTypeAndValuePaths,
4132
4122
  genTagId,
4133
4123
  generateFilterKey,
4134
4124
  export_getAIChatModelByTenant as getAIChatModelByTenant,
@@ -1260,27 +1260,27 @@ declare const UI_CONTENT: {
1260
1260
  };
1261
1261
  };
1262
1262
 
1263
- declare const genCleanCamelCaseId: (id: string) => string;
1264
-
1265
1263
  /**
1266
- * Generates a clean, short, unique ID from text input.
1267
- * Used for both contentType IDs and block valuePaths.
1264
+ * Generates a clean, deterministic, alphanumeric camelCase ID from text.
1268
1265
  *
1269
- * 1. Strips all characters except A-Z, a-z, 0-9
1270
- * 2. Lowercases the result
1271
- * 3. Prepends 'a' if starts with a digit
1272
- * 4. Truncates to maxLength (default 10)
1273
- * 5. Appends _{random id} (default 4 chars)
1266
+ * 1. Splits on non-alphanumeric characters, builds camelCase
1267
+ * 2. Strips all non a-zA-Z0-9 from result
1268
+ * 3. If input had no unicode letters/numbers at all (e.g. "---"), returns 'a'
1269
+ * 4. If camelCase had content but nothing survived ASCII strip (pure non-Latin),
1270
+ * generates a deterministic hash (FNV-1a) of the unicode camelCase
1271
+ * 5. Prepends 'a' if starts with digit
1272
+ * 6. Truncates to 40 chars
1274
1273
  *
1275
- * @param text - The input text to convert
1276
- * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1277
- * @param shortIdLength - Length of the random suffix (default 4)
1274
+ * Idempotent: running twice produces the same output.
1278
1275
  *
1279
1276
  * @example
1280
- * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1281
- * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1282
- * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1277
+ * genCleanCamelCaseId("Author Name") => "authorName"
1278
+ * genCleanCamelCaseId("authorName") => "authorName" (idempotent)
1279
+ * genCleanCamelCaseId("123 Test") => "a123Test"
1280
+ * genCleanCamelCaseId("café latté") => "cafLatt"
1281
+ * genCleanCamelCaseId("مرحبا") => deterministic hash
1282
+ * genCleanCamelCaseId("---") => "a"
1283
1283
  */
1284
- declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1284
+ declare const genCleanCamelCaseId: (id: string) => string;
1285
1285
 
1286
- export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _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 };
1286
+ export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
@@ -1260,27 +1260,27 @@ declare const UI_CONTENT: {
1260
1260
  };
1261
1261
  };
1262
1262
 
1263
- declare const genCleanCamelCaseId: (id: string) => string;
1264
-
1265
1263
  /**
1266
- * Generates a clean, short, unique ID from text input.
1267
- * Used for both contentType IDs and block valuePaths.
1264
+ * Generates a clean, deterministic, alphanumeric camelCase ID from text.
1268
1265
  *
1269
- * 1. Strips all characters except A-Z, a-z, 0-9
1270
- * 2. Lowercases the result
1271
- * 3. Prepends 'a' if starts with a digit
1272
- * 4. Truncates to maxLength (default 10)
1273
- * 5. Appends _{random id} (default 4 chars)
1266
+ * 1. Splits on non-alphanumeric characters, builds camelCase
1267
+ * 2. Strips all non a-zA-Z0-9 from result
1268
+ * 3. If input had no unicode letters/numbers at all (e.g. "---"), returns 'a'
1269
+ * 4. If camelCase had content but nothing survived ASCII strip (pure non-Latin),
1270
+ * generates a deterministic hash (FNV-1a) of the unicode camelCase
1271
+ * 5. Prepends 'a' if starts with digit
1272
+ * 6. Truncates to 40 chars
1274
1273
  *
1275
- * @param text - The input text to convert
1276
- * @param maxLength - Max characters before the random suffix (default 10, use 20 for contentType)
1277
- * @param shortIdLength - Length of the random suffix (default 4)
1274
+ * Idempotent: running twice produces the same output.
1278
1275
  *
1279
1276
  * @example
1280
- * genCleanIdForContentTypeAndValuePaths("Author Name") => "authorname_x7k2"
1281
- * genCleanIdForContentTypeAndValuePaths("My Articles!", 20) => "myarticles_m3p1"
1282
- * genCleanIdForContentTypeAndValuePaths("123 Test") => "a123test_ab4d"
1277
+ * genCleanCamelCaseId("Author Name") => "authorName"
1278
+ * genCleanCamelCaseId("authorName") => "authorName" (idempotent)
1279
+ * genCleanCamelCaseId("123 Test") => "a123Test"
1280
+ * genCleanCamelCaseId("café latté") => "cafLatt"
1281
+ * genCleanCamelCaseId("مرحبا") => deterministic hash
1282
+ * genCleanCamelCaseId("---") => "a"
1283
1283
  */
1284
- declare const genCleanIdForContentTypeAndValuePaths: (text: string, maxLength?: number, shortIdLength?: number) => string;
1284
+ declare const genCleanCamelCaseId: (id: string) => string;
1285
1285
 
1286
- export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _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 };
1286
+ export { BASE_BULLMQ_CONFIG, FILTER_IDS, TEMP_removeDuplicateFilters, UI_CONTENT, _self_managed_buildAnnoHierarchyConfig, _self_managed_buildDocHierarchyConfig, _self_managed_getFixedAnnoRollupBlocks, _self_managed_getFixedAnnoTagBlock, autoGenFilterConfigsFromTpl, buildFilterConfigurations, compareAndGroupBlocks, deleteVal, extractAllBlocksFromTpl, extractAndOrganizeBlocks, genCleanCamelCaseId, genTagId, generateFilterKey, getFilterKeyForBlock, getPlatformContextContent, getRollupPossibilities, getRoutePathToEditContent, getRoutePathToModerateContent, getRoutePathToPublishedContent, getVal, mergeAnnoDataIntoAnnotationsTags, parseSpecialConfigSyntax, processAuthorAndCommonFilters, _recursExtractBlocks as recursivelyExtractBlocks, segrigateDocs, setVal, toArray };
package/dist/universal.js CHANGED
@@ -35,7 +35,6 @@ __export(universal_exports, {
35
35
  extractAllBlocksFromTpl: () => extractAllBlocksFromTpl,
36
36
  extractAndOrganizeBlocks: () => extractAndOrganizeBlocks,
37
37
  genCleanCamelCaseId: () => genCleanCamelCaseId,
38
- genCleanIdForContentTypeAndValuePaths: () => genCleanIdForContentTypeAndValuePaths,
39
38
  genTagId: () => genTagId,
40
39
  generateFilterKey: () => generateFilterKey,
41
40
  getFilterKeyForBlock: () => getFilterKeyForBlock,
@@ -2127,37 +2126,28 @@ var autoGenFilterConfigsFromTpl = ({
2127
2126
  };
2128
2127
 
2129
2128
  // src/utils/genCleanCamelCaseId.ts
2129
+ var MAX_LENGTH = 40;
2130
+ function fnv1a(str, length = 8) {
2131
+ let hash = 2166136261;
2132
+ for (let i = 0; i < str.length; i++) {
2133
+ hash ^= str.charCodeAt(i);
2134
+ hash = hash * 16777619 >>> 0;
2135
+ }
2136
+ return hash.toString(36).slice(0, length);
2137
+ }
2130
2138
  var genCleanCamelCaseId = (id) => {
2131
2139
  if (!id || typeof id !== "string") return id;
2132
- const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
2133
- if (isAlreadyClean) return id;
2140
+ if ((/^[a-z][a-zA-Z0-9]*$/.test(id) || /^a\d[a-zA-Z0-9]*$/.test(id)) && id.length <= MAX_LENGTH) return id;
2134
2141
  const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
2135
2142
  if (words.length === 0) return "a";
2136
- const result = words.map((word, i) => {
2143
+ let result = words.map((word, i) => {
2137
2144
  const lower = word.toLowerCase();
2138
2145
  return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
2139
2146
  }).join("");
2140
- return /^\d/.test(result) ? "a" + result : result;
2141
- };
2142
-
2143
- // src/utils/genCleanIdForContentTypeAndValuePaths.ts
2144
- var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
2145
- function genShortId(length = 4) {
2146
- let result = "";
2147
- for (let i = 0; i < length; i++) {
2148
- result += CHARS[Math.floor(Math.random() * CHARS.length)];
2149
- }
2150
- return result;
2151
- }
2152
- var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
2153
- if (!text || typeof text !== "string") return text;
2154
- let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
2155
- if (!cleaned) {
2156
- throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
2157
- }
2158
- if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
2159
- const truncated = cleaned.slice(0, maxLength);
2160
- return `${truncated}_${genShortId(shortIdLength)}`;
2147
+ const strippedResult = result.replace(/[^a-zA-Z0-9]/g, "");
2148
+ result = strippedResult || fnv1a(result);
2149
+ if (/^\d/.test(result)) result = "a" + result;
2150
+ return result.slice(0, MAX_LENGTH);
2161
2151
  };
2162
2152
  // Annotate the CommonJS export names for ESM import in node:
2163
2153
  0 && (module.exports = {
@@ -2176,7 +2166,6 @@ var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength
2176
2166
  extractAllBlocksFromTpl,
2177
2167
  extractAndOrganizeBlocks,
2178
2168
  genCleanCamelCaseId,
2179
- genCleanIdForContentTypeAndValuePaths,
2180
2169
  genTagId,
2181
2170
  generateFilterKey,
2182
2171
  getFilterKeyForBlock,
@@ -2070,37 +2070,28 @@ var autoGenFilterConfigsFromTpl = ({
2070
2070
  };
2071
2071
 
2072
2072
  // src/utils/genCleanCamelCaseId.ts
2073
+ var MAX_LENGTH = 40;
2074
+ function fnv1a(str, length = 8) {
2075
+ let hash = 2166136261;
2076
+ for (let i = 0; i < str.length; i++) {
2077
+ hash ^= str.charCodeAt(i);
2078
+ hash = hash * 16777619 >>> 0;
2079
+ }
2080
+ return hash.toString(36).slice(0, length);
2081
+ }
2073
2082
  var genCleanCamelCaseId = (id) => {
2074
2083
  if (!id || typeof id !== "string") return id;
2075
- const isAlreadyClean = /^\p{Ll}[\p{L}\p{N}]*$/u.test(id) || /^a\d[\p{L}\p{N}]*$/u.test(id);
2076
- if (isAlreadyClean) return id;
2084
+ if ((/^[a-z][a-zA-Z0-9]*$/.test(id) || /^a\d[a-zA-Z0-9]*$/.test(id)) && id.length <= MAX_LENGTH) return id;
2077
2085
  const words = id.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
2078
2086
  if (words.length === 0) return "a";
2079
- const result = words.map((word, i) => {
2087
+ let result = words.map((word, i) => {
2080
2088
  const lower = word.toLowerCase();
2081
2089
  return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
2082
2090
  }).join("");
2083
- return /^\d/.test(result) ? "a" + result : result;
2084
- };
2085
-
2086
- // src/utils/genCleanIdForContentTypeAndValuePaths.ts
2087
- var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
2088
- function genShortId(length = 4) {
2089
- let result = "";
2090
- for (let i = 0; i < length; i++) {
2091
- result += CHARS[Math.floor(Math.random() * CHARS.length)];
2092
- }
2093
- return result;
2094
- }
2095
- var genCleanIdForContentTypeAndValuePaths = (text, maxLength = 10, shortIdLength = 4) => {
2096
- if (!text || typeof text !== "string") return text;
2097
- let cleaned = text.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
2098
- if (!cleaned) {
2099
- throw new Error(`[genCleanIdForContentTypeAndValuePaths] Input "${text}" contains no alphanumeric characters`);
2100
- }
2101
- if (/^\d/.test(cleaned)) cleaned = "a" + cleaned;
2102
- const truncated = cleaned.slice(0, maxLength);
2103
- return `${truncated}_${genShortId(shortIdLength)}`;
2091
+ const strippedResult = result.replace(/[^a-zA-Z0-9]/g, "");
2092
+ result = strippedResult || fnv1a(result);
2093
+ if (/^\d/.test(result)) result = "a" + result;
2094
+ return result.slice(0, MAX_LENGTH);
2104
2095
  };
2105
2096
  export {
2106
2097
  BASE_BULLMQ_CONFIG,
@@ -2118,7 +2109,6 @@ export {
2118
2109
  extractAllBlocksFromTpl,
2119
2110
  extractAndOrganizeBlocks,
2120
2111
  genCleanCamelCaseId,
2121
- genCleanIdForContentTypeAndValuePaths,
2122
2112
  genTagId,
2123
2113
  generateFilterKey,
2124
2114
  getFilterKeyForBlock,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.28.0",
6
+ "version": "1.28.2",
7
7
  "description": "Utility functions for both browser and Node.js",
8
8
  "main": "dist/index.js",
9
9
  "module": "dist/index.mjs",